fix(issue-documents): address greptile review
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -443,8 +443,7 @@ export function issueRoutes(db: Db, storage: StorageService) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const actor = getActorInfo(req);
|
const actor = getActorInfo(req);
|
||||||
const before = await documentsSvc.getIssueDocumentByKey(issue.id, keyParsed.data);
|
const result = await documentsSvc.upsertIssueDocument({
|
||||||
const doc = await documentsSvc.upsertIssueDocument({
|
|
||||||
issueId: issue.id,
|
issueId: issue.id,
|
||||||
key: keyParsed.data,
|
key: keyParsed.data,
|
||||||
title: req.body.title ?? null,
|
title: req.body.title ?? null,
|
||||||
@@ -455,6 +454,7 @@ export function issueRoutes(db: Db, storage: StorageService) {
|
|||||||
createdByAgentId: actor.agentId ?? null,
|
createdByAgentId: actor.agentId ?? null,
|
||||||
createdByUserId: actor.actorType === "user" ? actor.actorId : null,
|
createdByUserId: actor.actorType === "user" ? actor.actorId : null,
|
||||||
});
|
});
|
||||||
|
const doc = result.document;
|
||||||
|
|
||||||
await logActivity(db, {
|
await logActivity(db, {
|
||||||
companyId: issue.companyId,
|
companyId: issue.companyId,
|
||||||
@@ -462,7 +462,7 @@ export function issueRoutes(db: Db, storage: StorageService) {
|
|||||||
actorId: actor.actorId,
|
actorId: actor.actorId,
|
||||||
agentId: actor.agentId,
|
agentId: actor.agentId,
|
||||||
runId: actor.runId,
|
runId: actor.runId,
|
||||||
action: before ? "issue.document_updated" : "issue.document_created",
|
action: result.created ? "issue.document_created" : "issue.document_updated",
|
||||||
entityType: "issue",
|
entityType: "issue",
|
||||||
entityId: issue.id,
|
entityId: issue.id,
|
||||||
details: {
|
details: {
|
||||||
@@ -474,7 +474,7 @@ export function issueRoutes(db: Db, storage: StorageService) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(before ? 200 : 201).json(doc);
|
res.status(result.created ? 201 : 200).json(doc);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/issues/:id/documents/:key/revisions", async (req, res) => {
|
router.get("/issues/:id/documents/:key/revisions", async (req, res) => {
|
||||||
|
|||||||
@@ -297,15 +297,18 @@ export function documentService(db: Db) {
|
|||||||
.where(eq(issueDocuments.documentId, existing.id));
|
.where(eq(issueDocuments.documentId, existing.id));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...existing,
|
created: false as const,
|
||||||
title: input.title ?? null,
|
document: {
|
||||||
format: input.format,
|
...existing,
|
||||||
body: input.body,
|
title: input.title ?? null,
|
||||||
latestRevisionId: revision.id,
|
format: input.format,
|
||||||
latestRevisionNumber: nextRevisionNumber,
|
body: input.body,
|
||||||
updatedByAgentId: input.createdByAgentId ?? null,
|
latestRevisionId: revision.id,
|
||||||
updatedByUserId: input.createdByUserId ?? null,
|
latestRevisionNumber: nextRevisionNumber,
|
||||||
updatedAt: now,
|
updatedByAgentId: input.createdByAgentId ?? null,
|
||||||
|
updatedByUserId: input.createdByUserId ?? null,
|
||||||
|
updatedAt: now,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,21 +363,24 @@ export function documentService(db: Db) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: document.id,
|
created: true as const,
|
||||||
companyId: issue.companyId,
|
document: {
|
||||||
issueId: issue.id,
|
id: document.id,
|
||||||
key,
|
companyId: issue.companyId,
|
||||||
title: document.title,
|
issueId: issue.id,
|
||||||
format: document.format,
|
key,
|
||||||
body: document.latestBody,
|
title: document.title,
|
||||||
latestRevisionId: revision.id,
|
format: document.format,
|
||||||
latestRevisionNumber: 1,
|
body: document.latestBody,
|
||||||
createdByAgentId: document.createdByAgentId,
|
latestRevisionId: revision.id,
|
||||||
createdByUserId: document.createdByUserId,
|
latestRevisionNumber: 1,
|
||||||
updatedByAgentId: document.updatedByAgentId,
|
createdByAgentId: document.createdByAgentId,
|
||||||
updatedByUserId: document.updatedByUserId,
|
createdByUserId: document.createdByUserId,
|
||||||
createdAt: document.createdAt,
|
updatedByAgentId: document.updatedByAgentId,
|
||||||
updatedAt: document.updatedAt,
|
updatedByUserId: document.updatedByUserId,
|
||||||
|
createdAt: document.createdAt,
|
||||||
|
updatedAt: document.updatedAt,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ type DraftState = {
|
|||||||
type DocumentConflictState = {
|
type DocumentConflictState = {
|
||||||
key: string;
|
key: string;
|
||||||
serverDocument: IssueDocument;
|
serverDocument: IssueDocument;
|
||||||
|
localDraft: DraftState;
|
||||||
showRemote: boolean;
|
showRemote: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -189,14 +190,15 @@ export function IssueDocumentsSection({
|
|||||||
const beginEdit = (key: string) => {
|
const beginEdit = (key: string) => {
|
||||||
const doc = sortedDocuments.find((entry) => entry.key === key);
|
const doc = sortedDocuments.find((entry) => entry.key === key);
|
||||||
if (!doc) return;
|
if (!doc) return;
|
||||||
|
const conflictedDraft = documentConflict?.key === key ? documentConflict.localDraft : null;
|
||||||
setFoldedDocumentKeys((current) => current.filter((entry) => entry !== key));
|
setFoldedDocumentKeys((current) => current.filter((entry) => entry !== key));
|
||||||
resetAutosaveState();
|
resetAutosaveState();
|
||||||
setDocumentConflict((current) => current?.key === key ? current : null);
|
setDocumentConflict((current) => current?.key === key ? current : null);
|
||||||
setDraft({
|
setDraft({
|
||||||
key: doc.key,
|
key: conflictedDraft?.key ?? doc.key,
|
||||||
title: doc.title ?? "",
|
title: conflictedDraft?.title ?? doc.title ?? "",
|
||||||
body: doc.body,
|
body: conflictedDraft?.body ?? doc.body,
|
||||||
baseRevisionId: doc.latestRevisionId,
|
baseRevisionId: conflictedDraft?.baseRevisionId ?? doc.latestRevisionId,
|
||||||
isNew: false,
|
isNew: false,
|
||||||
});
|
});
|
||||||
setError(null);
|
setError(null);
|
||||||
@@ -306,6 +308,13 @@ export function IssueDocumentsSection({
|
|||||||
setDocumentConflict({
|
setDocumentConflict({
|
||||||
key: normalizedKey,
|
key: normalizedKey,
|
||||||
serverDocument: latestDocument,
|
serverDocument: latestDocument,
|
||||||
|
localDraft: {
|
||||||
|
key: normalizedKey,
|
||||||
|
title: isPlanKey(normalizedKey) ? "" : normalizedTitle,
|
||||||
|
body: currentDraft.body,
|
||||||
|
baseRevisionId: currentDraft.baseRevisionId,
|
||||||
|
isNew: false,
|
||||||
|
},
|
||||||
showRemote: true,
|
showRemote: true,
|
||||||
});
|
});
|
||||||
setFoldedDocumentKeys((current) => current.filter((key) => key !== normalizedKey));
|
setFoldedDocumentKeys((current) => current.filter((key) => key !== normalizedKey));
|
||||||
@@ -338,10 +347,14 @@ export function IssueDocumentsSection({
|
|||||||
}, [documentConflict, resetAutosaveState]);
|
}, [documentConflict, resetAutosaveState]);
|
||||||
|
|
||||||
const overwriteDocumentFromDraft = useCallback(async (key: string) => {
|
const overwriteDocumentFromDraft = useCallback(async (key: string) => {
|
||||||
if (documentConflict?.key !== key || !draft || draft.key !== key || draft.isNew) return;
|
if (documentConflict?.key !== key) return;
|
||||||
|
const sourceDraft =
|
||||||
|
draft && draft.key === key && !draft.isNew
|
||||||
|
? draft
|
||||||
|
: documentConflict.localDraft;
|
||||||
await commitDraft(
|
await commitDraft(
|
||||||
{
|
{
|
||||||
...draft,
|
...sourceDraft,
|
||||||
baseRevisionId: documentConflict.serverDocument.latestRevisionId,
|
baseRevisionId: documentConflict.serverDocument.latestRevisionId,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -352,6 +365,17 @@ export function IssueDocumentsSection({
|
|||||||
);
|
);
|
||||||
}, [commitDraft, documentConflict, draft]);
|
}, [commitDraft, documentConflict, draft]);
|
||||||
|
|
||||||
|
const keepConflictedDraft = useCallback((key: string) => {
|
||||||
|
if (documentConflict?.key !== key) return;
|
||||||
|
setDraft(documentConflict.localDraft);
|
||||||
|
setDocumentConflict((current) =>
|
||||||
|
current?.key === key
|
||||||
|
? { ...current, showRemote: false }
|
||||||
|
: current,
|
||||||
|
);
|
||||||
|
setError(null);
|
||||||
|
}, [documentConflict]);
|
||||||
|
|
||||||
const copyDocumentBody = useCallback(async (key: string, body: string) => {
|
const copyDocumentBody = useCallback(async (key: string, body: string) => {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(body);
|
await navigator.clipboard.writeText(body);
|
||||||
@@ -727,13 +751,7 @@ export function IssueDocumentsSection({
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() =>
|
onClick={() => keepConflictedDraft(doc.key)}
|
||||||
setDocumentConflict((current) =>
|
|
||||||
current?.key === doc.key
|
|
||||||
? { ...current, showRemote: false }
|
|
||||||
: current,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
Keep my draft
|
Keep my draft
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user