JSON to client (#5553)

This commit is contained in:
Tom Moor
2024-05-24 08:29:00 -04:00
committed by GitHub
parent e1e8257df7
commit d51267b8bc
71 changed files with 651 additions and 378 deletions

View File

@@ -1,12 +1,23 @@
import path from "path";
import { readFile } from "fs-extra";
import invariant from "invariant";
import { UserRole } from "@shared/types";
import { CollectionPermission, UserRole } from "@shared/types";
import WelcomeEmail from "@server/emails/templates/WelcomeEmail";
import env from "@server/env";
import {
InvalidAuthenticationError,
AuthenticationProviderDisabledError,
} from "@server/errors";
import { traceFunction } from "@server/logging/tracing";
import { AuthenticationProvider, Collection, Team, User } from "@server/models";
import {
AuthenticationProvider,
Collection,
Document,
Team,
User,
} from "@server/models";
import { DocumentHelper } from "@server/models/helpers/DocumentHelper";
import { sequelize } from "@server/storage/database";
import teamProvisioner from "./teamProvisioner";
import userProvisioner from "./userProvisioner";
@@ -174,7 +185,7 @@ async function accountProvisioner({
}
if (provision) {
await team.provisionFirstCollection(user.id);
await provisionFirstCollection(team, user);
}
}
@@ -186,6 +197,60 @@ async function accountProvisioner({
};
}
async function provisionFirstCollection(team: Team, user: User) {
await sequelize.transaction(async (transaction) => {
const collection = await Collection.create(
{
name: "Welcome",
description: `This collection is a quick guide to what ${env.APP_NAME} is all about. Feel free to delete this collection once your team is up to speed with the basics!`,
teamId: team.id,
createdById: user.id,
sort: Collection.DEFAULT_SORT,
permission: CollectionPermission.ReadWrite,
},
{
transaction,
}
);
// For the first collection we go ahead and create some intitial documents to get
// the team started. You can edit these in /server/onboarding/x.md
const onboardingDocs = [
"Integrations & API",
"Our Editor",
"Getting Started",
"What is Outline",
];
for (const title of onboardingDocs) {
const text = await readFile(
path.join(process.cwd(), "server", "onboarding", `${title}.md`),
"utf8"
);
const document = await Document.create(
{
version: 2,
isWelcome: true,
parentDocumentId: null,
collectionId: collection.id,
teamId: collection.teamId,
lastModifiedById: collection.createdById,
createdById: collection.createdById,
title,
text,
},
{ transaction }
);
document.content = await DocumentHelper.toJSON(document);
await document.publish(collection.createdById, collection.id, {
transaction,
});
}
});
}
export default traceFunction({
spanName: "accountProvisioner",
})(accountProvisioner);

View File

@@ -21,6 +21,7 @@ describe("commentCreator", () => {
type: "paragraph",
content: [
{
content: [],
type: "text",
text: "test",
},

View File

@@ -1,4 +1,5 @@
import { Transaction } from "sequelize";
import { ProsemirrorData } from "@shared/types";
import { Comment, User, Event } from "@server/models";
type Props = {
@@ -6,7 +7,7 @@ type Props = {
/** The user creating the comment */
user: User;
/** The comment as data in Prosemirror schema format */
data: Record<string, any>;
data: ProsemirrorData;
/** The document to comment within */
documentId: string;
/** The parent comment we're replying to, if any */

View File

@@ -1,6 +1,7 @@
import { Transaction } from "sequelize";
import { ProsemirrorData } from "@shared/types";
import { Event, Comment, User } from "@server/models";
import ProsemirrorHelper from "@server/models/helpers/ProsemirrorHelper";
import { ProsemirrorHelper } from "@server/models/helpers/ProsemirrorHelper";
type Props = {
/** The user updating the comment */
@@ -9,8 +10,8 @@ type Props = {
resolvedBy?: User;
/** The existing comment */
comment: Comment;
/** The index to comment the document at */
data: Record<string, any>;
/** The comment data */
data: ProsemirrorData;
/** The IP address of the user creating the comment */
ip: string;
transaction: Transaction;

View File

@@ -2,6 +2,7 @@ import { yDocToProsemirrorJSON } from "@getoutline/y-prosemirror";
import uniq from "lodash/uniq";
import { Node } from "prosemirror-model";
import * as Y from "yjs";
import { ProsemirrorData } from "@shared/types";
import { schema, serializer } from "@server/editor";
import Logger from "@server/logging/Logger";
import { Document, Event } from "@server/models";
@@ -41,7 +42,7 @@ export default async function documentCollaborativeUpdater({
});
const state = Y.encodeStateAsUpdate(ydoc);
const content = yDocToProsemirrorJSON(ydoc, "default");
const content = yDocToProsemirrorJSON(ydoc, "default") as ProsemirrorData;
const node = Node.fromJSON(schema, content);
const text = serializer.serialize(node, undefined);
const isUnchanged = document.text === text;

View File

@@ -1,7 +1,7 @@
import { Transaction } from "sequelize";
import { Optional } from "utility-types";
import { Document, Event, User } from "@server/models";
import TextHelper from "@server/models/helpers/TextHelper";
import { TextHelper } from "@server/models/helpers/TextHelper";
type Props = Optional<
Pick<
@@ -10,6 +10,7 @@ type Props = Optional<
| "urlId"
| "title"
| "text"
| "content"
| "emoji"
| "collectionId"
| "parentDocumentId"

View File

@@ -48,6 +48,7 @@ export default async function documentDuplicator({
emoji: document.emoji,
template: document.template,
title: title ?? document.title,
content: document.content,
text: document.text,
...sharedProperties,
});

View File

@@ -6,8 +6,8 @@ import parseTitle from "@shared/utils/parseTitle";
import { DocumentValidation } from "@shared/validations";
import { traceFunction } from "@server/logging/tracing";
import { User } from "@server/models";
import ProsemirrorHelper from "@server/models/helpers/ProsemirrorHelper";
import TextHelper from "@server/models/helpers/TextHelper";
import { ProsemirrorHelper } from "@server/models/helpers/ProsemirrorHelper";
import { TextHelper } from "@server/models/helpers/TextHelper";
import { DocumentConverter } from "@server/utils/DocumentConverter";
import { InvalidRequestError } from "../errors";

View File

@@ -2,9 +2,10 @@ import uniq from "lodash/uniq";
import { Op, QueryTypes } from "sequelize";
import Logger from "@server/logging/Logger";
import { Document, Attachment } from "@server/models";
import { DocumentHelper } from "@server/models/helpers/DocumentHelper";
import { ProsemirrorHelper } from "@server/models/helpers/ProsemirrorHelper";
import DeleteAttachmentTask from "@server/queues/tasks/DeleteAttachmentTask";
import { sequelize } from "@server/storage/database";
import parseAttachmentIds from "@server/utils/parseAttachmentIds";
export default async function documentPermanentDeleter(documents: Document[]) {
const activeDocument = documents.find((doc) => !doc.deletedAt);
@@ -25,7 +26,9 @@ export default async function documentPermanentDeleter(documents: Document[]) {
for (const document of documents) {
// Find any attachments that are referenced in the text content
const attachmentIdsInText = parseAttachmentIds(document.text);
const attachmentIdsInText = ProsemirrorHelper.parseAttachmentIds(
DocumentHelper.toProsemirror(document)
);
// Find any attachments that were originally uploaded to this document
const attachmentIdsForDocument = (

View File

@@ -1,6 +1,6 @@
import { Transaction } from "sequelize";
import { Event, Document, User } from "@server/models";
import DocumentHelper from "@server/models/helpers/DocumentHelper";
import { DocumentHelper } from "@server/models/helpers/DocumentHelper";
type Props = {
/** The user updating the document */