mirror of
https://github.com/outline/outline.git
synced 2026-06-13 03:14:59 +03:00
185 lines
5.4 KiB
TypeScript
185 lines
5.4 KiB
TypeScript
import copy from "copy-to-clipboard";
|
|
import { LinkIcon, RestoreIcon, TrashIcon, DownloadIcon } from "outline-icons";
|
|
import { matchPath } from "react-router-dom";
|
|
import { toast } from "sonner";
|
|
import { ExportContentType } from "@shared/types";
|
|
import Revision from "~/models/Revision";
|
|
import stores from "~/stores";
|
|
import { createAction, createActionWithChildren } from "~/actions";
|
|
import { RevisionSection } from "~/actions/sections";
|
|
import env from "~/env";
|
|
import history from "~/utils/history";
|
|
import {
|
|
documentHistoryPath,
|
|
matchDocumentHistory,
|
|
urlify,
|
|
} from "~/utils/routeHelpers";
|
|
|
|
export const restoreRevision = createAction({
|
|
name: ({ t }) => t("Restore"),
|
|
analyticsName: "Restore revision",
|
|
icon: <RestoreIcon />,
|
|
section: RevisionSection,
|
|
visible: ({ activeDocumentId }) =>
|
|
!!activeDocumentId && stores.policies.abilities(activeDocumentId).update,
|
|
perform: async ({ event, location, activeDocumentId, getActiveModel }) => {
|
|
event?.preventDefault();
|
|
if (!activeDocumentId) {
|
|
return;
|
|
}
|
|
|
|
const match = matchPath<{ revisionId: string }>(location.pathname, {
|
|
path: matchDocumentHistory,
|
|
});
|
|
const revisionId = getActiveModel(Revision)?.id ?? match?.params.revisionId;
|
|
if (!revisionId) {
|
|
return;
|
|
}
|
|
|
|
const document = stores.documents.get(activeDocumentId);
|
|
if (!document) {
|
|
return;
|
|
}
|
|
|
|
history.push(document.url, {
|
|
restore: true,
|
|
revisionId,
|
|
});
|
|
},
|
|
});
|
|
|
|
export const deleteRevision = createAction({
|
|
name: ({ t }) => t("Delete"),
|
|
analyticsName: "Delete revision",
|
|
icon: <TrashIcon />,
|
|
section: RevisionSection,
|
|
dangerous: true,
|
|
visible: ({ activeDocumentId }) =>
|
|
!!activeDocumentId && stores.policies.abilities(activeDocumentId).update,
|
|
perform: async ({ t, event, location, activeDocumentId }) => {
|
|
event?.preventDefault();
|
|
if (!activeDocumentId) {
|
|
return;
|
|
}
|
|
|
|
const document = stores.documents.get(activeDocumentId);
|
|
if (!document) {
|
|
return;
|
|
}
|
|
|
|
const match = matchPath<{ revisionId: string }>(location.pathname, {
|
|
path: matchDocumentHistory,
|
|
});
|
|
const revisionId = match?.params.revisionId;
|
|
if (revisionId) {
|
|
const revision = stores.revisions.get(revisionId);
|
|
await revision?.delete();
|
|
toast.success(t("This version of the document was deleted"));
|
|
history.push(documentHistoryPath(document));
|
|
}
|
|
},
|
|
});
|
|
|
|
export const copyLinkToRevision = (revisionId: string) =>
|
|
createAction({
|
|
name: ({ t }) => t("Copy link"),
|
|
analyticsName: "Copy link to revision",
|
|
icon: <LinkIcon />,
|
|
section: RevisionSection,
|
|
perform: async ({ activeDocumentId, t }) => {
|
|
if (!activeDocumentId) {
|
|
return;
|
|
}
|
|
|
|
const document = stores.documents.get(activeDocumentId);
|
|
if (!document) {
|
|
return;
|
|
}
|
|
|
|
const url = urlify(documentHistoryPath(document, revisionId));
|
|
|
|
copy(url, {
|
|
format: "text/plain",
|
|
onCopy: () => {
|
|
toast.message(t("Link copied"));
|
|
},
|
|
});
|
|
},
|
|
});
|
|
|
|
export const downloadRevisionAsHTML = (revisionId: string) =>
|
|
createAction({
|
|
name: ({ t }) => t("HTML"),
|
|
analyticsName: "Download revision as HTML",
|
|
section: RevisionSection,
|
|
keywords: "html export",
|
|
icon: <DownloadIcon />,
|
|
iconInContextMenu: false,
|
|
visible: ({ activeDocumentId }) =>
|
|
!!activeDocumentId &&
|
|
stores.policies.abilities(activeDocumentId).download,
|
|
perform: async () => {
|
|
const revision = stores.revisions.get(revisionId);
|
|
await revision?.download(ExportContentType.Html);
|
|
},
|
|
});
|
|
|
|
export const downloadRevisionAsPDF = (revisionId: string) =>
|
|
createAction({
|
|
name: ({ t }) => t("PDF"),
|
|
analyticsName: "Download revision as PDF",
|
|
section: RevisionSection,
|
|
keywords: "export",
|
|
icon: <DownloadIcon />,
|
|
iconInContextMenu: false,
|
|
visible: ({ activeDocumentId }) =>
|
|
!!(
|
|
activeDocumentId &&
|
|
stores.policies.abilities(activeDocumentId).download &&
|
|
env.PDF_EXPORT_ENABLED
|
|
),
|
|
perform: ({ t }) => {
|
|
const id = toast.loading(`${t("Exporting")}…`);
|
|
const revision = stores.revisions.get(revisionId);
|
|
return revision
|
|
?.download(ExportContentType.Pdf)
|
|
.finally(() => id && toast.dismiss(id));
|
|
},
|
|
});
|
|
|
|
export const downloadRevisionAsMarkdown = (revisionId: string) =>
|
|
createAction({
|
|
name: ({ t }) => t("Markdown"),
|
|
analyticsName: "Download revision as Markdown",
|
|
section: RevisionSection,
|
|
keywords: "md markdown export",
|
|
icon: <DownloadIcon />,
|
|
iconInContextMenu: false,
|
|
visible: ({ activeDocumentId }) =>
|
|
!!activeDocumentId &&
|
|
stores.policies.abilities(activeDocumentId).download,
|
|
perform: async () => {
|
|
const revision = stores.revisions.get(revisionId);
|
|
await revision?.download(ExportContentType.Markdown);
|
|
},
|
|
});
|
|
|
|
export const downloadRevision = (revisionId: string) =>
|
|
createActionWithChildren({
|
|
name: ({ t, isMenu }) => (isMenu ? t("Download") : t("Download revision")),
|
|
analyticsName: "Download revision",
|
|
section: RevisionSection,
|
|
icon: <DownloadIcon />,
|
|
keywords: "export",
|
|
visible: ({ activeDocumentId }) =>
|
|
!!activeDocumentId &&
|
|
stores.policies.abilities(activeDocumentId).download,
|
|
children: [
|
|
downloadRevisionAsHTML(revisionId),
|
|
downloadRevisionAsPDF(revisionId),
|
|
downloadRevisionAsMarkdown(revisionId),
|
|
],
|
|
});
|
|
|
|
export const rootRevisionActions = [];
|