UNPKG

alinea

Version:

[![npm](https://img.shields.io/npm/v/alinea.svg)](https://npmjs.org/package/alinea) [![install size](https://packagephobia.com/badge?p=alinea)](https://packagephobia.com/result?p=alinea)

358 lines (354 loc) 16.1 kB
import { useAtom, useAtomValue, useSetAtom } from "../../../chunks/chunk-WF77DMLN.js"; import "../../../chunks/chunk-OBOPLPUQ.js"; import { useQueryClient } from "../../../chunks/chunk-DJKGEOOC.js"; import "../../../chunks/chunk-U5RRZUYZ.js"; // src/dashboard/view/entry/EntryHeader.tsx import { EntryPhase } from "alinea/core"; import { entryFile, workspaceMediaDir } from "alinea/core/EntryFilenames"; import { Button, HStack, Icon, Stack, fromModule, px } from "alinea/ui"; import { AppBar } from "alinea/ui/AppBar"; import { DropdownMenu } from "alinea/ui/DropdownMenu"; import { IcOutlineAvTimer } from "alinea/ui/icons/IcOutlineAvTimer"; import { IcOutlineDrafts } from "alinea/ui/icons/IcOutlineDrafts"; import { IcOutlineKeyboardTab } from "alinea/ui/icons/IcOutlineKeyboardTab"; import { IcOutlineRemoveRedEye } from "alinea/ui/icons/IcOutlineRemoveRedEye"; import { IcRoundArchive } from "alinea/ui/icons/IcRoundArchive"; import { IcRoundCheck } from "alinea/ui/icons/IcRoundCheck"; import { IcRoundDelete } from "alinea/ui/icons/IcRoundDelete"; import { IcRoundEdit } from "alinea/ui/icons/IcRoundEdit"; import { IcRoundMenu } from "alinea/ui/icons/IcRoundMenu"; import { IcRoundMoreVert } from "alinea/ui/icons/IcRoundMoreVert"; import { IcRoundPublishedWithChanges } from "alinea/ui/icons/IcRoundPublishedWithChanges"; import { IcRoundSave } from "alinea/ui/icons/IcRoundSave"; import { IcRoundTranslate } from "alinea/ui/icons/IcRoundTranslate"; import { IcRoundUnfoldMore } from "alinea/ui/icons/IcRoundUnfoldMore"; import { useState } from "react"; import { EntryTransition } from "../../atoms/EntryEditorAtoms.js"; import { useLocation, useNavigate } from "../../atoms/LocationAtoms.js"; import { useConfig } from "../../hook/UseConfig.js"; import { useEntryLocation } from "../../hook/UseEntryLocation.js"; import { useLocale } from "../../hook/UseLocale.js"; import { useNav } from "../../hook/UseNav.js"; import { useUploads } from "../../hook/UseUploads.js"; import { useSidebar } from "../Sidebar.js"; import { FileUploader } from "../media/FileUploader.js"; // src/dashboard/view/entry/EntryHeader.module.scss var EntryHeader_module_default = { "root": "alinea-EntryHeader", "root-tabTrigger": "alinea-EntryHeader-tabTrigger", "rootTabTrigger": "alinea-EntryHeader-tabTrigger", "is-active": "alinea-EntryHeader-is-active", "isActive": "alinea-EntryHeader-is-active", "root-menuToggle": "alinea-EntryHeader-menuToggle", "rootMenuToggle": "alinea-EntryHeader-menuToggle", "root-description": "alinea-EntryHeader-description", "rootDescription": "alinea-EntryHeader-description", "root-description-separator": "alinea-EntryHeader-description-separator", "rootDescriptionSeparator": "alinea-EntryHeader-description-separator", "root-description-title": "alinea-EntryHeader-description-title", "rootDescriptionTitle": "alinea-EntryHeader-description-title", "root-description-action": "alinea-EntryHeader-description-action", "rootDescriptionAction": "alinea-EntryHeader-description-action", "root-description-action-button": "alinea-EntryHeader-description-action-button", "rootDescriptionActionButton": "alinea-EntryHeader-description-action-button", "root-url": "alinea-EntryHeader-url", "rootUrl": "alinea-EntryHeader-url", "root-more": "alinea-EntryHeader-more", "rootMore": "alinea-EntryHeader-more", "is-draft": "alinea-EntryHeader-is-draft", "isDraft": "alinea-EntryHeader-is-draft", "is-editing": "alinea-EntryHeader-is-editing", "isEditing": "alinea-EntryHeader-is-editing", "is-revision": "alinea-EntryHeader-is-revision", "isRevision": "alinea-EntryHeader-is-revision", "is-published": "alinea-EntryHeader-is-published", "isPublished": "alinea-EntryHeader-is-published", "is-archived": "alinea-EntryHeader-is-archived", "isArchived": "alinea-EntryHeader-is-archived", "is-publishing": "alinea-EntryHeader-is-publishing", "isPublishing": "alinea-EntryHeader-is-publishing", "is-archiving": "alinea-EntryHeader-is-archiving", "isArchiving": "alinea-EntryHeader-is-archiving", "root-action": "alinea-EntryHeader-action", "rootAction": "alinea-EntryHeader-action" }; // src/dashboard/view/entry/EntryHeader.tsx import { Langswitch } from "./LangSwitch.js"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var styles = fromModule(EntryHeader_module_default); var variantDescription = { draft: "Draft", editing: "Editing", published: "Published", archived: "Archived", untranslated: "Untranslated", revision: "Revision" }; var transitions = { [EntryTransition.SaveDraft]: "Saving", [EntryTransition.SaveTranslation]: "Saving", [EntryTransition.PublishEdits]: "Publishing", [EntryTransition.RestoreRevision]: "Restoring", [EntryTransition.PublishDraft]: "Publishing", [EntryTransition.DiscardDraft]: "Discarding", [EntryTransition.ArchivePublished]: "Archiving", [EntryTransition.PublishArchived]: "Publishing", [EntryTransition.DeleteFile]: "Deleting", [EntryTransition.DeleteArchived]: "Deleting" }; var variantIcon = { draft: IcOutlineDrafts, editing: IcRoundEdit, published: IcOutlineRemoveRedEye, archived: IcRoundArchive, untranslated: IcRoundTranslate, revision: IcRoundPublishedWithChanges, transition: IcOutlineAvTimer }; function EntryHeader({ editor, editable = true }) { const config = useConfig(); const locale = useLocale(); const phaseInUrl = useAtomValue(editor.phaseInUrl); const selectedPhase = useAtomValue(editor.selectedPhase); const previewRevision = useAtomValue(editor.previewRevision); const isActivePhase = editor.activePhase === selectedPhase; const isMediaFile = editor.activeVersion.type === "MediaFile"; const hasChanges = useAtomValue(editor.hasChanges); const currentTransition = useAtomValue(editor.transition)?.transition; const untranslated = locale && locale !== editor.activeVersion.locale; const variant = currentTransition ? "transition" : previewRevision ? "revision" : untranslated ? "untranslated" : hasChanges && !phaseInUrl ? "editing" : selectedPhase; const saveDraft = useSetAtom(editor.saveDraft); const publishEdits = useSetAtom(editor.publishEdits); const publishDraft = useSetAtom(editor.publishDraft); const restoreRevision = useSetAtom(editor.restoreRevision); const discardDraft = useSetAtom(editor.discardDraft); const archivePublished = useSetAtom(editor.archivePublished); const publishArchived = useSetAtom(editor.publishArchived); const deleteArchived = useSetAtom(editor.deleteArchived); const deleteFile = useSetAtom(editor.deleteFile); const queryClient = useQueryClient(); function deleteFileAndNavigate() { return deleteFile()?.then(() => { queryClient.invalidateQueries("explorer"); navigate(nav.root(entryLocation)); }); } const saveTranslation = useSetAtom(editor.saveTranslation); const discardEdits = useSetAtom(editor.discardEdits); const translate = () => saveTranslation(locale); const [showHistory, setShowHistory] = useAtom(editor.showHistory); const entryLocation = useEntryLocation(); const navigate = useNavigate(); const nav = useNav(); const { pathname } = useLocation(); const { isPreviewOpen, toggleNav, togglePreview } = useSidebar(); const [isReplacing, setIsReplacing] = useState(false); const { upload } = useUploads(); function replaceFile() { setIsReplacing(true); const input = document.createElement("input"); input.type = "file"; const extension = editor.activeVersion.data.extension; input.accept = extension; input.onchange = async () => { const file = input.files[0]; const destination = { parentId: editor.activeVersion.parent ?? void 0, workspace: editor.activeVersion.workspace, root: editor.activeVersion.root, directory: workspaceMediaDir(config, editor.activeVersion.workspace) }; await upload([file], destination, { entry: editor.activeVersion, entryFile: entryFile(config, editor.activeVersion) }); }; input.click(); } const options = variant === "draft" ? /* @__PURE__ */ jsx( DropdownMenu.Item, { className: styles.root.action(), onClick: discardDraft, children: "Remove draft" } ) : variant === EntryPhase.Published && !editor.activeVersion.seeded ? isMediaFile ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( DropdownMenu.Item, { className: styles.root.action(), onClick: replaceFile, children: "Replace" } ), /* @__PURE__ */ jsx( DropdownMenu.Item, { className: styles.root.action(), onClick: deleteFileAndNavigate, children: "Delete" } ) ] }) : /* @__PURE__ */ jsx( DropdownMenu.Item, { className: styles.root.action(), onClick: archivePublished, children: "Archive" } ) : variant === EntryPhase.Archived ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( DropdownMenu.Item, { className: styles.root.action(), onClick: publishArchived, children: "Publish" } ), /* @__PURE__ */ jsx( DropdownMenu.Item, { className: styles.root.action(), onClick: deleteArchived, children: "Delete" } ) ] }) : null; return /* @__PURE__ */ jsxs(Fragment, { children: [ isReplacing && /* @__PURE__ */ jsx(FileUploader, {}), /* @__PURE__ */ jsx(AppBar.Root, { className: styles.root(), variant, children: /* @__PURE__ */ jsxs(HStack, { center: true, gap: 12, className: styles.root.description(), children: [ /* @__PURE__ */ jsx( "button", { title: "Display menu", onClick: () => toggleNav(), className: styles.root.menuToggle(), children: /* @__PURE__ */ jsx(Icon, { icon: IcRoundMenu }) } ), /* @__PURE__ */ jsx(Icon, { icon: variantIcon[variant], size: 18 }), /* @__PURE__ */ jsxs(DropdownMenu.Root, { bottom: true, children: [ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { className: styles.root.description.title(), children: /* @__PURE__ */ jsxs(HStack, { center: true, gap: 4, children: [ /* @__PURE__ */ jsx("span", { children: variant === "transition" ? transitions[currentTransition] : variantDescription[variant] }), !previewRevision && editor.availablePhases.length > 1 && /* @__PURE__ */ jsx(Icon, { icon: IcRoundUnfoldMore }) ] }) }), /* @__PURE__ */ jsxs(DropdownMenu.Items, { children: [ hasChanges && /* @__PURE__ */ jsx( DropdownMenu.Item, { onClick: () => { navigate(pathname); }, children: "Editing" } ), !previewRevision && editor.availablePhases.map((phase) => { return /* @__PURE__ */ jsx( DropdownMenu.Item, { onClick: () => { navigate(`${pathname}?${phase}`); }, children: variantDescription[phase] }, phase ); }) ] }) ] }), editable && !currentTransition && !hasChanges && isActivePhase && !untranslated && !previewRevision && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("span", { className: styles.root.description.separator() }), /* @__PURE__ */ jsx("div", { className: styles.root.description.action(), children: "Edit to create a new draft" }) ] }), !currentTransition && !hasChanges && !isActivePhase && editor.availablePhases.includes(EntryPhase.Draft) && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("span", { className: styles.root.description.separator() }), /* @__PURE__ */ jsx("div", { className: styles.root.description.action(), children: "A newer draft version is available" }) ] }), !currentTransition && untranslated && !editor.parentNeedsTranslation && !hasChanges && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("span", { className: styles.root.description.separator() }), /* @__PURE__ */ jsx("div", { className: styles.root.description.action(), children: /* @__PURE__ */ jsxs(HStack, { center: true, children: [ /* @__PURE__ */ jsx("span", { style: { marginRight: px(8) }, children: "Translate from" }), /* @__PURE__ */ jsx( Langswitch, { selected: editor.activeVersion.locale, locales: editor.translations.map(({ locale: locale2 }) => locale2), onChange: (locale2) => { navigate(pathname + `?from=` + locale2); } } ) ] }) }) ] }), !currentTransition && untranslated && editor.parentNeedsTranslation && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("span", { className: styles.root.description.separator() }), /* @__PURE__ */ jsx("div", { className: styles.root.description.action(), children: "Translate parent page first" }) ] }), variant === "editing" && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("span", { className: styles.root.description.separator() }), /* @__PURE__ */ jsx("div", { className: styles.root.description.action(), children: /* @__PURE__ */ jsxs( "button", { className: styles.root.description.action.button(), onClick: discardEdits, children: [ /* @__PURE__ */ jsx(Icon, { icon: IcRoundDelete }), /* @__PURE__ */ jsx("span", { children: "Discard edits" }) ] } ) }) ] }), /* @__PURE__ */ jsx(Stack.Right, { children: /* @__PURE__ */ jsxs(HStack, { center: true, gap: 12, children: [ !currentTransition && /* @__PURE__ */ jsxs(Fragment, { children: [ untranslated && !editor.parentNeedsTranslation && /* @__PURE__ */ jsx(Button, { icon: IcRoundSave, onClick: translate, children: "Save translation" }), config.enableDrafts && variant === "editing" && /* @__PURE__ */ jsx(Button, { icon: IcRoundSave, onClick: saveDraft, children: "Save draft" }), !config.enableDrafts && variant === "editing" && /* @__PURE__ */ jsx(Button, { icon: IcRoundSave, onClick: publishEdits, children: "Publish" }), !untranslated && !hasChanges && selectedPhase === "draft" && /* @__PURE__ */ jsx(Button, { icon: IcRoundCheck, onClick: publishDraft, children: "Publish draft" }), variant === "revision" && /* @__PURE__ */ jsx(Button, { icon: IcRoundSave, onClick: restoreRevision, children: "Restore" }), /* @__PURE__ */ jsxs(DropdownMenu.Root, { bottom: true, left: true, children: [ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { className: styles.root.more(variant), children: /* @__PURE__ */ jsx(Icon, { icon: IcRoundMoreVert }) }), /* @__PURE__ */ jsxs(DropdownMenu.Items, { children: [ !isMediaFile && /* @__PURE__ */ jsxs( DropdownMenu.Item, { onClick: () => setShowHistory(!showHistory), children: [ showHistory ? "Hide" : "Show", " history" ] } ), options ] }) ] }) ] }), /* @__PURE__ */ jsx( "button", { title: "Display preview", onClick: () => togglePreview(), style: { cursor: "pointer" }, children: /* @__PURE__ */ jsx( Icon, { icon: IcOutlineKeyboardTab, style: { transform: `rotate(${isPreviewOpen ? 0 : 180}deg)` } } ) } ) ] }) }) ] }) }) ] }); } export { EntryHeader };