Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Bring reactions to comments and issues
Sebastian Martinez committed 2 years ago
commit 205fc814bcbce027d3b76140cd2b671b4577f3bd
parent 28718ba0cf74e41a10444d4f628aa8ad87eb9a5e
7 files changed +91 -4
modified src/components/Comment.svelte
@@ -3,6 +3,7 @@

  import Authorship from "@app/components/Authorship.svelte";
  import Button from "@app/components/Button.svelte";
+
  import Chip from "@app/components/Chip.svelte";
  import Icon from "@app/components/Icon.svelte";
  import Markdown from "@app/components/Markdown.svelte";
  import Textarea from "@app/components/Textarea.svelte";
@@ -14,12 +15,18 @@
  export let authorAliasColor: AuthorAliasColor = "--color-foreground-5";
  export let timestamp: number;
  export let body: string;
+
  export let reactions: [string, string][];
  export let showReplyIcon: boolean = false;
  export let action: "create" | "view" = "view";
  export let caption = "commented";
  export let rawPath: string;

  const dispatch = createEventDispatcher<{ toggleReply: null }>();
+

+
  $: groupedReactions = reactions?.reduce(
+
    (acc, [nid, emoji]) => acc.set(emoji, [...(acc.get(emoji) ?? []), nid]),
+
    new Map<string, string[]>(),
+
  );
</script>

<style>
@@ -48,6 +55,14 @@
    display: flex;
    gap: 0.5rem;
  }
+
  .reactions {
+
    margin-top: 1rem;
+
  }
+
  .reaction {
+
    display: inline-flex;
+
    flex-direction: row;
+
    gap: 0.5rem;
+
  }
</style>

<div class="card" {id}>
@@ -84,5 +99,17 @@
    {:else}
      <Markdown {rawPath} content={body} />
    {/if}
+
    {#if groupedReactions.size > 0}
+
      <div class="reactions">
+
        {#each groupedReactions as [reaction, nids], key}
+
          <Chip {key}>
+
            <div class="reaction">
+
              <span>{reaction}</span>
+
              <span title={nids.join("\n")}>{nids.length}</span>
+
            </div>
+
          </Chip>
+
        {/each}
+
      </div>
+
    {/if}
  </div>
</div>
modified src/components/Thread.svelte
@@ -77,6 +77,7 @@
      id={root.id}
      authorId={root.author.id}
      authorAlias={root.author.alias}
+
      reactions={root.reactions}
      timestamp={root.timestamp}
      body={root.body}
      showReplyIcon={Boolean($httpdStore.state === "authenticated")}
@@ -90,6 +91,7 @@
        authorId={reply.author.id}
        authorAlias={reply.author.alias}
        caption="replied"
+
        reactions={reply.reactions}
        timestamp={reply.timestamp}
        body={reply.body} />
    </div>
modified src/views/projects/Cob/Revision.svelte
@@ -378,11 +378,14 @@
                class:comment-review={review.verdict === null}
                class:positive-review={review.verdict === "accept"}
                class:negative-review={review.verdict === "reject"}>
+
                <!-- TODO: Empty array for reactions prop is a workaround
+
                  until review comments have reactions -->
                <CommentComponent
                  caption={formatVerdict(review.verdict)}
                  authorId={author}
                  authorAlias={review.author.alias}
                  authorAliasColor={aliasColorForVerdict(review.verdict)}
+
                  reactions={[]}
                  timestamp={review.timestamp}
                  rawPath={utils.getRawBasePath(
                    projectId,
modified src/views/projects/Issue.svelte
@@ -15,6 +15,7 @@
  import Authorship from "@app/components/Authorship.svelte";
  import Badge from "@app/components/Badge.svelte";
  import Button from "@app/components/Button.svelte";
+
  import Chip from "@app/components/Chip.svelte";
  import CobHeader from "@app/views/projects/Cob/CobHeader.svelte";
  import CobStateButton from "@app/views/projects/Cob/CobStateButton.svelte";
  import ErrorModal from "@app/views/projects/Cob/ErrorModal.svelte";
@@ -32,6 +33,11 @@
  const rawPath = utils.getRawBasePath(projectId, baseUrl, projectHead);
  const api = new HttpdClient(baseUrl);

+
  $: groupedReactions = issue.discussion[0].reactions.reduce(
+
    (acc, [nid, emoji]) => acc.set(emoji, [...(acc.get(emoji) ?? []), nid]),
+
    new Map<string, string[]>(),
+
  );
+

  let action: "edit" | "view";
  $: action =
    $httpdStore.state === "authenticated" && utils.isLocal(baseUrl.hostname)
@@ -267,6 +273,17 @@
    padding-left: 1rem;
    margin-left: 1rem;
  }
+
  .reactions {
+
    display: inline-flex;
+
    gap: 0.5rem;
+
    margin-top: 1rem;
+
    user-select: none;
+
  }
+
  .reaction {
+
    display: inline-flex;
+
    flex-direction: row;
+
    gap: 0.5rem;
+
  }

  .actions {
    display: flex;
@@ -334,6 +351,18 @@
        <Markdown
          content={issue.discussion[0].body}
          rawPath={utils.getRawBasePath(projectId, baseUrl, projectHead)} />
+
        {#if issue.discussion[0].reactions}
+
          <div class="reactions txt-tiny">
+
            {#each groupedReactions as [reaction, nids], key}
+
              <Chip {key}>
+
                <div class="reaction">
+
                  <span>{reaction}</span>
+
                  <span title={nids.join("\n")}>{nids.length}</span>
+
                </div>
+
              </Chip>
+
            {/each}
+
          </div>
+
        {/if}
      </div>
      <div class="author" slot="author">
        opened by <Authorship
modified tests/e2e/project.spec.ts
@@ -274,7 +274,7 @@ test("peer and branch switching", async ({ page }) => {
    await expect(page.getByTitle("Change peer")).toHaveText(
      `did:key:${aliceRemote.substring(8).substring(0, 6)}…${aliceRemote.slice(
        -6,
-
      )} (radicle) delegate`,
+
      )} (alice) delegate`,
    );
    await expect(
      page.locator(
@@ -339,7 +339,7 @@ test("peer and branch switching", async ({ page }) => {
    await expect(page.getByTitle("Change peer")).toHaveText(
      `did:key:${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(
        -6,
-
      )}`,
+
      )} (bob)`,
    );
    await expect(page.getByTitle("Change peer")).not.toHaveText("delegate");

modified tests/e2e/project/commits.spec.ts
@@ -20,7 +20,7 @@ test("peer and branch switching", async ({ page }) => {
    await expect(page.getByTitle("Change peer")).toHaveText(
      `  did:key:${aliceRemote
        .substring(8)
-
        .substring(0, 6)}…${aliceRemote.slice(-6)} (radicle) delegate`,
+
        .substring(0, 6)}…${aliceRemote.slice(-6)} (alice) delegate`,
    );

    await expect(page.getByText("Thursday, November 17, 2022")).toBeVisible();
@@ -122,7 +122,9 @@ test("relative timestamps", async ({ page }) => {
  await page.getByTitle("Change peer").click();
  await page.getByText(bobRemote).click();
  await expect(page.getByTitle("Change peer")).toHaveText(
-
    `did:key:${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(-6)}`,
+
    `did:key:${bobRemote.substring(8).substring(0, 6)}…${bobRemote.slice(
+
      -6,
+
    )} (bob)`,
  );
  const latestCommit = page.locator(".teaser").first();
  await expect(latestCommit).toContainText("Bob Belcher committed now");
modified tests/support/fixtures.ts
@@ -371,6 +371,18 @@ export async function createCobsFixture(peer: RadiclePeer) {
    { cwd: projectFolder },
  );
  await peer.rad(
+
    ["issue", "react", issueOne, "--emoji", "👍", "--to", issueOne],
+
    {
+
      cwd: projectFolder,
+
    },
+
  );
+
  await peer.rad(
+
    ["issue", "react", issueOne, "--emoji", "🎉", "--to", issueOne],
+
    {
+
      cwd: projectFolder,
+
    },
+
  );
+
  await peer.rad(
    ["assign", issueOne, "--to", `did:key:${peer.nodeId}`],
    createOptions(projectFolder, 1),
  );
@@ -384,6 +396,12 @@ export async function createCobsFixture(peer: RadiclePeer) {
    createOptions(projectFolder, 2),
  );
  await peer.rad(
+
    ["issue", "react", issueOne, "--emoji", "🙏", "--to", commentIssueOne],
+
    {
+
      cwd: projectFolder,
+
    },
+
  );
+
  const { stdout: replyIssueOne } = await peer.rad(
    [
      "comment",
      issueOne,
@@ -395,6 +413,12 @@ export async function createCobsFixture(peer: RadiclePeer) {
    createOptions(projectFolder, 3),
  );
  await peer.rad(
+
    ["issue", "react", issueOne, "--emoji", "🚀", "--to", replyIssueOne],
+
    {
+
      cwd: projectFolder,
+
    },
+
  );
+
  await peer.rad(
    [
      "comment",
      issueOne,