Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Separate global project header from source browsing header
Rūdolfs Ošiņš committed 3 years ago
commit e41a12d663b1c894c95798f393cab5a251b868b7
parent f9445de618243285b4c9a1630dcffa71daa62a29
6 files changed +153 -88
modified src/views/projects/Header.svelte
@@ -1,39 +1,39 @@
<script lang="ts">
-
  import type { BaseUrl, Project, Remote, Tree } from "@httpd-client";
+
  import type { BaseUrl } from "@httpd-client";
  import type { ProjectRoute } from "@app/views/projects/router";

-
  import { closeFocused } from "@app/components/Floating.svelte";
  import { config } from "@app/lib/config";
  import { pluralize } from "@app/lib/pluralize";

-
  import BranchSelector from "@app/views/projects/BranchSelector.svelte";
  import CloneButton from "@app/views/projects/CloneButton.svelte";
  import Link from "@app/components/Link.svelte";
-
  import PeerSelector from "@app/views/projects/PeerSelector.svelte";
  import ProjectLink from "@app/components/ProjectLink.svelte";
  import SquareButton from "@app/components/SquareButton.svelte";

-
  export let project: Project;
  export let activeRoute: ProjectRoute;
-
  export let tree: Tree;
-
  export let commit: string;
-
  export let peers: Remote[];
-
  export let branches: Record<string, string>;
  export let baseUrl: BaseUrl;

-
  $: revision = activeRoute.params.revision ?? commit;
+
  export let projectId: string;
+
  export let projectName: string;
+

+
  export let openPatchCount: number;
+
  export let openIssueCount: number;
</script>

<style>
  .header {
    font-size: var(--font-size-tiny);
    padding: 0 2rem 0 8rem;
-
    margin-bottom: 2rem;
    display: flex;
    align-items: center;
    justify-content: left;
    flex-wrap: wrap;
    gap: 0.5rem;
+
    margin-bottom: 1rem;
+
  }
+

+
  .header:last-of-type {
+
    margin-bottom: 2rem;
  }

  @media (max-width: 960px) {
@@ -47,90 +47,69 @@
</style>

<div class="header">
-
  {#if peers.length > 0}
-
    <PeerSelector
-
      {peers}
-
      peer={activeRoute.params.peer}
-
      on:click={() => closeFocused()} />
-
  {/if}
-

-
  <BranchSelector
-
    projectDefaultBranch={project.defaultBranch}
-
    projectHead={project.head}
-
    {branches}
-
    {revision}
-
    on:click={() => closeFocused()} />
-

-
  <CloneButton {baseUrl} id={project.id} name={project.name} />
-

-
  <Link
-
    route={{
-
      resource: "seeds",
-
      params: {
-
        hostnamePort:
-
          baseUrl.port === config.seeds.defaultHttpdPort
-
            ? baseUrl.hostname
-
            : `${baseUrl.hostname}:${baseUrl.port}`,
-
        projectPageIndex: 0,
-
      },
-
    }}>
-
    <SquareButton>
-
      {baseUrl.hostname}
-
    </SquareButton>
-
  </Link>
-

  <ProjectLink
    projectParams={{
-
      id: project.id,
-
      view: {
-
        resource:
-
          activeRoute.params.view.resource === "history" ? "tree" : "history",
-
      },
-
      revision: revision,
-
      search: undefined,
+
      view: { resource: "tree" },
+
      path: "/",
+
      peer: undefined,
+
      route: undefined,
+
      revision: undefined,
    }}>
-
    <SquareButton active={activeRoute.params.view.resource === "history"}>
-
      <span class="txt-bold">{tree.stats.commits}</span>
-
      {pluralize("commit", tree.stats.commits)}
+
    <SquareButton
+
      active={activeRoute.params.view.resource === "tree" ||
+
        activeRoute.params.view.resource === "history" ||
+
        activeRoute.params.view.resource === "commits"}>
+
      Source
    </SquareButton>
  </ProjectLink>
-

  <ProjectLink
    projectParams={{
-
      id: project.id,
+
      id: projectId,
      view: {
-
        resource:
-
          activeRoute.params.view.resource === "issues" ? "tree" : "issues",
+
        resource: "issues",
      },
+
      peer: undefined,
      search: undefined,
      revision: undefined,
      path: undefined,
    }}>
    <SquareButton active={activeRoute.params.view.resource === "issues"}>
-
      <span class="txt-bold">{project.issues.open}</span>
-
      {pluralize("issue", project.issues.open)}
+
      <span class="txt-bold">{openIssueCount}</span>
+
      {pluralize("issue", openIssueCount)}
    </SquareButton>
  </ProjectLink>

  <ProjectLink
    projectParams={{
-
      id: project.id,
+
      id: projectId,
      view: {
-
        resource:
-
          activeRoute.params.view.resource === "patches" ? "tree" : "patches",
+
        resource: "patches",
      },
+
      peer: undefined,
      search: undefined,
      revision: undefined,
      path: undefined,
    }}>
    <SquareButton active={activeRoute.params.view.resource === "patches"}>
-
      <span class="txt-bold">{project.patches.open}</span>
-
      {pluralize("patch", project.patches.open)}
+
      <span class="txt-bold">{openPatchCount}</span>
+
      {pluralize("patch", openPatchCount)}
    </SquareButton>
  </ProjectLink>
+
  <CloneButton {baseUrl} id={projectId} name={projectName} />

-
  <SquareButton hoverable={false}>
-
    <span class="txt-bold">{tree.stats.contributors}</span>
-
    {pluralize("contributor", tree.stats.contributors)}
-
  </SquareButton>
+
  <Link
+
    route={{
+
      resource: "seeds",
+
      params: {
+
        hostnamePort:
+
          baseUrl.port === config.seeds.defaultHttpdPort
+
            ? baseUrl.hostname
+
            : `${baseUrl.hostname}:${baseUrl.port}`,
+
        projectPageIndex: 0,
+
      },
+
    }}>
+
    <SquareButton>
+
      {baseUrl.hostname}
+
    </SquareButton>
+
  </Link>
</div>
modified src/views/projects/Issues.svelte
@@ -111,7 +111,7 @@

<div class="issues">
  <div class="section-header">
-
    <div style="margin-bottom: 1rem;">
+
    <div style="margin-bottom: 2rem;">
      <div style="display: flex; gap: 0.5rem;">
        {#each options as option}
          {#if !option.disabled}
@@ -120,7 +120,6 @@
                search: `state=${option.value}`,
              }}>
              <SquareButton
-
                size="small"
                clickable={option.disabled}
                active={option.value === state}
                disabled={option.disabled}>
@@ -129,7 +128,6 @@
            </ProjectLink>
          {:else}
            <SquareButton
-
              size="small"
              clickable={option.disabled}
              active={option.value === state}
              disabled={option.disabled}>
@@ -147,7 +145,7 @@
            params: { view: { resource: "new" } },
          },
        }}>
-
        <SquareButton size="small">New issue</SquareButton>
+
        <SquareButton>New issue</SquareButton>
      </ProjectLink>
    {/if}
  </div>
modified src/views/projects/Patches.svelte
@@ -106,12 +106,11 @@
</style>

<div class="patches">
-
  <div style="margin-bottom: 1rem;">
+
  <div style="margin-bottom: 2rem;">
    <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
      {#each options as option}
        {#if option.disabled}
          <SquareButton
-
            size="small"
            clickable={option.disabled}
            active={option.value === state}
            disabled={option.disabled}>
@@ -123,7 +122,6 @@
              search: `state=${option.value}`,
            }}>
            <SquareButton
-
              size="small"
              clickable={option.disabled}
              active={option.value === state}
              disabled={option.disabled}>
added src/views/projects/SourceBrowsingHeader.svelte
@@ -0,0 +1,79 @@
+
<script lang="ts">
+
  import type { Project, Remote } from "@httpd-client";
+
  import type { ProjectRoute } from "@app/views/projects/router";
+

+
  import { closeFocused } from "@app/components/Floating.svelte";
+
  import { pluralize } from "@app/lib/pluralize";
+

+
  import BranchSelector from "@app/views/projects/BranchSelector.svelte";
+
  import PeerSelector from "@app/views/projects/PeerSelector.svelte";
+
  import ProjectLink from "@app/components/ProjectLink.svelte";
+
  import SquareButton from "@app/components/SquareButton.svelte";
+

+
  export let project: Project;
+
  export let activeRoute: ProjectRoute;
+
  export let revision: string;
+
  export let peers: Remote[];
+
  export let branches: Record<string, string>;
+

+
  export let commitCount: number;
+
  export let contributorCount: number;
+
</script>
+

+
<style>
+
  .header {
+
    font-size: var(--font-size-tiny);
+
    padding: 0 2rem 0 8rem;
+
    display: flex;
+
    align-items: center;
+
    justify-content: left;
+
    flex-wrap: wrap;
+
    gap: 0.5rem;
+
    margin-bottom: 2rem;
+
  }
+

+
  @media (max-width: 960px) {
+
    .header {
+
      padding-left: 2rem;
+
    }
+
    .header {
+
      margin-bottom: 1.5rem;
+
    }
+
  }
+
</style>
+

+
<div class="header">
+
  {#if peers.length > 0}
+
    <PeerSelector
+
      {peers}
+
      peer={activeRoute.params.peer}
+
      on:click={() => closeFocused()} />
+
  {/if}
+

+
  <BranchSelector
+
    projectDefaultBranch={project.defaultBranch}
+
    projectHead={project.head}
+
    {branches}
+
    {revision}
+
    on:click={() => closeFocused()} />
+

+
  <ProjectLink
+
    projectParams={{
+
      id: project.id,
+
      view: {
+
        resource: "history",
+
      },
+
      revision: revision,
+
      search: undefined,
+
    }}>
+
    <SquareButton active={activeRoute.params.view.resource === "history"}>
+
      <span class="txt-bold">{commitCount}</span>
+
      {pluralize("commit", commitCount)}
+
    </SquareButton>
+
  </ProjectLink>
+

+
  <SquareButton hoverable={false}>
+
    <span class="txt-bold">{contributorCount}</span>
+
    {pluralize("contributor", contributorCount)}
+
  </SquareButton>
+
</div>
modified src/views/projects/View.svelte
@@ -15,6 +15,7 @@
  import ErrorMessage from "@app/components/ErrorMessage.svelte";
  import NotFound from "@app/components/NotFound.svelte";
  import Placeholder from "@app/components/Placeholder.svelte";
+
  import SourceBrowsingHeader from "./SourceBrowsingHeader.svelte";

  import Browser from "./Browser.svelte";
  import Commit from "./Commit.svelte";
@@ -188,14 +189,24 @@
      <Loading center />
    {:then { tree, commit }}
      <Header
-
        {tree}
-
        {commit}
-
        {project}
-
        {branches}
-
        {peers}
+
        projectId={project.id}
+
        projectName={project.name}
+
        openPatchCount={project.patches.open}
+
        openIssueCount={project.issues.open}
        {activeRoute}
        {baseUrl} />

+
      {#if activeRoute.params.view.resource === "tree" || activeRoute.params.view.resource === "history" || activeRoute.params.view.resource === "commits"}
+
        <SourceBrowsingHeader
+
          {project}
+
          {activeRoute}
+
          revision={activeRoute.params.revision ?? commit}
+
          {peers}
+
          {branches}
+
          commitCount={tree.stats.commits}
+
          contributorCount={tree.stats.contributors} />
+
      {/if}
+

      {#if activeRoute.params.view.resource === "tree"}
        <Browser {baseUrl} {project} {commit} {tree} {activeRoute} />
      {:else if activeRoute.params.view.resource === "history"}
@@ -203,8 +214,8 @@
      {:else if activeRoute.params.view.resource === "commits"}
        {#await api.project.getCommitBySha(id, commit)}
          <Loading center />
-
        {:then commit}
-
          <Commit {commit} />
+
        {:then fetchedCommit}
+
          <Commit commit={fetchedCommit} />
        {:catch e}
          <div class="message">
            <ErrorMessage message="Couln't load commit." stackTrace={e} />
modified tests/e2e/project.spec.ts
@@ -362,6 +362,12 @@ test("only one modal can be open at a time", async ({ page }) => {
  await expect(page.locator("text=bob hyyzz9")).not.toBeVisible();
  await expect(page.locator("text=feature/branch")).not.toBeVisible();

+
  await page.locator('button[name="Settings"]').click();
+
  await expect(page.locator("text=Code font")).toBeVisible();
+
  await expect(page.locator("text=Use the Radicle CLI")).not.toBeVisible();
+
  await expect(page.locator("text=bob hyyzz9")).not.toBeVisible();
+
  await expect(page.locator("text=feature/branch")).not.toBeVisible();
+

  await page.getByTitle("Change branch").click();
  await expect(page.locator("text=Code font")).not.toBeVisible();
  await expect(page.locator("text=Use the Radicle CLI")).not.toBeVisible();
@@ -373,12 +379,6 @@ test("only one modal can be open at a time", async ({ page }) => {
  await expect(page.locator("text=Use the Radicle CLI")).not.toBeVisible();
  await expect(page.locator(`text=${bobRemote}`)).toBeVisible();
  await expect(page.locator("text=feature/branch")).not.toBeVisible();
-

-
  await page.locator('button[name="Settings"]').click();
-
  await expect(page.locator("text=Code font")).toBeVisible();
-
  await expect(page.locator("text=Use the Radicle CLI")).not.toBeVisible();
-
  await expect(page.locator("text=bob hyyzz9")).not.toBeVisible();
-
  await expect(page.locator("text=feature/branch")).not.toBeVisible();
});

test.describe("browser error handling", () => {