Radish alpha
r
rad:z4D5UCArafTzTQpDZNQRuqswh3ury
Radicle desktop app
Radicle
Git
Display all additions of labels or assignees
Merged did:key:z6MkkfM3...sVz5 opened 1 year ago

Instead of relying on actions of previous labels or assignees, we should always display changes to labels and assignees which can also happen on creation of an issue or patch.

Also makes use of the pluralize helper function instead of reimplementing it.

Fixes 4d84207f198f1241aa74b22391e89620ca22b20c

2 files changed +143 -97 8f882c60 9231d3c6
modified src/components/IssueTimeline.svelte
@@ -17,6 +17,7 @@
    authorForNodeId,
    formatTimestamp,
    issueStatusColor,
+
    pluralize,
    publicKeyFromDid,
  } from "@app/lib/utils";
  import Icon from "./Icon.svelte";
@@ -126,72 +127,95 @@
          </div>
        </div>
      </div>
-
    {:else if op.type === "label" && op.previous && op.previous.type === op.type}
-
      {@const changed = itemDiff(op.previous?.labels ?? [], op.labels)}
-
      {#if changed.added.length || changed.removed.length}
-
        <div class="timeline-item">
-
          <div class="icon">
-
            <Icon name="label" />
-
          </div>
-
          <div class="wrapper">
-
            <NodeId {...authorForNodeId(op.author)} />
-
            {#if changed.added.length}
-
              added label{changed.added.length > 1 ? "s" : ""}
-
              {#each changed.added as label}
-
                <b>{label}</b>
-
              {/each}
-
            {/if}
-
            {#if changed.removed.length}
-
              removed label{changed.removed.length > 1 ? "s" : ""}
-
              {#each changed.removed as label}
-
                <b>{label}</b>
-
              {/each}
+
    {:else if op.type === "label"}
+
      <div class="timeline-item">
+
        <div class="icon">
+
          <Icon name="label" />
+
        </div>
+
        <div class="wrapper">
+
          <NodeId {...authorForNodeId(op.author)} />
+
          {#if op.previous && op.previous.type === op.type}
+
            {@const changed = itemDiff(op.previous?.labels ?? [], op.labels)}
+
            {#if changed.added.length || changed.removed.length}
+
              {#if changed.added.length}
+
                added {pluralize("label", changed.removed.length)}
+
                {#each changed.added as label}
+
                  <b>{label}</b>
+
                {/each}
+
              {/if}
+
              {#if changed.removed.length}
+
                removed {pluralize("label", changed.removed.length)}
+
                {#each changed.removed as label}
+
                  <b>{label}</b>
+
                {/each}
+
              {/if}
            {/if}
-
            <div title={absoluteTimestamp(op.timestamp)}>
-
              {formatTimestamp(op.timestamp)}
-
            </div>
+
          {:else}
+
            added {pluralize("label", op.labels.length)}
+
            {#each op.labels as label}
+
              <b>{label}</b>
+
            {/each}
+
          {/if}
+
          <div title={absoluteTimestamp(op.timestamp)}>
+
            {formatTimestamp(op.timestamp)}
          </div>
        </div>
-
      {/if}
-
    {:else if op.type === "assign" && op.previous && op.previous.type === op.type}
-
      {@const changed = itemDiff(op.previous?.assignees ?? [], op.assignees)}
-
      {#if changed.added.length || changed.removed.length}
-
        <div class="timeline-item">
-
          <div class="icon">
-
            <Icon name="user" />
-
          </div>
-
          <div class="wrapper">
-
            <NodeId {...authorForNodeId(op.author)} />
-
            {#if changed.added.length}
-
              assigned
-
              {#each changed.added as assignee}
-
                {#await invoke<string | null>( "alias", { nid: publicKeyFromDid(assignee) }, ) then alias}
-
                  <NodeId
-
                    {...authorForNodeId({
-
                      did: assignee,
-
                      alias: alias ?? undefined,
-
                    })} />
-
                {/await}
-
              {/each}
-
            {/if}
-
            {#if changed.removed.length}
-
              unassigned
-
              {#each changed.removed as assignee}
-
                {#await invoke<string | null>( "alias", { nid: publicKeyFromDid(assignee) }, ) then alias}
-
                  <NodeId
-
                    {...authorForNodeId({
-
                      did: assignee,
-
                      alias: alias ?? undefined,
-
                    })} />
-
                {/await}
-
              {/each}
+
      </div>
+
    {:else if op.type === "assign"}
+
      <div class="timeline-item">
+
        <div class="icon">
+
          <Icon name="user" />
+
        </div>
+
        <div class="wrapper">
+
          <NodeId {...authorForNodeId(op.author)} />
+
          {#if op.previous && op.previous.type === op.type}
+
            {@const changed = itemDiff(
+
              op.previous?.assignees ?? [],
+
              op.assignees,
+
            )}
+
            {#if changed.added.length || changed.removed.length}
+
              {#if changed.added.length}
+
                assigned
+
                {#each changed.added as assignee}
+
                  {#await invoke<string | null>( "alias", { nid: publicKeyFromDid(assignee) }, ) then alias}
+
                    <NodeId
+
                      {...authorForNodeId({
+
                        did: assignee,
+
                        alias: alias ?? undefined,
+
                      })} />
+
                  {/await}
+
                {/each}
+
              {/if}
+
              {#if changed.removed.length}
+
                unassigned
+
                {#each changed.removed as assignee}
+
                  {#await invoke<string | null>( "alias", { nid: publicKeyFromDid(assignee) }, ) then alias}
+
                    <NodeId
+
                      {...authorForNodeId({
+
                        did: assignee,
+
                        alias: alias ?? undefined,
+
                      })} />
+
                  {/await}
+
                {/each}
+
              {/if}
            {/if}
-
            <div title={absoluteTimestamp(op.timestamp)}>
-
              {formatTimestamp(op.timestamp)}
-
            </div>
+
          {:else}
+
            assigned
+
            {#each op.assignees as assignee}
+
              {#await invoke<string | null>( "alias", { nid: publicKeyFromDid(assignee) }, ) then alias}
+
                <NodeId
+
                  {...authorForNodeId({
+
                    did: assignee,
+
                    alias: alias ?? undefined,
+
                  })} />
+
              {/await}
+
            {/each}
+
          {/if}
+
          <div title={absoluteTimestamp(op.timestamp)}>
+
            {formatTimestamp(op.timestamp)}
          </div>
        </div>
-
      {/if}
+
      </div>
    {:else if op.type === "edit"}
      {#if op.previous && op.previous.type === op.type}
        <div class="timeline-item">
modified src/components/PatchTimeline.svelte
@@ -17,6 +17,7 @@
    authorForNodeId,
    formatTimestamp,
    patchStatusColor,
+
    pluralize,
    publicKeyFromDid,
  } from "@app/lib/utils";
  import Icon from "./Icon.svelte";
@@ -147,42 +148,52 @@
          </div>
        </div>
      </div>
-
    {:else if op.type === "label" && op.previous && op.previous.type === op.type}
-
      {@const changed = itemDiff(op.previous?.labels ?? [], op.labels)}
-
      {#if changed.added.length || changed.removed.length}
-
        <div class="timeline-item">
-
          <div class="icon">
-
            <Icon name="label" />
-
          </div>
-
          <div class="wrapper">
-
            <NodeId {...authorForNodeId(op.author)} />
-
            {#if changed.added.length}
-
              added label{changed.added.length > 1 ? "s" : ""}
-
              {#each changed.added as label}
-
                <b>{label}</b>
-
              {/each}
-
            {/if}
-
            {#if changed.removed.length}
-
              removed label{changed.removed.length > 1 ? "s" : ""}
-
              {#each changed.removed as label}
-
                <b>{label}</b>
-
              {/each}
+
    {:else if op.type === "label"}
+
      <div class="timeline-item">
+
        <div class="icon">
+
          <Icon name="label" />
+
        </div>
+
        <div class="wrapper">
+
          <NodeId {...authorForNodeId(op.author)} />
+
          {#if op.previous && op.previous.type === op.type}
+
            {@const changed = itemDiff(op.previous?.labels ?? [], op.labels)}
+
            {#if changed.added.length || changed.removed.length}
+
              {#if changed.added.length}
+
                added {pluralize("label", changed.added.length)}
+
                {#each changed.added as label}
+
                  <b>{label}</b>
+
                {/each}
+
              {/if}
+
              {#if changed.removed.length}
+
                removed {pluralize("label", changed.removed.length)}
+
                {#each changed.removed as label}
+
                  <b>{label}</b>
+
                {/each}
+
              {/if}
            {/if}
-
            <div title={absoluteTimestamp(op.timestamp)}>
-
              {formatTimestamp(op.timestamp)}
-
            </div>
+
          {:else}
+
            added {pluralize("label", op.labels.length)}
+
            {#each op.labels as label}
+
              <b>{label}</b>
+
            {/each}
+
          {/if}
+
          <div title={absoluteTimestamp(op.timestamp)}>
+
            {formatTimestamp(op.timestamp)}
          </div>
        </div>
-
      {/if}
-
    {:else if op.type === "assign" && op.previous && op.previous.type === op.type}
-
      {@const changed = itemDiff(op.previous?.assignees ?? [], op.assignees)}
-
      {#if changed.added.length || changed.removed.length}
-
        <div class="timeline-item">
-
          <div class="icon">
-
            <Icon name="user" />
-
          </div>
-
          <div class="wrapper">
-
            <NodeId {...authorForNodeId(op.author)} />
+
      </div>
+
    {:else if op.type === "assign"}
+
      <div class="timeline-item">
+
        <div class="icon">
+
          <Icon name="user" />
+
        </div>
+
        <div class="wrapper">
+
          <NodeId {...authorForNodeId(op.author)} />
+
          {#if op.previous && op.previous.type === op.type}
+
            {@const changed = itemDiff(
+
              op.previous?.assignees ?? [],
+
              op.assignees,
+
            )}
            {#if changed.added.length}
              assigned
              {#each changed.added as assignee}
@@ -207,12 +218,23 @@
                {/await}
              {/each}
            {/if}
-
            <div title={absoluteTimestamp(op.timestamp)}>
-
              {formatTimestamp(op.timestamp)}
-
            </div>
+
          {:else}
+
            assigned
+
            {#each op.assignees as assignee}
+
              {#await invoke<string | null>( "alias", { nid: publicKeyFromDid(assignee) }, ) then alias}
+
                <NodeId
+
                  {...authorForNodeId({
+
                    did: assignee,
+
                    alias: alias ?? undefined,
+
                  })} />
+
              {/await}
+
            {/each}
+
          {/if}
+
          <div title={absoluteTimestamp(op.timestamp)}>
+
            {formatTimestamp(op.timestamp)}
          </div>
        </div>
-
      {/if}
+
      </div>
    {:else if op.type === "merge"}
      <div class="timeline-item">
        <div class="icon" style:color="var(--color-fill-primary)">