UNPKG

alinea

Version:
223 lines (219 loc) 9.73 kB
import { dist_default } from "../../chunks/chunk-A5O3N2GS.js"; import { useAtomValue, useSetAtom } from "../../chunks/chunk-TOJF2G3X.js"; import "../../chunks/chunk-WJ67RR7S.js"; import "../../chunks/chunk-NZLE2WMY.js"; // src/dashboard/view/EntryEdit.tsx import { Section } from "alinea/core/Section"; import { Type } from "alinea/core/Type"; import { TabsSection } from "alinea/field/tabs/Tabs"; import { TabsHeader } from "alinea/field/tabs/Tabs.view"; import { Button, HStack, Stack, VStack } from "alinea/ui"; import { Main } from "alinea/ui/Main"; import { Statusbar } from "alinea/ui/Statusbar"; import { Tabs } from "alinea/ui/Tabs"; import { IcRoundInsertDriveFile } from "alinea/ui/icons/IcRoundInsertDriveFile"; import { IcRoundLink } from "alinea/ui/icons/IcRoundLink"; import { IcRoundTranslate } from "alinea/ui/icons/IcRoundTranslate"; import { Suspense, useEffect, useRef, useState } from "react"; import { FormProvider } from "../atoms/FormAtoms.js"; import { useRouteBlocker } from "../atoms/RouterAtoms.js"; import { InputForm } from "../editor/InputForm.js"; import { useConfig } from "../hook/UseConfig.js"; import { useDashboard } from "../hook/UseDashboard.js"; import { EntryEditorProvider } from "../hook/UseEntryEditor.js"; import { useLocale } from "../hook/UseLocale.js"; import { useNav } from "../hook/UseNav.js"; import { SuspenseBoundary } from "../util/SuspenseBoundary.js"; import { Modal } from "../view/Modal.js"; // src/dashboard/view/EntryEdit.module.scss var EntryEdit_module_default = { "root": "alinea-EntryEdit", "root-tabs": "alinea-EntryEdit-tabs", "rootTabs": "alinea-EntryEdit-tabs" }; // src/dashboard/view/EntryEdit.tsx import { Preview } from "./Preview.js"; import { useSidebar } from "./Sidebar.js"; import { EntryDiff } from "./diff/EntryDiff.js"; import { EditMode } from "./entry/EditModeToggle.js"; import { EntryHeader } from "./entry/EntryHeader.js"; import { EntryHistory } from "./entry/EntryHistory.js"; import { EntryNotice } from "./entry/EntryNotice.js"; import { EntryPreview } from "./entry/EntryPreview.js"; import { EntryTitle } from "./entry/EntryTitle.js"; import { FieldToolbar } from "./entry/FieldToolbar.js"; import { BrowserPreviewMetaProvider } from "./preview/BrowserPreview.js"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var styles = dist_default(EntryEdit_module_default); function ShowChanges({ editor }) { const draftEntry = useAtomValue(editor.draftEntry); const hasChanges = useAtomValue(editor.hasChanges); const compareTo = hasChanges ? editor.activeVersion : editor.statuses[editor.availableStatuses.find((status) => status !== "draft")]; return /* @__PURE__ */ jsx(EntryDiff, { entryA: compareTo, entryB: draftEntry }); } function EntryEdit({ editor }) { const { alineaDev } = useDashboard(); const locale = useLocale(); const config = useConfig(); const { isPreviewOpen } = useSidebar(); const nav = useNav(); const [rootTab, setRootTab] = useState(); const mode = useAtomValue(editor.editMode); const hasChanges = useAtomValue(editor.hasChanges); const selectedStatus = useAtomValue(editor.selectedStatus); const ref = useRef(null); useEffect(() => { ref.current?.scrollTo({ top: 0 }); }, [editor.entryId, mode, selectedStatus]); const { isBlocking, nextRoute, confirm, cancel } = useRouteBlocker( "Are you sure you want to discard changes?", !editor.untranslated && hasChanges ); const isNavigationChange = nextRoute?.data.editor?.entryId !== editor.entryId; const form = useAtomValue(editor.form); const saveDraft = useSetAtom(editor.saveDraft); const publishDraft = useSetAtom(editor.publishDraft); const publishEdits = useSetAtom(editor.publishEdits); const discardEdits = useSetAtom(editor.discardEdits); const showHistory = useAtomValue(editor.showHistory); const saveTranslation = useSetAtom(editor.saveTranslation); const previewRevision = useAtomValue(editor.previewRevision); const preview = editor.preview; const translate = () => saveTranslation(locale); useEffect(() => { function listener(e) { const isControl = e.ctrlKey || e.metaKey; if (isControl && e.key === "s") { e.preventDefault(); if (previewRevision) { alert("todo"); return; } if (editor.untranslated && hasChanges) { translate(); } else if (config.enableDrafts) { if (hasChanges) saveDraft(); else if (selectedStatus === "draft") publishDraft(); } else { if (hasChanges) publishEdits(); } } } document.addEventListener("keydown", listener); return () => { document.removeEventListener("keydown", listener); }; }, [editor, hasChanges, saveDraft, config.enableDrafts]); const sections = Type.sections(editor.type); const hasRootTabs = sections.length === 1 && sections[0][Section.Data] instanceof TabsSection; const tabs = hasRootTabs ? sections[0][Section.Data] : void 0; const visibleTypes = tabs?.types.filter((type) => !Type.isHidden(type)); let selectedRootTab = 0; if (hasRootTabs && visibleTypes && rootTab !== void 0) { selectedRootTab = rootTab; if (rootTab >= visibleTypes.length) selectedRootTab = 0; } useEffect(() => { if (isBlocking && !isNavigationChange) confirm?.(); }, [isBlocking, isNavigationChange, confirm]); return /* @__PURE__ */ jsxs(BrowserPreviewMetaProvider, { entryId: editor.entryId, children: [ alineaDev && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(Statusbar.Slot, { children: /* @__PURE__ */ jsxs(Statusbar.Status, { icon: IcRoundInsertDriveFile, children: [ editor.activeVersion.filePath, " @", " ", editor.activeVersion.fileHash.slice(0, 8) ] }) }), /* @__PURE__ */ jsx(Statusbar.Slot, { children: /* @__PURE__ */ jsx(Statusbar.Status, { icon: IcRoundLink, children: editor.activeVersion.url }) }) ] }), isBlocking && isNavigationChange && /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => cancel(), children: /* @__PURE__ */ jsxs(VStack, { gap: 30, children: [ /* @__PURE__ */ jsxs("p", { children: [ "This document was changed,", /* @__PURE__ */ jsx("br", {}), "would you like to save your changes?" ] }), /* @__PURE__ */ jsx(HStack, { as: "footer", children: /* @__PURE__ */ jsx(Stack.Right, { children: /* @__PURE__ */ jsxs(HStack, { gap: 16, children: [ /* @__PURE__ */ jsx( Button, { outline: true, type: "button", onClick: () => { discardEdits(); confirm(); }, children: "Discard my changes" } ), config.enableDrafts ? /* @__PURE__ */ jsx( Button, { onClick: () => { saveDraft(); confirm(); }, children: "Save as draft" } ) : /* @__PURE__ */ jsx( Button, { onClick: () => { publishEdits(); confirm(); }, children: "Publish changes" } ) ] }) }) }) ] }) }), /* @__PURE__ */ jsx(Main, { scrollRef: ref, className: styles.root(), children: /* @__PURE__ */ jsxs(FieldToolbar.Provider, { children: [ /* @__PURE__ */ jsx(EntryHeader, { editor }), showHistory && /* @__PURE__ */ jsx(EntryHistory, { editor }), /* @__PURE__ */ jsxs( Tabs.Root, { style: { flex: 1 }, selectedIndex: selectedRootTab, onChange: (index) => setRootTab(index), children: [ /* @__PURE__ */ jsx( EntryTitle, { editor, backLink: editor.activeVersion.parentId ? nav.entry({ id: editor.activeVersion.parentId, workspace: editor.activeVersion.workspace }) : nav.entry({ id: void 0 }), children: hasRootTabs && /* @__PURE__ */ jsx("div", { className: styles.root.tabs(), children: /* @__PURE__ */ jsx(TabsHeader, { backdrop: false, section: sections[0] }) }) } ), /* @__PURE__ */ jsxs(Main.Container, { children: [ editor.untranslated && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx( EntryNotice, { icon: IcRoundTranslate, title: "Untranslated", variant: "untranslated", children: editor.parentNeedsTranslation ? "Translate the parent page first." : "Enter the details below and save to start translating." } ) }), /* @__PURE__ */ jsx(EntryEditorProvider, { editor, children: /* @__PURE__ */ jsx(SuspenseBoundary, { name: "input form", children: mode === EditMode.Diff ? /* @__PURE__ */ jsx(ShowChanges, { editor }) : hasRootTabs && visibleTypes ? /* @__PURE__ */ jsx(Tabs.Panels, { children: visibleTypes.map((type, i) => { return /* @__PURE__ */ jsx(FormProvider, { form, children: /* @__PURE__ */ jsx(Tabs.Panel, { unmount: false, tabIndex: i, children: /* @__PURE__ */ jsx(InputForm, { type }) }) }, i); }) }) : /* @__PURE__ */ jsx(VStack, { gap: 18, children: /* @__PURE__ */ jsx(InputForm, { form }) }) }) }) ] }) ] } ), /* @__PURE__ */ jsx(FieldToolbar.Root, {}) ] }) }), preview && /* @__PURE__ */ jsx(Preview, { children: /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(EntryPreview, { preview, editor }) }) }) ] }); } export { EntryEdit };