UNPKG

strapi-plugin-preview-button

Version:

A plugin for Strapi CMS that adds a preview button and live view button to the content manager edit view.

276 lines (275 loc) 9.71 kB
import { jsx, jsxs, Fragment } from "react/jsx-runtime"; import * as React from "react"; import { a as createContext, u as useRBAC, b as Page, D as DocumentRBAC, g as useQueryParams, h as buildValidParams, C as COLLECTION_TYPES, w as useGetPreviewUrlQuery, d as useDocument, e as useDocumentLayout, k as useNotification, x as useClipboard, y as ForwardRef$2l, z as ForwardRef$3$, p as DocumentStatus } from "./index-DX9HaYlZ.mjs"; import { Typography, Tabs, Portal, FocusTrap, Box, Flex, Grid, IconButton } from "@strapi/design-system"; import { useIntl } from "react-intl"; import { useParams, Link } from "react-router-dom"; import { stringify } from "qs"; import { styled } from "styled-components"; import { getDocumentStatus } from "./EditViewPage-D2FPb5Mh-Bpzl24Um.mjs"; const PreviewContent = () => { const previewUrl = usePreviewContext("PreviewContent", (state) => state.url); const { formatMessage } = useIntl(); return /* @__PURE__ */ jsx( Box, { src: previewUrl, title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }), width: "100%", height: "100%", borderWidth: 0, tag: "iframe" } ); }; const ClosePreviewButton = () => { const [{ query }] = useQueryParams(); const { formatMessage } = useIntl(); return /* @__PURE__ */ jsx( IconButton, { tag: Link, relative: "path", to: { pathname: "..", search: stringify({ plugins: query.plugins }, { encode: false }) }, label: formatMessage({ id: "content-manager.preview.header.close", defaultMessage: "Close preview" }), children: /* @__PURE__ */ jsx(ForwardRef$3$, {}) } ); }; const Status = () => { const document = usePreviewContext("PreviewHeader", (state) => state.document); const schema = usePreviewContext("PreviewHeader", (state) => state.schema); const meta = usePreviewContext("PreviewHeader", (state) => state.meta); const hasDraftAndPublished = schema?.options?.draftAndPublish ?? false; if (!hasDraftAndPublished) { return null; } const status = getDocumentStatus(document, meta); return /* @__PURE__ */ jsx(DocumentStatus, { status, size: "XS" }); }; const PreviewTabs = () => { const { formatMessage } = useIntl(); const [{ query }, setQuery] = useQueryParams(); const document = usePreviewContext("PreviewHeader", (state) => state.document); const schema = usePreviewContext("PreviewHeader", (state) => state.schema); const meta = usePreviewContext("PreviewHeader", (state) => state.meta); const hasDraftAndPublish = schema?.options?.draftAndPublish ?? false; const documentStatus = getDocumentStatus(document, meta); const handleTabChange = (status) => { if (status === "published" || status === "draft") { setQuery({ status }, "push", true); } }; if (!hasDraftAndPublish) { return null; } return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Tabs.Root, { variant: "simple", value: query.status || "draft", onValueChange: handleTabChange, children: /* @__PURE__ */ jsxs( Tabs.List, { "aria-label": formatMessage({ id: "preview.tabs.label", defaultMessage: "Document status" }), children: [ /* @__PURE__ */ jsx(StatusTab, { value: "draft", children: formatMessage({ id: "content-manager.containers.List.draft", defaultMessage: "draft" }) }), /* @__PURE__ */ jsx(StatusTab, { value: "published", disabled: documentStatus === "draft", children: formatMessage({ id: "content-manager.containers.List.published", defaultMessage: "published" }) }) ] } ) }) }); }; const PreviewHeader = () => { const mainField = usePreviewContext("PreviewHeader", (state) => state.mainField); const document = usePreviewContext("PreviewHeader", (state) => state.document); const schema = usePreviewContext("PreviewHeader", (state) => state.schema); let documentTitle = "Untitled"; if (mainField !== "id" && document?.[mainField]) { documentTitle = document[mainField]; } else if (schema.kind === "singleType" && schema?.info.displayName) { documentTitle = schema.info.displayName; } const { formatMessage } = useIntl(); const { toggleNotification } = useNotification(); const { copy } = useClipboard(); const handleCopyLink = () => { copy(window.location.href); toggleNotification({ message: formatMessage({ id: "content-manager.preview.copy.success", defaultMessage: "Copied preview link" }), type: "success" }); }; return /* @__PURE__ */ jsxs( Grid.Root, { gap: 3, gridCols: 3, paddingLeft: 2, paddingRight: 2, background: "neutral0", borderColor: "neutral150", tag: "header", children: [ /* @__PURE__ */ jsxs(Grid.Item, { xs: 1, paddingTop: 2, paddingBottom: 2, gap: 3, children: [ /* @__PURE__ */ jsx(ClosePreviewButton, {}), /* @__PURE__ */ jsx(PreviewTitle, { tag: "h1", fontWeight: 600, fontSize: 2, maxWidth: "200px", title: documentTitle, children: documentTitle }), /* @__PURE__ */ jsx(Status, {}) ] }), /* @__PURE__ */ jsx(Grid.Item, { xs: 1, marginBottom: "-1px", alignItems: "end", margin: "auto", children: /* @__PURE__ */ jsx(PreviewTabs, {}) }), /* @__PURE__ */ jsx(Grid.Item, { xs: 1, justifyContent: "end", paddingTop: 2, paddingBottom: 2, children: /* @__PURE__ */ jsx( IconButton, { type: "button", label: formatMessage({ id: "preview.copy.label", defaultMessage: "Copy preview link" }), onClick: handleCopyLink, children: /* @__PURE__ */ jsx(ForwardRef$2l, {}) } ) }) ] } ); }; const PreviewTitle = styled(Typography)` overflow: hidden; text-overflow: ellipsis; white-space: nowrap; `; const StatusTab = styled(Tabs.Trigger)` text-transform: uppercase; `; const [PreviewProvider, usePreviewContext] = createContext("PreviewPage"); const PreviewPage = () => { const { formatMessage } = useIntl(); const { slug: model, id: documentId, collectionType } = useParams(); const [{ query }] = useQueryParams(); const params = React.useMemo(() => buildValidParams(query), [query]); if (!collectionType) { throw new Error("Could not find collectionType in url params"); } if (!model) { throw new Error("Could not find model in url params"); } if (collectionType === COLLECTION_TYPES && !documentId) { throw new Error("Could not find documentId in url params"); } const previewUrlResponse = useGetPreviewUrlQuery({ params: { contentType: model }, query: { documentId, locale: params.locale, status: params.status } }); const documentResponse = useDocument({ model, collectionType, documentId, params }); const documentLayoutResponse = useDocumentLayout(model); if (documentResponse.isLoading || previewUrlResponse.isLoading || documentLayoutResponse.isLoading) { return /* @__PURE__ */ jsx(Page.Loading, {}); } if (previewUrlResponse.error || documentLayoutResponse.error || !documentResponse.document || !documentResponse.meta || !documentResponse.schema) { return /* @__PURE__ */ jsx(Page.Error, {}); } if (!previewUrlResponse.data?.data?.url) { return /* @__PURE__ */ jsx(Page.NoData, {}); } return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(Page.Title, { children: formatMessage( { id: "content-manager.preview.page-title", defaultMessage: "{contentType} preview" }, { contentType: documentLayoutResponse.edit.settings.displayName } ) }), /* @__PURE__ */ jsx( PreviewProvider, { url: previewUrlResponse.data.data.url, mainField: documentLayoutResponse.edit.settings.mainField, document: documentResponse.document, meta: documentResponse.meta, schema: documentResponse.schema, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", height: "100%", alignItems: "stretch", children: [ /* @__PURE__ */ jsx(PreviewHeader, {}), /* @__PURE__ */ jsx(PreviewContent, {}) ] }) } ) ] }); }; const ProtectedPreviewPageImpl = () => { const { slug: model } = useParams(); const { permissions = [], isLoading, error } = useRBAC([{ action: "plugin::content-manager.explorer.read", subject: model }]); if (isLoading) { return /* @__PURE__ */ jsx(Page.Loading, {}); } if (error || !model) { return /* @__PURE__ */ jsx( Box, { height: "100vh", width: "100vw", position: "fixed", top: 0, left: 0, zIndex: 2, background: "neutral0", children: /* @__PURE__ */ jsx(Page.Error, {}) } ); } return /* @__PURE__ */ jsx( Box, { height: "100vh", width: "100vw", position: "fixed", top: 0, left: 0, zIndex: 2, background: "neutral0", children: /* @__PURE__ */ jsx(Page.Protect, { permissions, children: ({ permissions: permissions2 }) => /* @__PURE__ */ jsx(DocumentRBAC, { permissions: permissions2, children: /* @__PURE__ */ jsx(PreviewPage, {}) }) }) } ); }; const ProtectedPreviewPage = () => { return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(FocusTrap, { children: /* @__PURE__ */ jsx(ProtectedPreviewPageImpl, {}) }) }); }; export { ProtectedPreviewPage, usePreviewContext };