Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
radicle-explorer src views repos Patch PatchTeaser.svelte
<script lang="ts">
  import type { BaseUrl } from "@http-client";
  import type { Patch } from "@http-client";

  import { absoluteTimestamp, formatTimestamp } from "@app/lib/utils";

  import CommentCounter from "../CommentCounter.svelte";
  import DiffStatBadgeLoader from "../DiffStatBadgeLoader.svelte";
  import Icon from "@app/components/Icon.svelte";
  import Id from "@app/components/Id.svelte";
  import InlineLabels from "@app/views/repos/Cob/InlineLabels.svelte";
  import InlineTitle from "@app/views/repos/components/InlineTitle.svelte";
  import Link from "@app/components/Link.svelte";
  import NodeId from "@app/components/NodeId.svelte";

  export let repoId: string;
  export let baseUrl: BaseUrl;
  export let patch: Patch;

  $: latestRevisionIndex = patch.revisions.length - 1;
  $: latestRevision = patch.revisions[latestRevisionIndex];

  $: commentCount = patch.revisions.reduce(
    (acc, curr) => acc + curr.discussions.reduce(acc => acc + 1, 0),
    0,
  );
</script>

<style>
  .patch-teaser {
    display: flex;
    padding: 1.25rem;
    background-color: var(--color-surface-canvas);
  }
  .patch-teaser:hover {
    background-color: var(--color-surface-subtle);
  }
  .content {
    width: 100%;
    gap: 0.5rem;
    display: flex;
    flex-direction: column;
  }
  .subtitle {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    font: var(--txt-body-m-regular);
    gap: 0.5rem;
  }
  .summary {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    word-break: break-word;
  }
  .right {
    margin-left: auto;
    display: flex;
    align-items: flex-start;
  }
  .state {
    justify-self: center;
    align-self: flex-start;
    margin-right: 0.5rem;
    padding: 0.25rem 0.25rem;
    border-radius: var(--border-radius-xs);
  }
  .open {
    color: var(--color-text-open);
    background: var(--color-surface-open);
  }
  .archived {
    color: var(--color-text-archived);
    background: var(--color-surface-archived);
  }
  .merged {
    color: var(--color-text-merged);
    background: var(--color-surface-merged);
  }
  .draft {
    color: var(--color-text-draft);
    background: var(--color-surface-draft);
  }
  .diff-comment {
    display: flex;
    flex-direction: row;
    gap: 0.5rem;
    min-height: 1.5rem;
  }
</style>

<div role="button" tabindex="0" class="patch-teaser">
  <div
    class="state"
    class:draft={patch.state.status === "draft"}
    class:open={patch.state.status === "open"}
    class:merged={patch.state.status === "merged"}
    class:archived={patch.state.status === "archived"}>
    <Icon
      name={patch.state.status === "draft"
        ? "patch-draft"
        : patch.state.status === "merged"
          ? "patch-merged"
          : patch.state.status === "archived"
            ? "patch-archived"
            : "patch"} />
  </div>
  <div class="content">
    <div class="summary">
      <Link
        styleHoverState
        route={{
          resource: "repo.patch",
          repo: repoId,
          node: baseUrl,
          patch: patch.id,
        }}>
        <InlineTitle fontSize="body-m-regular" content={patch.title} />
      </Link>
      {#if patch.labels.length > 0}
        <span
          class="global-hide-on-small-desktop-down"
          style="display: inline-flex; gap: 0.5rem;">
          <InlineLabels labels={patch.labels} />
        </span>
      {/if}
      <div class="right">
        <div class="diff-comment">
          {#if commentCount > 0}
            <CommentCounter {commentCount} />
          {/if}
          <DiffStatBadgeLoader {repoId} {baseUrl} {patch} {latestRevision} />
        </div>
      </div>
    </div>
    <div class="summary">
      <span class="subtitle">
        {#if patch.labels.length > 0}
          <div
            class="global-hide-on-medium-desktop-up"
            style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
            <InlineLabels labels={patch.labels} />
          </div>
        {/if}
        <div
          style="display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;">
          <NodeId
            {baseUrl}
            nodeId={patch.author.id}
            alias={patch.author.alias} />
          {patch.revisions.length > 1 ? "updated" : "opened"}
          <Id id={patch.id} />
          {#if patch.revisions.length > 1}
            <span class="global-hide-on-mobile-down">
              to <Id id={patch.revisions[patch.revisions.length - 1].id} />
            </span>
          {/if}
          <span title={absoluteTimestamp(latestRevision.timestamp)}>
            {formatTimestamp(latestRevision.timestamp)}
          </span>
        </div>
      </span>
    </div>
  </div>
</div>