alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
220 lines (216 loc) • 9.76 kB
JavaScript
import {
useAtomValue,
useSetAtom
} from "../../chunks/chunk-WF77DMLN.js";
import "../../chunks/chunk-OBOPLPUQ.js";
import "../../chunks/chunk-U5RRZUYZ.js";
// src/dashboard/view/EntryEdit.tsx
import { EntryPhase, Section, Type } from "alinea/core";
import { FormProvider } from "alinea/dashboard";
import { InputForm } from "alinea/dashboard/editor/InputForm";
import { Modal } from "alinea/dashboard/view/Modal";
import { TabsHeader, TabsSection } from "alinea/input/tabs/Tabs.browser";
import { Button, HStack, Stack, VStack, fromModule } from "alinea/ui";
import { Main } from "alinea/ui/Main";
import { Statusbar } from "alinea/ui/Statusbar";
import { Tabs } from "alinea/ui/Tabs";
import { IcOutlineTableRows } from "alinea/ui/icons/IcOutlineTableRows";
import { IcRoundInsertDriveFile } from "alinea/ui/icons/IcRoundInsertDriveFile";
import { IcRoundTranslate } from "alinea/ui/icons/IcRoundTranslate";
import { useEffect, useRef } from "react";
import { useRouteBlocker } from "../atoms/RouterAtoms.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";
// 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 { 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 { Fragment, jsx, jsxs } from "react/jsx-runtime";
var styles = fromModule(EntryEdit_module_default);
function ShowChanges({ editor }) {
const draftEntry = useAtomValue(editor.draftEntry);
const hasChanges = useAtomValue(editor.hasChanges);
const compareTo = hasChanges ? editor.activeVersion : editor.phases[editor.availablePhases.find((phase) => phase !== EntryPhase.Draft)];
return /* @__PURE__ */ jsx(EntryDiff, { entryA: compareTo, entryB: draftEntry });
}
function EntryEdit({ editor }) {
const { alineaDev } = useDashboard();
const locale = useLocale();
const { preview, enableDrafts } = useConfig();
const { isPreviewOpen } = useSidebar();
const nav = useNav();
const mode = useAtomValue(editor.editMode);
const hasChanges = useAtomValue(editor.hasChanges);
const selectedPhase = useAtomValue(editor.selectedPhase);
const ref = useRef(null);
useEffect(() => {
ref.current?.scrollTo({ top: 0 });
}, [editor.entryId, mode, selectedPhase]);
const untranslated = locale && locale !== editor.activeVersion.locale;
const { isBlocking, nextRoute, confirm, cancel } = useRouteBlocker(
"Are you sure you want to discard changes?",
!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 translate = () => saveTranslation(locale);
useEffect(() => {
function listener(e) {
if (e.ctrlKey && e.key === "s") {
e.preventDefault();
if (previewRevision) {
alert("todo");
return;
}
if (untranslated && hasChanges) {
translate();
} else if (enableDrafts) {
if (hasChanges)
saveDraft();
else if (selectedPhase === EntryPhase.Draft)
publishDraft();
} else {
if (hasChanges)
publishEdits();
}
}
}
document.addEventListener("keydown", listener);
return () => {
document.removeEventListener("keydown", listener);
};
}, [editor, hasChanges, saveDraft, 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];
const visibleTypes = tabs && tabs.types.filter((type) => !Type.meta(type).isHidden);
useEffect(() => {
if (isBlocking && !isNavigationChange)
confirm?.();
}, [isBlocking, isNavigationChange, confirm]);
return /* @__PURE__ */ jsxs(Fragment, { children: [
alineaDev && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Statusbar.Slot, { children: /* @__PURE__ */ jsxs(Statusbar.Status, { children: [
"File path: ",
editor.activeVersion.filePath
] }) }),
/* @__PURE__ */ jsx(Statusbar.Slot, { children: /* @__PURE__ */ jsxs(Statusbar.Status, { children: [
"Parent dir: ",
editor.activeVersion.parentDir
] }) }),
/* @__PURE__ */ jsx(Statusbar.Slot, { children: /* @__PURE__ */ jsxs(Statusbar.Status, { children: [
"Children dir: ",
editor.activeVersion.childrenDir
] }) }),
/* @__PURE__ */ jsx(Statusbar.Slot, { children: /* @__PURE__ */ jsxs(Statusbar.Status, { children: [
"Url: ",
editor.activeVersion.url
] }) }),
/* @__PURE__ */ jsx(Statusbar.Slot, { children: /* @__PURE__ */ jsx(Statusbar.Status, { icon: IcRoundInsertDriveFile, children: editor.activeVersion.fileHash }) }),
/* @__PURE__ */ jsx(Statusbar.Slot, { children: /* @__PURE__ */ jsx(Statusbar.Status, { icon: IcOutlineTableRows, children: editor.activeVersion.rowHash }) })
] }),
isBlocking && isNavigationChange && /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => cancel(), children: /* @__PURE__ */ jsxs(VStack, { gap: 30, children: [
/* @__PURE__ */ jsxs("p", { children: [
"This document was changed, would you like to save your changes",
isNavigationChange ? " before navigating" : "",
"?"
] }),
/* @__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"
}
),
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, { children: [
/* @__PURE__ */ jsx(
EntryTitle,
{
editor,
backLink: editor.activeVersion.parent ? nav.entry({
entryId: editor.activeVersion.parent,
workspace: editor.activeVersion.workspace
}) : nav.entry({ entryId: 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: [
untranslated && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
EntryNotice,
{
icon: IcRoundTranslate,
title: "Untranslated",
variant: "untranslated",
children: [
"This page has not yet been translated to this language,",
/* @__PURE__ */ jsx("br", {}),
editor.parentNeedsTranslation ? "please translate the parent page first." : "please 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, { tabIndex: i, children: /* @__PURE__ */ jsx(InputForm, { type }) }) }, i);
}) }) : /* @__PURE__ */ jsx(VStack, { gap: 18, children: /* @__PURE__ */ jsx(InputForm, { form }) }) }) })
] })
] }),
/* @__PURE__ */ jsx(FieldToolbar.Root, {})
] }) }),
preview && isPreviewOpen && !untranslated && /* @__PURE__ */ jsx(EntryPreview, { preview, editor })
] });
}
export {
EntryEdit
};