alinea
Version:
Headless git-based CMS
405 lines (401 loc) • 17.7 kB
JavaScript
import {
dist_default
} from "../../../chunks/chunk-A5O3N2GS.js";
import {
useAtom,
useAtomValue,
useSetAtom
} from "../../../chunks/chunk-TOJF2G3X.js";
import "../../../chunks/chunk-WJ67RR7S.js";
import {
useQueryClient
} from "../../../chunks/chunk-YWCPLD22.js";
import "../../../chunks/chunk-NZLE2WMY.js";
// src/dashboard/view/entry/EntryHeader.tsx
import { workspaceMediaDir } from "alinea/core/util/EntryFilenames";
import { Button, HStack, Icon, px, Stack } from "alinea/ui";
import { AppBar } from "alinea/ui/AppBar";
import { DropdownMenu } from "alinea/ui/DropdownMenu";
import { IcOutlineArchive } from "alinea/ui/icons/IcOutlineArchive";
import { IcOutlineAvTimer } from "alinea/ui/icons/IcOutlineAvTimer";
import { IcOutlineRemoveRedEye } from "alinea/ui/icons/IcOutlineRemoveRedEye";
import { IcRoundCheck } from "alinea/ui/icons/IcRoundCheck";
import { IcRoundDelete } from "alinea/ui/icons/IcRoundDelete";
import { IcRoundEdit } from "alinea/ui/icons/IcRoundEdit";
import { IcRoundLastPage } from "alinea/ui/icons/IcRoundLastPage";
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 { RiFlashlightFill } from "alinea/ui/icons/RiFlashlightFill";
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 { FileUploader } from "../media/FileUploader.js";
import { useSidebar } from "../Sidebar.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",
"is-unpublished": "alinea-EntryHeader-is-unpublished",
"isUnpublished": "alinea-EntryHeader-is-unpublished",
"root-action": "alinea-EntryHeader-action",
"rootAction": "alinea-EntryHeader-action",
"root-main": "alinea-EntryHeader-main",
"rootMain": "alinea-EntryHeader-main",
"root-previewToggle": "alinea-EntryHeader-previewToggle",
"rootPreviewToggle": "alinea-EntryHeader-previewToggle"
};
// src/dashboard/view/entry/EntryHeader.tsx
import { Langswitch } from "./LangSwitch.js";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var styles = dist_default(EntryHeader_module_default);
var variantDescription = {
draft: "Draft",
editing: "Editing",
published: "Published",
archived: "Archived",
untranslated: "Untranslated",
revision: "Revision",
unpublished: "Unpublished"
};
var transitions = {
[EntryTransition.SaveDraft]: "Saving",
[EntryTransition.SaveTranslation]: "Saving",
[EntryTransition.PublishEdits]: "Publishing",
[EntryTransition.RestoreRevision]: "Restoring",
[EntryTransition.PublishDraft]: "Publishing",
[EntryTransition.UnpublishDraft]: "Unpublishing",
[EntryTransition.DiscardDraft]: "Discarding",
[EntryTransition.ArchivePublished]: "Archiving",
[EntryTransition.PublishArchived]: "Publishing",
[EntryTransition.DeleteFile]: "Deleting",
[EntryTransition.DeleteEntry]: "Deleting"
};
var variantIcon = {
draft: IcRoundEdit,
editing: IcRoundEdit,
published: IcOutlineRemoveRedEye,
archived: IcOutlineArchive,
untranslated: IcRoundTranslate,
revision: IcRoundPublishedWithChanges,
transition: IcOutlineAvTimer,
unpublished: RiFlashlightFill
};
function EntryHeader({ editor, editable = true }) {
const config = useConfig();
const locale = useLocale();
const { canPublish, canDelete, untranslated, parentNeedsTranslation } = editor;
const statusInUrl = useAtomValue(editor.statusInUrl);
const selectedStatus = useAtomValue(editor.selectedStatus);
const previewRevision = useAtomValue(editor.previewRevision);
const isActiveStatus = editor.activeStatus === selectedStatus;
const isMediaFile = editor.activeVersion.type === "MediaFile";
const isMediaLibrary = editor.activeVersion.type === "MediaLibrary";
const hasChanges = useAtomValue(editor.hasChanges);
const currentTransition = useAtomValue(editor.transition);
const variant = currentTransition !== void 0 ? "transition" : previewRevision ? "revision" : untranslated ? "untranslated" : hasChanges && !statusInUrl ? "editing" : selectedStatus === "draft" && editor.activeVersion.main ? "unpublished" : selectedStatus;
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 unPublish = useSetAtom(editor.unPublish);
const archive = useSetAtom(editor.archive);
const publishArchived = useSetAtom(editor.publishArchived);
const deleteEntry = useSetAtom(editor.deleteEntry);
const deleteFile = useSetAtom(editor.deleteFile);
const deleteMediaLibrary = useSetAtom(editor.deleteMediaLibrary);
const queryClient = useQueryClient();
function deleteFileAndNavigate() {
return deleteFile()?.then(() => {
queryClient.invalidateQueries("explorer");
navigate(nav.root(entryLocation));
});
}
function deleteMediaLibraryAndNavigate() {
return deleteMediaLibrary()?.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 { isNavOpen, 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.parentId ?? void 0,
workspace: editor.activeVersion.workspace,
root: editor.activeVersion.root,
directory: workspaceMediaDir(config, editor.activeVersion.workspace)
};
await upload([file], destination, editor.entryId);
};
input.click();
}
const isParentUnpublished = editor.parents.some((p) => p.status === "draft");
const options = variant === "draft" ? /* @__PURE__ */ jsx(
DropdownMenu.Item,
{
className: styles.root.action(),
onClick: discardDraft,
children: "Remove draft"
}
) : variant === "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"
}
)
] }) : isMediaLibrary ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
DropdownMenu.Item,
{
className: styles.root.action(),
onClick: deleteMediaLibraryAndNavigate,
children: "Delete"
}
) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
config.enableDrafts && /* @__PURE__ */ jsx(
DropdownMenu.Item,
{
className: styles.root.action(),
onClick: unPublish,
children: "Unpublish"
}
),
/* @__PURE__ */ jsx(DropdownMenu.Item, { className: styles.root.action(), onClick: archive, children: "Archive" })
] }) : variant === "archived" ? /* @__PURE__ */ jsxs(Fragment, { children: [
canPublish && /* @__PURE__ */ jsx(
DropdownMenu.Item,
{
className: styles.root.action(),
onClick: publishArchived,
children: "Publish"
}
),
canDelete && /* @__PURE__ */ jsx(
DropdownMenu.Item,
{
className: styles.root.action(),
onClick: deleteEntry,
children: "Delete"
}
)
] }) : variant === "unpublished" ? isParentUnpublished ? /* @__PURE__ */ jsx(
DropdownMenu.Item,
{
className: styles.root.action(),
onClick: deleteEntry,
children: "Delete"
}
) : /* @__PURE__ */ jsx(DropdownMenu.Item, { className: styles.root.action(), onClick: archive, children: "Archive" }) : null;
const inTransition = currentTransition !== void 0;
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",
{
type: "button",
onClick: () => toggleNav(),
title: !isNavOpen ? "Display menu" : "Hide menu",
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.availableStatuses.length > 1 && /* @__PURE__ */ jsx(Icon, { icon: IcRoundUnfoldMore })
] }) }),
/* @__PURE__ */ jsxs(DropdownMenu.Items, { children: [
hasChanges && /* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => {
navigate(pathname);
},
children: "Editing"
}
),
!previewRevision && editor.availableStatuses.map((status) => {
return /* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => {
navigate(`${pathname}?${status}`);
},
children: variantDescription[status]
},
status
);
})
] })
] }),
!inTransition && !hasChanges && !isActiveStatus && editor.availableStatuses.includes("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" })
] }),
!inTransition && untranslated && !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}`);
}
}
)
] }) })
] }),
!inTransition && 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",
{
type: "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: [
!inTransition && /* @__PURE__ */ jsxs(Fragment, { children: [
untranslated && !editor.parentNeedsTranslation && /* @__PURE__ */ jsx(Button, { icon: IcRoundSave, onClick: translate, children: "Save translation" }),
variant === "editing" && canPublish && /* @__PURE__ */ jsx(Button, { icon: IcRoundCheck, onClick: publishEdits, children: "Publish" }),
!untranslated && !hasChanges && canPublish && selectedStatus === "draft" && /* @__PURE__ */ jsx(
Button,
{
icon: IcRoundCheck,
onClick: publishDraft,
className: styles.root.main({
unpublished: variant === "unpublished"
}),
children: "Publish"
}
),
config.enableDrafts && variant === "editing" && /* @__PURE__ */ jsx(Button, { outline: true, icon: IcRoundSave, onClick: saveDraft, children: "Save" }),
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 && !isMediaLibrary && /* @__PURE__ */ jsxs(
DropdownMenu.Item,
{
onClick: () => setShowHistory(!showHistory),
children: [
showHistory ? "Hide" : "Show",
" history"
]
}
),
options
] })
] })
] }),
/* @__PURE__ */ jsx(
"button",
{
type: "button",
onClick: () => togglePreview(),
title: isPreviewOpen ? "Hide preview" : "Display preview",
className: styles.root.previewToggle(),
children: /* @__PURE__ */ jsx(
Icon,
{
icon: IcRoundLastPage,
style: {
transform: `scaleX(${isPreviewOpen ? 1 : -1})`
}
}
)
}
)
] }) })
] }) })
] });
}
export {
EntryHeader
};