From 4912d85198f833477a554f2e8fbd877359687d82 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Thu, 21 Dec 2023 10:35:42 +0100 Subject: [PATCH] Add editing of revisions --- src/views/projects/Cob/Revision.svelte | 48 +++++++++++++++---- src/views/projects/Patch.svelte | 66 +++++++++++++++++--------- tests/e2e/project/patch.spec.ts | 51 ++++++++++++++++++++ 3 files changed, 133 insertions(+), 32 deletions(-) diff --git a/src/views/projects/Cob/Revision.svelte b/src/views/projects/Cob/Revision.svelte index 1150be266..903d1aa4b 100644 --- a/src/views/projects/Cob/Revision.svelte +++ b/src/views/projects/Cob/Revision.svelte @@ -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) | undefined; export let editComment: | ((commentId: string, body: string, embeds: Embed[]) => Promise) | 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)} {/if} - -
- {utils.formatTimestamp(revisionTimestamp)} +
+ {#if canEdit(revisionAuthor.id) && editRevision && revisionState === "read"} + (revisionState = "edit")}> + + + {/if} +
+ {utils.formatTimestamp(revisionTimestamp)} +
- {#if revisionDescription && !first} + {#if editRevision && revisionState !== "read"} + {@const editRevision_ = editRevision} + (revisionState = "read")} + on:submit={async ({ detail: { comment } }) => { + revisionState = "submit"; + try { + await editRevision_(comment); + } finally { + revisionState = "read"; + } + }} /> + {:else if revisionDescription && !first}
@@ -460,6 +489,7 @@
{utils.formatTimestamp(revisionTimestamp)} diff --git a/src/views/projects/Patch.svelte b/src/views/projects/Patch.svelte index 5af7b8314..6d8e41595 100644 --- a/src/views/projects/Patch.svelte +++ b/src/views/projects/Patch.svelte @@ -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 && diff --git a/tests/e2e/project/patch.spec.ts b/tests/e2e/project/patch.spec.ts index 353120474..4376d68ec 100644 --- a/tests/e2e/project/patch.spec.ts +++ b/tests/e2e/project/patch.spec.ts @@ -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(); +});