Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Use `lastCommit` of each blob for navigation instead of patch revision
Sebastian Martinez committed 2 years ago
commit 9b15911f83c6ccb902b996ef30426f959d249411
parent fb06b5fe8b24f70d65b987afbaf0a7e8352a0357
8 files changed +56 -44
modified httpd-client/index.ts
@@ -1,6 +1,7 @@
import type { BaseUrl } from "./lib/fetcher.js";
import type {
  Blob,
+
  CommitBlob,
  Project,
  Remote,
  Tree,
@@ -41,6 +42,7 @@ export type {
  CodeLocation,
  Comment,
  Commit,
+
  CommitBlob,
  CommitHeader,
  Diff,
  DiffContent,
modified httpd-client/lib/project.ts
@@ -1,4 +1,4 @@
-
import type { Commit, CommitHeader, Commits, Diff } from "./project/commit.js";
+
import type { Commit, Commits } from "./project/commit.js";
import type { Fetcher, RequestOptions } from "./fetcher.js";
import type {
  Issue,
@@ -86,6 +86,14 @@ const blobSchema = object({

export type Blob = z.infer<typeof blobSchema>;

+
const commitBlobSchema = object({
+
  binary: boolean(),
+
  content: optional(string()),
+
  lastCommit: commitHeaderSchema,
+
});
+

+
export type CommitBlob = z.infer<typeof commitBlobSchema>;
+

const treeEntrySchema = object({
  path: string(),
  name: string(),
@@ -100,13 +108,7 @@ export interface TreeStats {
  contributors: number;
}

-
export interface Tree {
-
  entries: TreeEntry[];
-
  lastCommit: CommitHeader;
-
  name: string;
-
  path: string;
-
  stats: TreeStats;
-
}
+
export type Tree = z.infer<typeof treeSchema>;

const treeSchema = object({
  entries: array(treeEntrySchema),
@@ -118,33 +120,26 @@ const treeSchema = object({
    branches: number(),
    contributors: number(),
  }),
-
}) satisfies ZodSchema<Tree>;
+
});

-
export interface Remote {
-
  id: string;
-
  alias?: string;
-
  heads: Record<string, string>;
-
  delegate: boolean;
-
}
+
export type Remote = z.infer<typeof remoteSchema>;

const remoteSchema = object({
  id: string(),
  alias: string().optional(),
  heads: record(string(), string()),
  delegate: boolean(),
-
}) satisfies ZodSchema<Remote>;
+
});

const remotesSchema = array(remoteSchema) satisfies ZodSchema<Remote[]>;

-
export interface DiffResponse {
-
  commits: CommitHeader[];
-
  diff: Diff;
-
}
+
export type DiffResponse = z.infer<typeof diffResponseSchema>;

const diffResponseSchema = object({
  commits: array(commitHeaderSchema),
  diff: diffSchema,
-
}) satisfies ZodSchema<DiffResponse>;
+
  files: record(string(), commitBlobSchema),
+
});

export class Client {
  #fetcher: Fetcher;
modified src/views/projects/Changeset.svelte
@@ -1,5 +1,5 @@
<script lang="ts">
-
  import type { BaseUrl, Diff } from "@httpd-client";
+
  import type { BaseUrl, CommitBlob, Diff } from "@httpd-client";

  import { pluralize } from "@app/lib/pluralize";

@@ -7,7 +7,10 @@
  import FileLocationChange from "@app/views/projects/Changeset/FileLocationChange.svelte";

  export let diff: Diff;
-
  export let revision: string;
+
  // This only is needed in commit view where we have a useful revision.
+
  export let revision: string | undefined = undefined;
+
  // This only is needed for patch changesets where we have different files with different last commits.
+
  export let files: Record<string, CommitBlob> = {};
  export let baseUrl: BaseUrl;
  export let projectId: string;

@@ -72,7 +75,7 @@
    <FileDiff
      {projectId}
      {baseUrl}
-
      {revision}
+
      revision={revision ?? files[file.new.oid].lastCommit.id}
      filePath={file.path}
      fileDiff={file.diff}
      headerBadgeCaption="added" />
@@ -81,7 +84,7 @@
    <FileDiff
      {projectId}
      {baseUrl}
-
      {revision}
+
      revision={revision ?? files[file.old.oid].lastCommit.id}
      filePath={file.path}
      fileDiff={file.diff}
      headerBadgeCaption="deleted" />
@@ -90,7 +93,7 @@
    <FileDiff
      {projectId}
      {baseUrl}
-
      {revision}
+
      revision={revision ?? files[file.new.oid].lastCommit.id}
      filePath={file.path}
      fileDiff={file.diff} />
  {/each}
@@ -108,7 +111,6 @@
      <FileLocationChange
        {projectId}
        {baseUrl}
-
        {revision}
        newPath={file.newPath}
        oldPath={file.oldPath}
        mode="moved" />
@@ -118,7 +120,6 @@
    <FileLocationChange
      {projectId}
      {baseUrl}
-
      {revision}
      newPath={file.newPath}
      oldPath={file.oldPath}
      mode="copied" />
modified src/views/projects/Changeset/FileDiff.svelte
@@ -9,7 +9,7 @@
  export let filePath: string;
  export let oldFilePath: string | undefined = undefined;
  export let fileDiff: DiffContent;
-
  export let revision: string;
+
  export let revision: string | undefined = undefined;
  export let headerBadgeCaption:
    | "added"
    | "deleted"
@@ -345,18 +345,20 @@
        <Badge variant="foreground">copied</Badge>
      {/if}
    </div>
-
    <div class="browse" title="View file">
-
      <Link
-
        route={{
-
          resource: "project.source",
-
          project: projectId,
-
          node: baseUrl,
-
          path: filePath,
-
          revision,
-
        }}>
-
        <Icon name="browse" />
-
      </Link>
-
    </div>
+
    {#if revision}
+
      <div class="browse" title="View file">
+
        <Link
+
          route={{
+
            resource: "project.source",
+
            project: projectId,
+
            node: baseUrl,
+
            path: filePath,
+
            revision,
+
          }}>
+
          <Icon name="browse" />
+
        </Link>
+
      </div>
+
    {/if}
  </header>
  {#if !collapsed}
    <main>
modified src/views/projects/Changeset/FileLocationChange.svelte
@@ -7,7 +7,7 @@

  export let newPath: string;
  export let oldPath: string;
-
  export let revision: string;
+
  export let revision: string | undefined = undefined;
  export let mode: "moved" | "copied";
  export let baseUrl: BaseUrl;
  export let projectId: string;
modified src/views/projects/Patch.svelte
@@ -587,7 +587,7 @@
          <Changeset
            projectId={project.id}
            {baseUrl}
-
            revision={view.revision}
+
            files={view.files}
            diff={view.diff} />
        </div>
      {:else}
modified src/views/projects/router.ts
@@ -6,6 +6,7 @@ import type {
  BaseUrl,
  Blob,
  Commit,
+
  CommitBlob,
  CommitHeader,
  Diff,
  Issue,
@@ -197,6 +198,7 @@ export type PatchView =
      revision: string;
      diff: Diff;
      commits: CommitHeader[];
+
      files: Record<string, CommitBlob>;
    }
  | {
      name: "diff";
@@ -537,7 +539,7 @@ async function loadPatchView(
          `revision ${revisionId} of patch ${route.patch} not found`,
        );
      }
-
      const { diff, commits } = await api.project.getDiff(
+
      const { diff, commits, files } = await api.project.getDiff(
        route.project,
        revision.base,
        revision.oid,
@@ -547,6 +549,7 @@ async function loadPatchView(
        revision: revision.id,
        diff,
        commits,
+
        files,
      };
      break;
    }
modified tests/e2e/project/patches.spec.ts
@@ -301,3 +301,12 @@ test("navigate through revision diffs", async ({ page }) => {
    );
  }
});
+

+
test("view file navigation from files tab", async ({ page }) => {
+
  await page.goto(`${cobUrl}/patches/687c3268119d23c5da32055c0b44c03e0e4088b8`);
+
  await page.getByRole("button", { name: "Files" }).click();
+
  await page.getByTitle("View file").getByRole("link").click();
+
  await expect(page).toHaveURL(
+
    `${cobUrl}/tree/9898da6155467adad511f63bf0fb5aa4156b92ef/README.md`,
+
  );
+
});