chore: Export improvements (#4617)

* wip

* i18n
This commit is contained in:
Tom Moor
2022-12-27 09:51:39 -08:00
committed by GitHub
parent ee37ba9355
commit 1b8dd9399c
17 changed files with 99 additions and 26 deletions

View File

@@ -103,6 +103,14 @@ export function ValidationError(message = "Validation failed") {
});
}
export function IncorrectEditionError(
message = "Functionality not available in this edition"
) {
return httpErrors(402, message, {
id: "incorrect_edition",
});
}
export function EditorUpdateError(
message = "The client editor is out of date and must be reloaded"
) {

View File

@@ -2,7 +2,7 @@ import Revision from "@server/models/Revision";
import DocumentHelper from "./DocumentHelper";
describe("toEmailDiff", () => {
test("toEmailDiff", () => {
test("toEmailDiff", async () => {
const before = new Revision({
title: "Title",
text: `
@@ -58,7 +58,7 @@ same on both sides
same on both sides`,
});
const html = DocumentHelper.toEmailDiff(before, after);
const html = await DocumentHelper.toEmailDiff(before, after);
// marks breaks in diff
expect(html).toContain("diff-context-break");

View File

@@ -37,6 +37,8 @@ type HTMLOptions = {
includeStyles?: boolean;
/** Whether to include styles to center diff (defaults to true) */
centered?: boolean;
/** Whether to replace attachment urls with pre-signed versions (defaults to false) */
signedUrls?: boolean;
};
export default class DocumentHelper {
@@ -81,7 +83,7 @@ export default class DocumentHelper {
* @param options Options for the HTML output
* @returns The document title and content as a HTML string
*/
static toHTML(document: Document | Revision, options?: HTMLOptions) {
static async toHTML(document: Document | Revision, options?: HTMLOptions) {
const node = DocumentHelper.toProsemirror(document);
const sheet = new ServerStyleSheet();
let html, styleTags;
@@ -153,7 +155,16 @@ export default class DocumentHelper {
target
);
return dom.serialize();
let output = dom.serialize();
if (options?.signedUrls && document instanceof Document) {
output = await DocumentHelper.attachmentsToSignedUrls(
output,
document.teamId
);
}
return output;
}
/**
@@ -164,17 +175,17 @@ export default class DocumentHelper {
* @param options Options passed to HTML generation
* @returns The diff as a HTML string
*/
static diff(
static async diff(
before: Document | Revision | null,
after: Revision,
options?: HTMLOptions
) {
if (!before) {
return DocumentHelper.toHTML(after, options);
return await DocumentHelper.toHTML(after, options);
}
const beforeHTML = DocumentHelper.toHTML(before, options);
const afterHTML = DocumentHelper.toHTML(after, options);
const beforeHTML = await DocumentHelper.toHTML(before, options);
const afterHTML = await DocumentHelper.toHTML(after, options);
const beforeDOM = new JSDOM(beforeHTML);
const afterDOM = new JSDOM(afterHTML);
@@ -205,7 +216,7 @@ export default class DocumentHelper {
* @param options Options passed to HTML generation
* @returns The diff as a HTML string
*/
static toEmailDiff(
static async toEmailDiff(
before: Document | Revision | null,
after: Revision,
options?: HTMLOptions
@@ -214,7 +225,7 @@ export default class DocumentHelper {
return "";
}
const html = DocumentHelper.diff(before, after, options);
const html = await DocumentHelper.diff(before, after, options);
const dom = new JSDOM(html);
const doc = dom.window.document;

View File

@@ -1,4 +1,5 @@
import env from "@server/env";
import { IncorrectEditionError } from "@server/errors";
import { Team, User } from "@server/models";
import { allow } from "./cancan";
@@ -13,7 +14,7 @@ allow(User, "share", Team, (user, team) => {
allow(User, "createTeam", Team, () => {
if (env.DEPLOYMENT !== "hosted") {
throw new Error("createTeam only available on cloud");
throw IncorrectEditionError("createTeam only available on cloud");
}
});

View File

@@ -20,6 +20,7 @@ export default function present(env: Environment): PublicEnv {
SLACK_APP_ID: env.SLACK_APP_ID,
MAXIMUM_IMPORT_SIZE: env.MAXIMUM_IMPORT_SIZE,
SUBDOMAINS_ENABLED: env.SUBDOMAINS_ENABLED,
PDF_EXPORT_ENABLED: false,
DEFAULT_LANGUAGE: env.DEFAULT_LANGUAGE,
EMAIL_ENABLED: !!env.SMTP_HOST || env.ENVIRONMENT === "development",
GOOGLE_ANALYTICS_ID: env.GOOGLE_ANALYTICS_ID,

View File

@@ -122,7 +122,7 @@ export default class NotificationsProcessor extends BaseProcessor {
// generate the diff html for the email
const before = await revision.previous();
let content = DocumentHelper.toEmailDiff(before, revision, {
let content = await DocumentHelper.toEmailDiff(before, revision, {
includeTitle: false,
centered: false,
});

View File

@@ -7,6 +7,7 @@ import { Op, ScopeOptions, WhereOptions } from "sequelize";
import { TeamPreference } from "@shared/types";
import { subtractDate } from "@shared/utils/date";
import { bytesToHumanReadable } from "@shared/utils/files";
import { RateLimiterStrategy } from "@server/RateLimiter";
import documentCreator from "@server/commands/documentCreator";
import documentImporter from "@server/commands/documentImporter";
import documentLoader from "@server/commands/documentLoader";
@@ -19,8 +20,10 @@ import {
InvalidRequestError,
AuthenticationError,
ValidationError,
IncorrectEditionError,
} from "@server/errors";
import auth from "@server/middlewares/authentication";
import { rateLimiter } from "@server/middlewares/rateLimiter";
import validate from "@server/middlewares/validate";
import {
Backlink,
@@ -433,6 +436,7 @@ router.post(
router.post(
"documents.export",
rateLimiter(RateLimiterStrategy.FivePerMinute),
auth({
optional: true,
}),
@@ -447,7 +451,7 @@ router.post(
shareId,
user,
// We need the collaborative state to generate HTML.
includeState: accept === "text/html",
includeState: !accept?.includes("text/markdown"),
});
let contentType;
@@ -455,7 +459,11 @@ router.post(
if (accept?.includes("text/html")) {
contentType = "text/html";
content = DocumentHelper.toHTML(document);
content = await DocumentHelper.toHTML(document);
} else if (accept?.includes("application/pdf")) {
throw IncorrectEditionError(
"PDF export is not available in the community edition"
);
} else if (accept?.includes("text/markdown")) {
contentType = "text/markdown";
content = DocumentHelper.toMarkdown(document);

View File

@@ -8,7 +8,8 @@ export default function apiWrapper() {
if (
typeof ctx.body === "object" &&
!(ctx.body instanceof stream.Readable)
!(ctx.body instanceof stream.Readable) &&
!(ctx.body instanceof Buffer)
) {
ctx.body = {
...ctx.body,

View File

@@ -30,7 +30,7 @@ router.post("revisions.info", auth(), async (ctx) => {
ctx.body = {
data: await presentRevision(
revision,
DocumentHelper.diff(before, revision, {
await DocumentHelper.diff(before, revision, {
includeTitle: false,
includeStyles: false,
})
@@ -73,7 +73,7 @@ router.post("revisions.diff", auth(), async (ctx) => {
}
const accept = ctx.request.headers["accept"];
const content = DocumentHelper.diff(before, revision);
const content = await DocumentHelper.diff(before, revision);
if (accept?.includes("text/html")) {
ctx.set("Content-Type", "text/html");

View File

@@ -32,7 +32,7 @@ describe("teams.create", () => {
name: "new workspace",
},
});
expect(res.status).toEqual(500);
expect(res.status).toEqual(402);
});
});