Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
Add rudimentary "Browse all repos on node" view
Cameron Eldridge committed 7 months ago
commit 97dac7e28f62cfd29e2a79d2f8a3175cc4562369
parent 5cf6572
2 files changed +170 -65
added src/views/nodes/ReposView.svelte
@@ -0,0 +1,168 @@
+
<script lang="ts">
+
  import type { BaseUrl, NodeStats } from "@http-client";
+

+
  import * as router from "@app/lib/router";
+
  import { baseUrlToString } from "@app/lib/utils";
+
  import { fetchRepoInfos } from "@app/components/RepoCard";
+
  import { handleError } from "@app/views/nodes/error";
+

+
  import Loading from "@app/components/Loading.svelte";
+
  import Placeholder from "@app/components/Placeholder.svelte";
+
  import RepoCard from "@app/components/RepoCard.svelte";
+

+
  export let baseUrl: BaseUrl;
+
  export let stats: NodeStats;
+

+
  let listState: "pinned" | "all" = "pinned";
+

+
  $: page = 0;
+
  $: perPage = listState === "pinned" ? stats.repos.total : 24;
+
  $: totalPages = Math.ceil(stats.repos.total / perPage);
+

+
  function showPinned() {
+
    listState = "pinned";
+
    page = 0;
+
  }
+
  function showAll() {
+
    listState = "all";
+
  }
+
</script>
+

+
<style>
+
  .subtitle,
+
  .pagination {
+
    font-size: var(--font-size-small);
+
    color: var(--color-foreground-dim);
+
  }
+
  .pagination {
+
    display: flex;
+
    gap: 0.25rem;
+
    margin-left: auto;
+
  }
+
  .repos {
+
    margin-top: 0;
+
  }
+
  .repo-grid {
+
    display: grid;
+
    grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr));
+
    gap: 1rem;
+
  }
+
  .empty-state {
+
    display: flex;
+
    flex-direction: column;
+
    align-items: center;
+
    justify-content: center;
+
    gap: 0.5rem;
+
    height: 35vh;
+
    font-size: var(--font-size-small);
+
  }
+
  .text-button {
+
    background: none;
+
    border: none;
+
    font: inherit;
+
    color: inherit;
+
    margin: 0;
+
    padding: 0;
+
  }
+
  .text-button:not(:disabled) {
+
    cursor: pointer;
+
  }
+
  .text-button:hover:not(:disabled) {
+
    text-decoration: underline;
+
  }
+
  .current-page {
+
    text-decoration: underline;
+
  }
+
  .footer {
+
    display: flex;
+
    gap: 0.5rem 1rem;
+
    margin-top: 1rem;
+
  }
+

+
  @media (max-width: 1010.98px) {
+
    .repos {
+
      margin-top: 3rem;
+
    }
+
    .footer {
+
      flex-direction: column;
+
    }
+
    .pagination {
+
      margin-left: 0;
+
    }
+
  }
+
</style>
+

+
<div class="repos">
+
  {#await fetchRepoInfos(baseUrl, { show: listState, perPage, page })}
+
    <div style:height="35vh">
+
      <Loading small center />
+
    </div>
+
  {:then repoInfos}
+
    {#if repoInfos.length > 0}
+
      <div class="repo-grid">
+
        {#each repoInfos as repoInfo}
+
          <RepoCard {baseUrl} {repoInfo} />
+
        {/each}
+
      </div>
+
      <div class="footer">
+
        {#if listState === "pinned"}
+
          <div class="subtitle">
+
            {repoInfos.length}
+
            pinned {repoInfos.length === 1 ? "repository" : "repositories"} ·
+
            <button class="text-button" on:click={showAll}>Browse all</button>
+
          </div>
+
        {:else}
+
          <div class="subtitle">
+
            {stats.repos.total.toLocaleString()}
+
            seeded {stats.repos.total === 1 ? "repository" : "repositories"} ·
+
            <button class="text-button" on:click={showPinned}>
+
              See pinned
+
            </button>
+
          </div>
+

+
          <div class="pagination">
+
            {#if page !== 0}
+
              <button class="text-button" on:click={() => (page = page - 1)}>
+
                Previous
+
              </button>
+
              ·
+
            {/if}
+

+
            {#each Array.from({ length: Math.min(totalPages, 7) }) as _, i}
+
              {@const startPage = Math.max(page - 3, 0)}
+
              {@const pageNumber = startPage + i}
+
              <button
+
                class="text-button"
+
                class:current-page={page === pageNumber}
+
                on:click={() => (page = pageNumber)}
+
                disabled={page === pageNumber}>
+
                {pageNumber + 1}
+
              </button>
+
            {/each}
+

+
            {#if page !== totalPages - 1}
+
              ·
+
              <button class="text-button" on:click={() => (page = page + 1)}>
+
                Next
+
              </button>
+
            {/if}
+
          </div>
+
        {/if}
+
      </div>
+
    {:else}
+
      <div class="empty-state">
+
        {#if listState === "pinned"}
+
          <Placeholder
+
            iconName="desert"
+
            caption="This node doesn't have any pinned repositories." />
+
        {:else}
+
          <Placeholder
+
            iconName="desert"
+
            caption="This node doesn't seed any repositories." />
+
        {/if}
+
      </div>
+
    {/if}
+
  {:catch error}
+
    {router.push(handleError(error, baseUrlToString(baseUrl)))}
+
  {/await}
+
</div>
modified src/views/nodes/View.svelte
@@ -1,12 +1,8 @@
<script lang="ts">
  import type { BaseUrl, Node, NodeStats } from "@http-client";

-
  import * as router from "@app/lib/router";
  import dompurify from "dompurify";
  import { markdown } from "@app/lib/markdown";
-
  import { baseUrlToString } from "@app/lib/utils";
-
  import { fetchRepoInfos } from "@app/components/RepoCard";
-
  import { handleError } from "@app/views/nodes/error";

  import Settings from "@app/App/Settings.svelte";

@@ -16,11 +12,9 @@
  import Icon from "@app/components/Icon.svelte";
  import IconButton from "@app/components/IconButton.svelte";
  import Link from "@app/components/Link.svelte";
-
  import Loading from "@app/components/Loading.svelte";
  import MobileFooter from "@app/App/MobileFooter.svelte";
-
  import Placeholder from "@app/components/Placeholder.svelte";
  import Popover from "@app/components/Popover.svelte";
-
  import RepoCard from "@app/components/RepoCard.svelte";
+
  import ReposView from "./ReposView.svelte";

  import PolicyExplainer from "./PolicyExplainer.svelte";
  import SeedSelector from "./SeedSelector.svelte";
@@ -138,32 +132,6 @@
    height: 2rem;
  }

-
  .subtitle {
-
    font-size: var(--font-size-small);
-
    color: var(--color-foreground-dim);
-
    display: flex;
-
    align-items: center;
-
    gap: 0.5rem;
-
    width: 100%;
-
    margin-top: 1rem;
-
  }
-
  .repos {
-
    margin-top: 0;
-
  }
-
  .repo-grid {
-
    display: grid;
-
    grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr));
-
    gap: 1rem;
-
  }
-
  .empty-state {
-
    display: flex;
-
    flex-direction: column;
-
    align-items: center;
-
    justify-content: center;
-
    gap: 0.5rem;
-
    height: 35vh;
-
    font-size: var(--font-size-small);
-
  }
  .box {
    font-size: var(--font-size-small);
    line-height: 1.625rem;
@@ -220,9 +188,6 @@
    .container {
      padding: 0;
    }
-
    .repos {
-
      margin-top: 3rem;
-
    }
    .mobile-footer {
      margin-top: auto;
      display: grid;
@@ -418,35 +383,7 @@
            </div>
          {/if}

-
          <div class="repos">
-
            {#await fetchRepoInfos( baseUrl, { show: "pinned", perPage: stats.repos.total }, )}
-
              <div style:height="35vh">
-
                <Loading small center />
-
              </div>
-
            {:then repoInfos}
-
              {#if repoInfos.length > 0}
-
                <div class="repo-grid">
-
                  {#each repoInfos as repoInfo}
-
                    <RepoCard {baseUrl} {repoInfo} />
-
                  {/each}
-
                </div>
-
                <div class="subtitle">
-
                  {repoInfos.length}
-
                  pinned {repoInfos.length === 1
-
                    ? "repository"
-
                    : "repositories"}
-
                </div>
-
              {:else}
-
                <div class="empty-state">
-
                  <Placeholder
-
                    iconName="desert"
-
                    caption="This node doesn't have any pinned repositories." />
-
                </div>
-
              {/if}
-
            {:catch error}
-
              {router.push(handleError(error, baseUrlToString(baseUrl)))}
-
            {/await}
-
          </div>
+
          <ReposView {baseUrl} {stats} />
        </div>
      </div>
    </div>