Files
outline/server/commands/documentUpdater.ts
Apoorv Mishra 6b286d82b8 Ability to choose publish location for a document (#4582)
* feat: initial base structure

* feat: utils for constructing and flattening collection tree

* feat: basic demo to display tree-like structure with virtualization

* feat: make it searchable

* feat: row component

* fix: handle row selection

* fix: scroll jitter

* fix: popover max-height to eliminate extra scroll

* fix: position scrollbar correctly

* fix: do not sort to maintain correct tree-like view

* feat: footer

* fix: scroll to selected item

* fix: deselect item

* fix: display selected location in footer

* fix: deselect item if any upon search trigger

* fix: create draft without collection

* fix: pass down collectionId to all the nodes

* feat: publish document under selected location

* fix: move the doc post publish in case it is supposed to be a nested doc

* fix: wrap text for selected location

* fix: footer background in dark mode and unused css

* fix: popover height in small devices

* fix: no need to spread

* refactor: remove outline

* refactor: border-radius is common

* refactor: remove active and focus

* fix: do not shrink spacer

* fix: scroll list padding with correctly adjusted scrolling

* refactor: use constants

* fix: use padding in favor of spacer

* refactor: border attrs not needed

* refactor: control title padding and icon size centrally

* fix: rename param

* fix: import path

* fix: refactor styles, avoid magic numbers

* fix: type err

* feat: make rows collapsible

* fix: fully expanded without disclosure upon search

* fix: use modal in place of popover

* fix: collapse descendants

* fix: rename PublishPopover to PublishModal

* fix: adjust collapse icon as part of tree view

* fix: enable keyboard navigation

* not sure why collapse and expand shortcuts are not working

* fix: row expansion and search box focus and blur

* fix: remove css hover, handle it via active prop

* fix: discard tree like view for search results

* fix: minor tweaks

* refactor: no need to pass onPublish

* refactor: remove unnecessary attrs from search component

* fix: publish button text

* fix: reset intial scroll offset to 0 on search

* fix: remove search highlights

* fix: clean up search component

* refactor: search and row collapse

* refactor: PublishLocation

* fix: show emoji or star icon if present

* fix: shift focus only from top item

* fix: leading emoji

* fix: baseline text

* fix: make path tertiary

* fix: do not show path for collections

* fix: path text color upon selection

* fix: deleted collection case

* fix: no results found

* fix: space around slash

* Refinement, some small refactors

* fix: Publish shortcut, use Button action

* Allow new document creation from command menu without active collection

* fix: duplicate

* fix: Unneccessary truncation

* fix: Scroll on expand/collapse
Remove wraparound

* fix: tsc

* fix: Horizontal overflow on PublishLocation
Remove pointless moveTo method

* fix: Missing translation

* Remove method indirection
Show expanded collection icon in tree when expanded

* Shrink font size a point

* Remove feature flag

* fix: Path color contrast in light mode
Remove unused expanded/show attributes

* shrink -> collapse, fix expanded disclosure without items after searching

* Mobile styles

* fix: scroll just into view

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-01-23 17:38:24 -08:00

136 lines
3.3 KiB
TypeScript

import { Transaction } from "sequelize";
import { Event, Document, User } from "@server/models";
import DocumentHelper from "@server/models/helpers/DocumentHelper";
type Props = {
/** The user updating the document */
user: User;
/** The existing document */
document: Document;
/** The new title */
title?: string;
/** The new text content */
text?: string;
/** The version of the client editor that was used */
editorVersion?: string;
/** The ID of the template that was used */
templateId?: string | null;
/** If the document should be displayed full-width on the screen */
fullWidth?: boolean;
/** Whether the text be appended to the end instead of replace */
append?: boolean;
/** Whether the document should be published to the collection */
publish?: boolean;
/** The ID of the collection to publish the document to */
collectionId?: string | null;
/** The IP address of the user creating the document */
ip: string;
/** The database transaction to run within */
transaction: Transaction;
};
/**
* This command updates document properties. To update collaborative text state
* use documentCollaborativeUpdater.
*
* @param Props The properties of the document to update
* @returns Document The updated document
*/
export default async function documentUpdater({
user,
document,
title,
text,
editorVersion,
templateId,
fullWidth,
append,
publish,
collectionId,
transaction,
ip,
}: Props): Promise<Document> {
const previousTitle = document.title;
if (title !== undefined) {
document.title = title;
}
if (editorVersion) {
document.editorVersion = editorVersion;
}
if (templateId) {
document.templateId = templateId;
}
if (fullWidth !== undefined) {
document.fullWidth = fullWidth;
}
if (text !== undefined) {
if (user.team?.collaborativeEditing) {
document = DocumentHelper.applyMarkdownToDocument(document, text, append);
} else if (append) {
document.text += text;
} else {
document.text = text;
}
}
const changed = document.changed();
if (publish) {
if (!document.collectionId) {
document.collectionId = collectionId as string;
}
await document.publish(user.id, { transaction });
await Event.create(
{
name: "documents.publish",
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
actorId: user.id,
data: {
title: document.title,
},
ip,
},
{ transaction }
);
} else if (changed) {
document.lastModifiedById = user.id;
await document.save({ transaction });
await Event.create(
{
name: "documents.update",
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
actorId: user.id,
data: {
title: document.title,
},
ip,
},
{ transaction }
);
}
if (document.title !== previousTitle) {
await Event.schedule({
name: "documents.title_change",
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
actorId: user.id,
data: {
previousTitle,
title: document.title,
},
ip,
});
}
return document;
}