mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-10-25 14:50:30 +08:00
Bring reactions to comments and issues
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -370,6 +370,18 @@ export async function createCobsFixture(peer: RadiclePeer) {
|
||||
["bug", "feature-request"],
|
||||
{ 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,
|
||||
@@ -394,6 +412,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",
|
||||
|
||||
Reference in New Issue
Block a user