fix: Sidebar jumps when publish or unpublish document (#4706)

* Return updated collection in API response for documents.unpublish and documents.update
Allows for improved UX on clientside

* test

* tsc

* tsc
This commit is contained in:
Tom Moor
2023-01-15 09:01:06 -05:00
committed by GitHub
parent 31f743eb4c
commit 0c269081d9
4 changed files with 70 additions and 24 deletions

View File

@@ -194,8 +194,17 @@ const Link = styled(NavLink)<{
${(props) =>
props.$isDraft &&
css`
padding: 4px 14px;
border: 1px dashed ${props.theme.sidebarDraftBorder};
&:after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
border-radius: 4px;
border: 1.5px dashed ${props.theme.sidebarDraftBorder};
}
`}
svg {

View File

@@ -686,15 +686,24 @@ export default class DocumentsStore extends BaseStore<Document> {
lastRevision: number;
}
) {
const document = await super.update(params, options);
this.isSaving = true;
// Because the collection object contains the url and title
// we need to ensure they are updated there as well.
const collection = this.getCollectionForDocument(document);
if (collection) {
collection.updateDocument(document);
try {
const res = await client.post(`/${this.apiEndpoint}.update`, {
...params,
...options,
apiVersion: 2,
});
invariant(res?.data, "Data should be available");
this.addPolicies(res.policies);
const document = this.add(res.data.document);
const collection = this.getCollectionForDocument(document);
collection?.updateFromJson(res.data.collection);
return document;
} finally {
this.isSaving = false;
}
return document;
}
@action
@@ -763,16 +772,16 @@ export default class DocumentsStore extends BaseStore<Document> {
unpublish = async (document: Document) => {
const res = await client.post("/documents.unpublish", {
id: document.id,
apiVersion: 2,
});
runInAction("Document#unpublish", () => {
invariant(res?.data, "Data should be available");
document.updateFromJson(res.data);
document.updateFromJson(res.data.document);
const collection = this.getCollectionForDocument(document);
collection?.updateFromJson(res.data.collection);
this.addPolicies(res.policies);
});
const collection = this.getCollectionForDocument(document);
if (collection) {
collection.refresh();
}
};
star = (document: Document) => {

View File

@@ -826,6 +826,7 @@ router.post(
templateId,
collectionId,
append,
apiVersion,
} = ctx.input.body;
const editorVersion = ctx.headers["x-editor-version"] as string | undefined;
const { user } = ctx.state.auth;
@@ -845,8 +846,6 @@ router.post(
"collectionId is required to publish a draft without collection"
);
collection = await Collection.findByPk(collectionId as string);
} else {
collection = document.collection;
}
authorize(user, "publish", collection);
}
@@ -855,7 +854,7 @@ router.post(
throw InvalidRequestError("Document has changed since last revision");
}
const updatedDocument = await sequelize.transaction(async (transaction) => {
await sequelize.transaction((transaction) => {
return documentUpdater({
document,
user,
@@ -872,12 +871,27 @@ router.post(
});
});
updatedDocument.updatedBy = user;
updatedDocument.collection = collection;
document.updatedBy = user;
// Original collection has membership data for calculating policies so we
// use that collection and just update the documentStructure for performance
if (collection) {
const { documentStructure } = collection;
document.collection = collection;
document.collection.documentStructure = documentStructure;
}
ctx.body = {
data: await presentDocument(updatedDocument),
policies: presentPolicies(user, [updatedDocument]),
data:
apiVersion === 2
? {
document: await presentDocument(document),
collection: document.collection
? presentCollection(document.collection)
: undefined,
}
: await presentDocument(document),
policies: presentPolicies(user, [document]),
};
}
);
@@ -1043,7 +1057,7 @@ router.post(
auth(),
validate(T.DocumentsUnpublishSchema),
async (ctx: APIContext<T.DocumentsUnpublishReq>) => {
const { id } = ctx.input.body;
const { id, apiVersion } = ctx.input.body;
const { user } = ctx.state.auth;
const document = await Document.findByPk(id, {
@@ -1072,7 +1086,15 @@ router.post(
});
ctx.body = {
data: await presentDocument(document),
data:
apiVersion === 2
? {
document: await presentDocument(document),
collection: document.collection
? presentCollection(document.collection)
: undefined,
}
: await presentDocument(document),
policies: presentPolicies(user, [document]),
};
}

View File

@@ -201,6 +201,9 @@ export const DocumentsUpdateSchema = BaseSchema.extend({
/** Boolean to denote if text should be appended */
append: z.boolean().optional(),
/** Version of the API to be used */
apiVersion: z.number().optional(),
}),
}).refine((req) => !(req.body.append && !req.body.text), {
message: "text is required while appending",
@@ -241,7 +244,10 @@ export const DocumentsDeleteSchema = BaseSchema.extend({
export type DocumentsDeleteReq = z.infer<typeof DocumentsDeleteSchema>;
export const DocumentsUnpublishSchema = BaseSchema.extend({
body: BaseIdSchema,
body: BaseIdSchema.extend({
/** Version of the API to be used */
apiVersion: z.number().optional(),
}),
});
export type DocumentsUnpublishReq = z.infer<typeof DocumentsUnpublishSchema>;