Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Simplify project view component
Rūdolfs Ošiņš committed 2 years ago
commit d4650ab482129795fb0db690abb3c495dc37751e
parent 7dab02c273441a7712d7bed1e353c1706665ad9a
6 files changed +132 -142
modified src/views/projects/Issue/New.svelte
@@ -1,10 +1,9 @@
-
<script lang="ts" strictEvents>
+
<script lang="ts">
  import type { BaseUrl } from "@httpd-client";
-
  import type { Session } from "@app/lib/httpd";
-

-
  import { createEventDispatcher } from "svelte";

+
  import * as httpd from "@app/lib/httpd";
  import * as modal from "@app/lib/modal";
+
  import * as router from "@app/lib/router";
  import * as utils from "@app/lib/utils";
  import { HttpdClient } from "@httpd-client";
  import { httpdStore } from "@app/lib/httpd";
@@ -18,13 +17,12 @@
  import Markdown from "@app/components/Markdown.svelte";
  import TagInput from "@app/views/projects/Cob/TagInput.svelte";
  import Textarea from "@app/components/Textarea.svelte";
+
  import ErrorMessage from "@app/components/ErrorMessage.svelte";

-
  export let session: Session;
  export let projectId: string;
  export let projectHead: string;
  export let baseUrl: BaseUrl;

-
  const dispatch = createEventDispatcher<{ create: string }>();
  let preview: boolean = false;
  let action: "create" | "view";
  $: action =
@@ -41,7 +39,7 @@

  const api = new HttpdClient(baseUrl);

-
  async function createIssue() {
+
  async function createIssue(sessionId: string) {
    try {
      const result = await api.project.createIssue(
        projectId,
@@ -51,9 +49,20 @@
          assignees: utils.stripDidPrefix(assignees),
          tags: tags,
        },
-
        session.id,
+
        sessionId,
      );
-
      dispatch("create", result.id);
+

+
      void router.push({
+
        resource: "projects",
+
        params: {
+
          id: projectId,
+
          hostAndPort: httpd.api.hostAndPort,
+
          view: {
+
            resource: "issue",
+
            params: { issue: result.id },
+
          },
+
        },
+
      });
    } catch {
      modal.show({
        component: AuthenticationErrorModal,
@@ -123,63 +132,75 @@
</style>

<main>
-
  <div class="form">
-
    <div class="editor">
-
      <CobHeader {action} bind:title={issueTitle}>
-
        <svelte:fragment slot="state">
-
          {#if action === "view"}
-
            <Badge variant="positive">open</Badge>
-
          {/if}
-
        </svelte:fragment>
-
        <svelte:fragment slot="description">
-
          {#if action === "create"}
-
            <Textarea
-
              resizable
-
              bind:value={issueText}
-
              on:submit={createIssue}
-
              placeholder="Write a description" />
-
          {:else if !issueText}
-
            <p class="txt-missing">No description</p>
-
          {:else}
-
            <Markdown
-
              content={issueText}
-
              rawPath={utils.getRawBasePath(projectId, baseUrl, projectHead)} />
-
          {/if}
-
        </svelte:fragment>
-
        <div class="author" slot="author">
-
          {#if action === "view"}
-
            opened by <Authorship authorId={session.publicKey} /> now
-
          {/if}
+
  {#if $httpdStore.state === "authenticated"}
+
    {@const session = $httpdStore.session}
+
    <div class="form">
+
      <div class="editor">
+
        <CobHeader {action} bind:title={issueTitle}>
+
          <svelte:fragment slot="state">
+
            {#if action === "view"}
+
              <Badge variant="positive">open</Badge>
+
            {/if}
+
          </svelte:fragment>
+
          <svelte:fragment slot="description">
+
            {#if action === "create"}
+
              <Textarea
+
                resizable
+
                bind:value={issueText}
+
                on:submit={() => {
+
                  void createIssue(session.id);
+
                }}
+
                placeholder="Write a description" />
+
            {:else if !issueText}
+
              <p class="txt-missing">No description</p>
+
            {:else}
+
              <Markdown
+
                content={issueText}
+
                rawPath={utils.getRawBasePath(
+
                  projectId,
+
                  baseUrl,
+
                  projectHead,
+
                )} />
+
            {/if}
+
          </svelte:fragment>
+
          <div class="author" slot="author">
+
            {#if action === "view"}
+
              opened by <Authorship authorId={$httpdStore.session.publicKey} /> now
+
            {/if}
+
          </div>
+
        </CobHeader>
+
        <div class="actions">
+
          <Button
+
            size="small"
+
            variant="text"
+
            on:click={() => (preview = !preview)}>
+
            {#if preview}
+
              Resume editing
+
            {:else}
+
              Preview
+
            {/if}
+
          </Button>
+
          <Button
+
            disabled={!issueTitle}
+
            size="small"
+
            variant="secondary"
+
            on:click={() => void createIssue(session.id)}>
+
            Submit
+
          </Button>
        </div>
-
      </CobHeader>
-
      <div class="actions">
-
        <Button
-
          size="small"
-
          variant="text"
-
          on:click={() => (preview = !preview)}>
-
          {#if preview}
-
            Resume editing
-
          {:else}
-
            Preview
-
          {/if}
-
        </Button>
-
        <Button
-
          disabled={!issueTitle}
-
          size="small"
-
          variant="secondary"
-
          on:click={createIssue}>
-
          Submit
-
        </Button>
+
      </div>
+
      <div class="metadata">
+
        <AssigneeInput
+
          {action}
+
          on:save={({ detail: updatedAssignees }) =>
+
            (assignees = updatedAssignees)} />
+
        <TagInput
+
          {action}
+
          on:save={({ detail: updatedTags }) => (tags = updatedTags)} />
      </div>
    </div>
-
    <div class="metadata">
-
      <AssigneeInput
-
        {action}
-
        on:save={({ detail: updatedAssignees }) =>
-
          (assignees = updatedAssignees)} />
-
      <TagInput
-
        {action}
-
        on:save={({ detail: updatedTags }) => (tags = updatedTags)} />
-
    </div>
-
  </div>
+
  {:else}
+
    <ErrorMessage
+
      message="Couldn't access issue creation. Make sure you're still logged in." />
+
  {/if}
</main>
modified src/views/projects/Issues.svelte
@@ -21,11 +21,14 @@
  import ProjectLink from "@app/components/ProjectLink.svelte";
  import SquareButton from "@app/components/SquareButton.svelte";

+
  export let search: string | undefined = undefined;
  export let projectId: string;
-
  export let state: IssueStatus;
  export let baseUrl: BaseUrl;
  export let issueCounters: { open: number; closed: number };

+
  $: searchParams = new URLSearchParams(search || "");
+
  $: state = (searchParams.get("state") as IssueStatus) || "open";
+

  const perPage = 10;

  let loading = false;
modified src/views/projects/Patch.svelte
@@ -63,14 +63,18 @@
  import SquareButton from "@app/components/SquareButton.svelte";
  import TagInput from "@app/views/projects/Cob/TagInput.svelte";

+
  export let search: string | undefined = undefined;
  export let projectId: string;
  export let baseUrl: BaseUrl;
  export let patch: Patch;
  export let projectHead: string;
  export let projectDefaultBranch: string;
-
  export let revision: string;
-
  export let currentTab: "activity" | "commits" | "files";
-
  export let diff: string | undefined = undefined;
+
  export let revision: string | undefined = undefined;
+

+
  $: searchParams = new URLSearchParams(search || "");
+
  $: currentTab =
+
    (searchParams.get("tab") as "activity" | "commits" | "files") || "activity";
+
  $: diff = searchParams.get("diff") || undefined;

  const api = new HttpdClient(baseUrl);

@@ -136,7 +140,8 @@
  }));

  $: currentRevision =
-
    patch.revisions.find(r => r.id === revision) || patch.revisions[0];
+
    (revision && patch.revisions.find(r => r.id === revision)) ||
+
    patch.revisions[patch.revisions.length - 1];
  $: timelineTuple = patch.revisions.map<
    [
      {
modified src/views/projects/Patches.svelte
@@ -18,8 +18,8 @@
  import ProjectLink from "@app/components/ProjectLink.svelte";
  import SquareButton from "@app/components/SquareButton.svelte";

+
  export let search: string | undefined = undefined;
  export let projectId: string;
-
  export let state: PatchStatus;
  export let baseUrl: BaseUrl;
  export let patchCounters: {
    draft: number;
@@ -28,6 +28,9 @@
    merged: number;
  };

+
  $: searchParams = new URLSearchParams(search || "");
+
  $: state = (searchParams.get("state") as PatchStatus) || "open";
+

  const perPage = 10;

  let loading = false;
modified src/views/projects/View.svelte
@@ -1,18 +1,10 @@
<script lang="ts">
-
  import type { IssueStatus } from "./Issues.svelte";
-
  import type { PatchStatus } from "./Patches.svelte";
  import type { Project } from "@httpd-client";
  import type { ProjectLoadedView } from "@app/views/projects/router";

-
  import * as httpd from "@app/lib/httpd";
-
  import * as router from "@app/lib/router";
  import * as utils from "@app/lib/utils";
-
  import { HttpdClient } from "@httpd-client";
  import { unreachable } from "@app/lib/utils";
-
  import { httpdStore } from "@app/lib/httpd";

-
  import Loading from "@app/components/Loading.svelte";
-
  import ErrorMessage from "@app/components/ErrorMessage.svelte";
  import SourceBrowsingHeader from "./SourceBrowsingHeader.svelte";

  import Browser from "./Browser.svelte";
@@ -37,28 +29,7 @@
  export let revision: string | undefined = undefined;
  export let search: string | undefined = undefined;

-
  $: searchParams = new URLSearchParams(search || "");
-
  $: issueFilter = (searchParams.get("state") as IssueStatus) || "open";
-
  $: patchTabFilter =
-
    (searchParams.get("tab") as "activity" | "commits" | "files") || "activity";
-
  $: patchFilter = (searchParams.get("state") as PatchStatus) || "open";
-
  $: patchDiffFilter = searchParams.get("diff") || undefined;
  $: baseUrl = utils.extractBaseUrl(hostAndPort);
-
  $: api = new HttpdClient(baseUrl);
-

-
  function handleIssueCreation({ detail: issueId }: CustomEvent<string>) {
-
    void router.push({
-
      resource: "projects",
-
      params: {
-
        id,
-
        hostAndPort: httpd.api.hostAndPort,
-
        view: {
-
          resource: "issue",
-
          params: { issue: issueId },
-
        },
-
      },
-
    });
-
  }
</script>

<style>
@@ -74,14 +45,7 @@
    min-width: var(--content-min-width);
    padding-bottom: 4rem;
  }
-
  main > .message {
-
    padding: 0 2rem 0 8rem;
-
  }
-

  @media (max-width: 960px) {
-
    main > .message {
-
      padding-left: 2rem;
-
    }
    main {
      padding-top: 2rem;
      min-width: 0;
@@ -133,36 +97,12 @@
        totalCommitCount={view.totalCommitCount}
        commitHeaders={view.commitHeaders} />
    {:else if view.resource === "commits"}
-
      {#await api.project.getCommitBySha(id, view.params.selectedCommit)}
-
        <Loading center />
-
      {:then fetchedCommit}
-
        <Commit commit={fetchedCommit} />
-
      {:catch e}
-
        <div class="message">
-
          <ErrorMessage message="Couln't load commit." stackTrace={e} />
-
        </div>
-
      {/await}
+
      <Commit commit={view.commit} />
    {/if}
  {:else if view.resource === "issues" && view.params?.view.resource === "new"}
-
    {#if $httpdStore.state === "authenticated"}
-
      <NewIssue
-
        on:create={handleIssueCreation}
-
        session={$httpdStore.session}
-
        projectId={id}
-
        projectHead={project.head}
-
        {baseUrl} />
-
    {:else}
-
      <div class="message">
-
        <ErrorMessage
-
          message="Couldn't access issue creation. Make sure you're still logged in." />
-
      </div>
-
    {/if}
+
    <NewIssue projectId={id} projectHead={project.head} {baseUrl} />
  {:else if view.resource === "issues"}
-
    <Issues
-
      {baseUrl}
-
      projectId={id}
-
      issueCounters={project.issues}
-
      state={issueFilter} />
+
    <Issues {baseUrl} projectId={id} issueCounters={project.issues} {search} />
  {:else if view.resource === "issue"}
    <Issue
      projectId={id}
@@ -173,20 +113,17 @@
    <Patches
      {baseUrl}
      projectId={id}
-
      state={patchFilter}
-
      patchCounters={project.patches} />
+
      patchCounters={project.patches}
+
      {search} />
  {:else if view.resource === "patch"}
-
    {@const patch = view.params.loadedPatch}
-
    {@const latestRevision = patch.revisions[patch.revisions.length - 1]}
    <Patch
-
      {patch}
+
      patch={view.params.loadedPatch}
      {baseUrl}
      projectId={id}
      projectDefaultBranch={project.defaultBranch}
      projectHead={project.head}
-
      revision={view.params.revision ?? latestRevision.id}
-
      currentTab={patchTabFilter}
-
      diff={patchDiffFilter} />
+
      revision={view.params.revision}
+
      {search} />
  {:else}
    {unreachable(view)}
  {/if}
modified src/views/projects/router.ts
@@ -1,5 +1,6 @@
import type { LoadError } from "@app/lib/router/definitions";
import type {
+
  Commit,
  CommitHeader,
  Issue,
  Patch,
@@ -83,6 +84,7 @@ export type ProjectLoadedView =
  | {
      resource: "commits";
      params: LoadedSourceBrowsingParams;
+
      commit: Commit;
    }
  | {
      resource: "history";
@@ -224,6 +226,25 @@ export async function loadProjectRoute(
            },
          },
        };
+
      }
+
      if (params.view.resource === "commits") {
+
        const loadedCommit = await api.project.getCommitBySha(
+
          params.id,
+
          commit,
+
        );
+

+
        return {
+
          resource: "projects",
+
          params: {
+
            ...params,
+
            project,
+
            view: {
+
              resource: params.view.resource,
+
              params: viewParams,
+
              commit: loadedCommit,
+
            },
+
          },
+
        };
      } else {
        return {
          resource: "projects",