Add editing of revisions

This commit is contained in:
Sebastian Martinez
2023-12-21 20:35:11 +01:00
parent ecba243526
commit 4912d85198
3 changed files with 133 additions and 32 deletions
+39 -9
View File
@@ -19,6 +19,7 @@
import DropdownListItem from "@app/components/DropdownList/DropdownListItem.svelte";
import ErrorMessage from "@app/components/ErrorMessage.svelte";
import ExpandButton from "@app/components/ExpandButton.svelte";
import ExtendedTextarea from "@app/components/ExtendedTextarea.svelte";
import IconButton from "@app/components/IconButton.svelte";
import IconSmall from "@app/components/IconSmall.svelte";
import Link from "@app/components/Link.svelte";
@@ -46,7 +47,8 @@
export let previousRevId: string | undefined = undefined;
export let previousRevOid: string | undefined = undefined;
export let first: boolean;
export let canEditComment: (author: string) => true | undefined;
export let canEdit: (author: string) => true | undefined;
export let editRevision: ((description: string) => Promise<void>) | undefined;
export let editComment:
| ((commentId: string, body: string, embeds: Embed[]) => Promise<void>)
| undefined;
@@ -95,9 +97,12 @@
}
}
type State = "read" | "submit" | "edit";
let response: DiffResponse | undefined = undefined;
let error: any | undefined = undefined;
let loading: boolean = false;
let revisionState: State = "read";
onMount(async () => {
try {
@@ -194,7 +199,6 @@
font-size: var(--font-size-small);
}
.timestamp {
margin-left: auto;
font-size: var(--font-size-small);
color: var(--color-fill-gray);
}
@@ -382,14 +386,39 @@
{utils.formatObjectId(revisionId)}
</span>
{/if}
<div
class="timestamp"
title={utils.absoluteTimestamp(revisionTimestamp)}>
{utils.formatTimestamp(revisionTimestamp)}
<div style="display: flex; gap: 0.5rem; margin-left: auto;">
{#if canEdit(revisionAuthor.id) && editRevision && revisionState === "read"}
<IconButton
title="edit revision"
on:click={() => (revisionState = "edit")}>
<IconSmall name="edit" />
</IconButton>
{/if}
<div
class="timestamp"
title={utils.absoluteTimestamp(revisionTimestamp)}>
{utils.formatTimestamp(revisionTimestamp)}
</div>
</div>
</div>
{#if revisionDescription && !first}
{#if editRevision && revisionState !== "read"}
{@const editRevision_ = editRevision}
<ExtendedTextarea
rawPath={rawPath(revisionId)}
body={revisionDescription}
submitCaption="Save"
submitInProgress={revisionState === "submit"}
placeholder="Leave a description"
on:close={() => (revisionState = "read")}
on:submit={async ({ detail: { comment } }) => {
revisionState = "submit";
try {
await editRevision_(comment);
} finally {
revisionState = "read";
}
}} />
{:else if revisionDescription && !first}
<div class="revision-description txt-small">
<Markdown
rawPath={rawPath(projectHead)}
@@ -433,7 +462,7 @@
enableAttachments
thread={element.inner}
rawPath={rawPath(projectHead)}
{canEditComment}
canEditComment={canEdit}
{editComment}
{createReply}
{handleReaction} />
@@ -460,6 +489,7 @@
</span>
<div
style="margin-left: auto"
class="timestamp"
title={utils.absoluteTimestamp(revisionTimestamp)}>
{utils.formatTimestamp(revisionTimestamp)}
+43 -23
View File
@@ -93,22 +93,8 @@
["Convert to draft", { status: "draft" }],
];
async function editPatch(
sessionId: string,
title: string,
description: string,
) {
async function editPatch(sessionId: string, title: string) {
try {
await api.project.updatePatch(
project.id,
patch.id,
{
type: "revision.edit",
revision: patch.id,
description,
},
sessionId,
);
await api.project.updatePatch(
project.id,
patch.id,
@@ -120,9 +106,43 @@
modal.show({
component: ErrorModal,
props: {
title: "Patch editing failed",
title: "Patch title editing failed",
subtitle: [
"There was an error while updating the patch.",
"There was an error while updating the title of this patch.",
"Check your radicle-httpd logs for details.",
],
error: {
message: error.message,
stack: error.stack,
},
},
});
}
} finally {
await refreshPatch();
}
}
async function editRevision(
sessionId: string,
revisionId: string,
description: string,
) {
try {
await api.project.updatePatch(
project.id,
patch.id,
{ type: "revision.edit", revision: revisionId, description },
sessionId,
);
} catch (error) {
if (error instanceof Error) {
modal.show({
component: ErrorModal,
props: {
title: "Revision editing failed",
subtitle: [
"There was an error while updating the revision.",
"Check your radicle-httpd logs for details.",
],
error: {
@@ -693,15 +713,13 @@
submitCaption="Save"
submitInProgress={patchState === "submit"}
placeholder="Leave a description"
on:close={() => {
patchState = "read";
void refreshPatch();
}}
on:close={() => (patchState = "read")}
on:submit={async ({ detail: { comment } }) => {
patchState = "submit";
if (session) {
try {
await editPatch(session.id, patch.title, comment);
await editPatch(session.id, patch.title);
await editRevision(session.id, patch.id, comment);
} finally {
patchState = "read";
}
@@ -850,11 +868,13 @@
projectHead={project.head}
{...revision}
first={index === 0}
canEditComment={partial(
canEdit={partial(
role.isDelegateOrAuthor,
session?.publicKey,
project.delegates,
)}
editRevision={session &&
partial(editRevision, session.id, revision.revisionId)}
editComment={session &&
partial(editComment, session.id, revision.revisionId)}
handleReaction={session &&
+51
View File
@@ -226,3 +226,54 @@ test("edit patch", async ({ page, authenticatedPeer }) => {
page.getByText("This is a modified patch description"),
).toBeVisible();
});
test("edit revision", async ({ page, authenticatedPeer }) => {
const { rid, projectFolder } = await createProject(authenticatedPeer, {
name: "edit-revision",
});
await authenticatedPeer.git(["switch", "-c", "edit-revision"], {
cwd: projectFolder,
});
await authenticatedPeer.git(
[
"commit",
"--allow-empty",
"-m",
"Some patch title",
"-m",
"This should be a description",
],
{
cwd: projectFolder,
},
);
const patchId = extractPatchId(
await authenticatedPeer.git(["push", "rad", "HEAD:refs/patches"], {
cwd: projectFolder,
}),
);
await authenticatedPeer.git(
[
"commit",
"--allow-empty",
"-m",
"Let's create a new revision",
"-m",
"More descriptions",
],
{
cwd: projectFolder,
},
);
await authenticatedPeer.git(["push", "rad"], { cwd: projectFolder });
await page.goto(`${authenticatedPeer.ridUrl(rid)}/patches/${patchId}`);
await page.getByRole("button", { name: "edit revision" }).click();
await page
.getByPlaceholder("Leave a description")
.fill("This is an edited second revision");
await page.getByRole("button", { name: "Save" }).click();
await expect(
page.getByText("This is an edited second revision"),
).toBeVisible();
});