node_modules ignore

This commit is contained in:
oier committed 2025-05-08 23:43:47 +02:00
1 parent e19d52f172
commit 4574544c9f
65041 files changed
+10593536

No files matched your search

@@ -0,0 +1,261 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
require('react');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var designSystem = require('@strapi/design-system');
var Icons = require('@strapi/icons');
var qs = require('qs');
var reactIntl = require('react-intl');
var reactRouterDom = require('react-router-dom');
var styledComponents = require('styled-components');
var InjectionZone = require('../../components/InjectionZone.js');
var DocumentActions = require('../../pages/EditView/components/DocumentActions.js');
var DocumentStatus = require('../../pages/EditView/components/DocumentStatus.js');
var EditViewPage = require('../../pages/EditView/EditViewPage.js');
var Preview = require('../pages/Preview.js');
/* -------------------------------------------------------------------------------------------------
* ClosePreviewButton
* -----------------------------------------------------------------------------------------------*/ const ClosePreviewButton = ()=>{
const [{ query }] = strapiAdmin.useQueryParams();
const { formatMessage } = reactIntl.useIntl();
const canGoBack = strapiAdmin.useHistory('BackButton', (state)=>state.canGoBack);
const goBack = strapiAdmin.useHistory('BackButton', (state)=>state.goBack);
const history = strapiAdmin.useHistory('BackButton', (state)=>state.history);
const locationIndex = strapiAdmin.useHistory('BackButton', (state)=>state.currentLocationIndex);
/**
* Get the link destination from the history.
* Rely on a fallback (the parent edit view page) if there's no page to go back .
*/ const historyTo = canGoBack ? history.at(locationIndex - 2) : undefined;
const fallback = {
pathname: '..',
search: qs.stringify(query, {
encode: false
})
};
const toWithFallback = historyTo ?? fallback;
const handleClick = (e)=>{
if (canGoBack) {
// Prevent normal link behavior, go back in the history stack instead
e.preventDefault();
goBack();
return;
}
// Otherwise rely on native link behavior to go back to the edit view. We don't use navigate()
// here in order to get the relative="path" functionality from the Link component.
};
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
variant: "ghost",
tag: reactRouterDom.Link,
relative: "path",
to: toWithFallback,
onClick: handleClick,
label: formatMessage({
id: 'content-manager.preview.header.close',
defaultMessage: 'Close preview'
}),
children: /*#__PURE__*/ jsxRuntime.jsx(Icons.Cross, {})
});
};
/* -------------------------------------------------------------------------------------------------
* Status
* -----------------------------------------------------------------------------------------------*/ const Status = ()=>{
// Get status
const document = Preview.usePreviewContext('PreviewHeader', (state)=>state.document);
const schema = Preview.usePreviewContext('PreviewHeader', (state)=>state.schema);
const meta = Preview.usePreviewContext('PreviewHeader', (state)=>state.meta);
const hasDraftAndPublished = schema?.options?.draftAndPublish ?? false;
if (!hasDraftAndPublished) {
return null;
}
const status = EditViewPage.getDocumentStatus(document, meta);
return /*#__PURE__*/ jsxRuntime.jsx(DocumentStatus.DocumentStatus, {
status: status,
size: "XS"
});
};
const PreviewTabs = ()=>{
const { formatMessage } = reactIntl.useIntl();
// URL query params
const [{ query }, setQuery] = strapiAdmin.useQueryParams();
// Get status
const document = Preview.usePreviewContext('PreviewHeader', (state)=>state.document);
const schema = Preview.usePreviewContext('PreviewHeader', (state)=>state.schema);
const meta = Preview.usePreviewContext('PreviewHeader', (state)=>state.meta);
const hasDraftAndPublish = schema?.options?.draftAndPublish ?? false;
const documentStatus = EditViewPage.getDocumentStatus(document, meta);
const handleTabChange = (status)=>{
if (status === 'published' || status === 'draft') {
setQuery({
status
}, 'push', true);
}
};
if (!hasDraftAndPublish) {
return null;
}
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Root, {
variant: "simple",
value: query.status || 'draft',
onValueChange: handleTabChange,
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tabs.List, {
"aria-label": formatMessage({
id: 'preview.tabs.label',
defaultMessage: 'Document status'
}),
children: [
/*#__PURE__*/ jsxRuntime.jsx(StatusTab, {
value: "draft",
children: formatMessage({
id: 'content-manager.containers.List.draft',
defaultMessage: 'draft'
})
}),
/*#__PURE__*/ jsxRuntime.jsx(StatusTab, {
value: "published",
disabled: documentStatus === 'draft',
children: formatMessage({
id: 'content-manager.containers.List.published',
defaultMessage: 'published'
})
})
]
})
});
};
/* -------------------------------------------------------------------------------------------------
* PreviewHeader
* -----------------------------------------------------------------------------------------------*/ const PreviewHeader = ()=>{
const title = Preview.usePreviewContext('PreviewHeader', (state)=>state.title);
const document = Preview.usePreviewContext('PreviewHeader', (state)=>state.document);
const schema = Preview.usePreviewContext('PreviewHeader', (state)=>state.schema);
const meta = Preview.usePreviewContext('PreviewHeader', (state)=>state.meta);
Preview.usePreviewContext('PreviewHeader', (state)=>state.onPreview);
const plugins = strapiAdmin.useStrapiApp('PreviewHeader', (state)=>state.plugins);
const [{ query }] = strapiAdmin.useQueryParams();
const { formatMessage } = reactIntl.useIntl();
const { toggleNotification } = strapiAdmin.useNotification();
const { copy } = strapiAdmin.useClipboard();
const handleCopyLink = ()=>{
copy(window.location.href);
toggleNotification({
message: formatMessage({
id: 'content-manager.preview.copy.success',
defaultMessage: 'Copied preview link'
}),
type: 'success'
});
};
const hasDraftAndPublish = schema.options?.draftAndPublish ?? false;
const documentActionProps = {
activeTab: query.status ?? null,
collectionType: schema.kind === 'collectionType' ? 'collection-types' : 'single-types',
model: schema.uid,
documentId: schema.kind === 'collectionType' ? document.documentId : undefined,
document,
meta
};
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
height: "48px",
gap: 4,
background: "neutral0",
borderColor: "neutral150",
tag: "header",
children: [
/*#__PURE__*/ jsxRuntime.jsxs(TitleContainer, {
height: "100%",
paddingLeft: 2,
paddingRight: 4,
children: [
/*#__PURE__*/ jsxRuntime.jsx(ClosePreviewButton, {}),
/*#__PURE__*/ jsxRuntime.jsx(PreviewTitle, {
tag: "h1",
title: title,
maxWidth: "200px",
fontSize: 2,
paddingLeft: 2,
paddingRight: 3,
fontWeight: 600,
children: title
}),
/*#__PURE__*/ jsxRuntime.jsx(Status, {})
]
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
flex: 1,
paddingRight: 2,
gap: 2,
justifyContent: hasDraftAndPublish ? 'space-between' : 'flex-end',
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
flex: "1 1 70%",
children: /*#__PURE__*/ jsxRuntime.jsx(PreviewTabs, {})
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
gap: 2,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
type: "button",
label: formatMessage({
id: 'preview.copy.label',
defaultMessage: 'Copy preview link'
}),
onClick: handleCopyLink,
children: /*#__PURE__*/ jsxRuntime.jsx(Icons.Link, {})
}),
/*#__PURE__*/ jsxRuntime.jsx(InjectionZone.InjectionZone, {
area: "preview.actions"
}),
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.DescriptionComponentRenderer, {
props: documentActionProps,
descriptions: plugins['content-manager'].apis.getDocumentActions('preview'),
children: (actions)=>{
const filteredActions = actions.filter((action)=>[
action.position
].flat().includes('preview'));
const [primaryAction, secondaryAction] = filteredActions;
if (!primaryAction && !secondaryAction) return null;
// Both actions are available when draft and publish enabled
if (primaryAction && secondaryAction) {
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
...secondaryAction,
variant: secondaryAction.variant || 'secondary'
}),
/*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
...primaryAction,
variant: primaryAction.variant || 'default'
})
]
});
}
// Otherwise we just have the save action
return /*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
...primaryAction,
variant: primaryAction.variant || 'secondary'
});
}
})
]
})
]
})
]
});
};
const PreviewTitle = styledComponents.styled(designSystem.Typography)`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StatusTab = styledComponents.styled(designSystem.Tabs.Trigger)`
text-transform: uppercase;
`;
const TitleContainer = styledComponents.styled(designSystem.Flex)`
border-right: 1px solid ${({ theme })=>theme.colors.neutral150};
`;
exports.PreviewHeader = PreviewHeader;
//# sourceMappingURL=PreviewHeader.js.map
@@ -0,0 +1 @@
{"version":3,"file":"PreviewHeader.js","sources":["../../../../admin/src/preview/components/PreviewHeader.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n DescriptionComponentRenderer,\n useClipboard,\n useHistory,\n useNotification,\n useQueryParams,\n useStrapiApp,\n} from '@strapi/admin/strapi-admin';\nimport { IconButton, Tabs, Typography, Flex } from '@strapi/design-system';\nimport { Cross, Link as LinkIcon } from '@strapi/icons';\nimport { stringify } from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Link, type To } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { InjectionZone } from '../../components/InjectionZone';\nimport { DocumentActionButton } from '../../pages/EditView/components/DocumentActions';\nimport { DocumentStatus } from '../../pages/EditView/components/DocumentStatus';\nimport { getDocumentStatus } from '../../pages/EditView/EditViewPage';\nimport { usePreviewContext } from '../pages/Preview';\n\nimport type { ContentManagerPlugin, DocumentActionProps } from '../../content-manager';\n\n/* -------------------------------------------------------------------------------------------------\n * ClosePreviewButton\n * -----------------------------------------------------------------------------------------------*/\n\nconst ClosePreviewButton = () => {\n const [{ query }] = useQueryParams<{\n plugins?: Record<string, unknown>;\n }>();\n const { formatMessage } = useIntl();\n\n const canGoBack = useHistory('BackButton', (state) => state.canGoBack);\n const goBack = useHistory('BackButton', (state) => state.goBack);\n const history = useHistory('BackButton', (state) => state.history);\n const locationIndex = useHistory('BackButton', (state) => state.currentLocationIndex);\n\n /**\n * Get the link destination from the history.\n * Rely on a fallback (the parent edit view page) if there's no page to go back .\n */\n const historyTo = canGoBack ? history.at(locationIndex - 2) : undefined;\n const fallback = {\n pathname: '..',\n search: stringify(query, { encode: false }),\n } satisfies To;\n const toWithFallback = historyTo ?? fallback;\n\n const handleClick = (e: React.MouseEvent) => {\n if (canGoBack) {\n // Prevent normal link behavior, go back in the history stack instead\n e.preventDefault();\n goBack();\n return;\n }\n\n // Otherwise rely on native link behavior to go back to the edit view. We don't use navigate()\n // here in order to get the relative=\"path\" functionality from the Link component.\n };\n\n return (\n <IconButton\n variant=\"ghost\"\n tag={Link}\n relative=\"path\"\n to={toWithFallback}\n onClick={handleClick}\n label={formatMessage({\n id: 'content-manager.preview.header.close',\n defaultMessage: 'Close preview',\n })}\n >\n <Cross />\n </IconButton>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Status\n * -----------------------------------------------------------------------------------------------*/\n\nconst Status = () => {\n // Get status\n const document = usePreviewContext('PreviewHeader', (state) => state.document);\n const schema = usePreviewContext('PreviewHeader', (state) => state.schema);\n const meta = usePreviewContext('PreviewHeader', (state) => state.meta);\n const hasDraftAndPublished = schema?.options?.draftAndPublish ?? false;\n\n if (!hasDraftAndPublished) {\n return null;\n }\n\n const status = getDocumentStatus(document, meta);\n\n return <DocumentStatus status={status} size=\"XS\" />;\n};\n\nconst PreviewTabs = () => {\n const { formatMessage } = useIntl();\n\n // URL query params\n const [{ query }, setQuery] = useQueryParams<{ status: 'draft' | 'published' }>();\n\n // Get status\n const document = usePreviewContext('PreviewHeader', (state) => state.document);\n const schema = usePreviewContext('PreviewHeader', (state) => state.schema);\n const meta = usePreviewContext('PreviewHeader', (state) => state.meta);\n const hasDraftAndPublish = schema?.options?.draftAndPublish ?? false;\n const documentStatus = getDocumentStatus(document, meta);\n\n const handleTabChange = (status: string) => {\n if (status === 'published' || status === 'draft') {\n setQuery({ status }, 'push', true);\n }\n };\n\n if (!hasDraftAndPublish) {\n return null;\n }\n\n return (\n <Tabs.Root variant=\"simple\" value={query.status || 'draft'} onValueChange={handleTabChange}>\n <Tabs.List\n aria-label={formatMessage({\n id: 'preview.tabs.label',\n defaultMessage: 'Document status',\n })}\n >\n <StatusTab value=\"draft\">\n {formatMessage({\n id: 'content-manager.containers.List.draft',\n defaultMessage: 'draft',\n })}\n </StatusTab>\n <StatusTab value=\"published\" disablLine truncated
@@ -0,0 +1,259 @@
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
import 'react';
import { useStrapiApp, useQueryParams, useNotification, useClipboard, DescriptionComponentRenderer, useHistory } from '@strapi/admin/strapi-admin';
import { Typography, Tabs, Flex, IconButton } from '@strapi/design-system';
import { Link, Cross } from '@strapi/icons';
import { stringify } from 'qs';
import { useIntl } from 'react-intl';
import { Link as Link$1 } from 'react-router-dom';
import { styled } from 'styled-components';
import { InjectionZone } from '../../components/InjectionZone.mjs';
import { DocumentActionButton } from '../../pages/EditView/components/DocumentActions.mjs';
import { DocumentStatus } from '../../pages/EditView/components/DocumentStatus.mjs';
import { getDocumentStatus } from '../../pages/EditView/EditViewPage.mjs';
import { usePreviewContext } from '../pages/Preview.mjs';
/* -------------------------------------------------------------------------------------------------
* ClosePreviewButton
* -----------------------------------------------------------------------------------------------*/ const ClosePreviewButton = ()=>{
const [{ query }] = useQueryParams();
const { formatMessage } = useIntl();
const canGoBack = useHistory('BackButton', (state)=>state.canGoBack);
const goBack = useHistory('BackButton', (state)=>state.goBack);
const history = useHistory('BackButton', (state)=>state.history);
const locationIndex = useHistory('BackButton', (state)=>state.currentLocationIndex);
/**
* Get the link destination from the history.
* Rely on a fallback (the parent edit view page) if there's no page to go back .
*/ const historyTo = canGoBack ? history.at(locationIndex - 2) : undefined;
const fallback = {
pathname: '..',
search: stringify(query, {
encode: false
})
};
const toWithFallback = historyTo ?? fallback;
const handleClick = (e)=>{
if (canGoBack) {
// Prevent normal link behavior, go back in the history stack instead
e.preventDefault();
goBack();
return;
}
// Otherwise rely on native link behavior to go back to the edit view. We don't use navigate()
// here in order to get the relative="path" functionality from the Link component.
};
return /*#__PURE__*/ jsx(IconButton, {
variant: "ghost",
tag: Link$1,
relative: "path",
to: toWithFallback,
onClick: handleClick,
label: formatMessage({
id: 'content-manager.preview.header.close',
defaultMessage: 'Close preview'
}),
children: /*#__PURE__*/ jsx(Cross, {})
});
};
/* -------------------------------------------------------------------------------------------------
* Status
* -----------------------------------------------------------------------------------------------*/ const Status = ()=>{
// Get 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: status,
size: "XS"
});
};
const PreviewTabs = ()=>{
const { formatMessage } = useIntl();
// URL query params
const [{ query }, setQuery] = useQueryParams();
// Get status
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(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'
})
})
]
})
});
};
/* -------------------------------------------------------------------------------------------------
* PreviewHeader
* -----------------------------------------------------------------------------------------------*/ const PreviewHeader = ()=>{
const title = usePreviewContext('PreviewHeader', (state)=>state.title);
const document = usePreviewContext('PreviewHeader', (state)=>state.document);
const schema = usePreviewContext('PreviewHeader', (state)=>state.schema);
const meta = usePreviewContext('PreviewHeader', (state)=>state.meta);
usePreviewContext('PreviewHeader', (state)=>state.onPreview);
const plugins = useStrapiApp('PreviewHeader', (state)=>state.plugins);
const [{ query }] = useQueryParams();
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'
});
};
const hasDraftAndPublish = schema.options?.draftAndPublish ?? false;
const documentActionProps = {
activeTab: query.status ?? null,
collectionType: schema.kind === 'collectionType' ? 'collection-types' : 'single-types',
model: schema.uid,
documentId: schema.kind === 'collectionType' ? document.documentId : undefined,
document,
meta
};
return /*#__PURE__*/ jsxs(Flex, {
height: "48px",
gap: 4,
background: "neutral0",
borderColor: "neutral150",
tag: "header",
children: [
/*#__PURE__*/ jsxs(TitleContainer, {
height: "100%",
paddingLeft: 2,
paddingRight: 4,
children: [
/*#__PURE__*/ jsx(ClosePreviewButton, {}),
/*#__PURE__*/ jsx(PreviewTitle, {
tag: "h1",
title: title,
maxWidth: "200px",
fontSize: 2,
paddingLeft: 2,
paddingRight: 3,
fontWeight: 600,
children: title
}),
/*#__PURE__*/ jsx(Status, {})
]
}),
/*#__PURE__*/ jsxs(Flex, {
flex: 1,
paddingRight: 2,
gap: 2,
justifyContent: hasDraftAndPublish ? 'space-between' : 'flex-end',
children: [
/*#__PURE__*/ jsx(Flex, {
flex: "1 1 70%",
children: /*#__PURE__*/ jsx(PreviewTabs, {})
}),
/*#__PURE__*/ jsxs(Flex, {
gap: 2,
children: [
/*#__PURE__*/ jsx(IconButton, {
type: "button",
label: formatMessage({
id: 'preview.copy.label',
defaultMessage: 'Copy preview link'
}),
onClick: handleCopyLink,
children: /*#__PURE__*/ jsx(Link, {})
}),
/*#__PURE__*/ jsx(InjectionZone, {
area: "preview.actions"
}),
/*#__PURE__*/ jsx(DescriptionComponentRenderer, {
props: documentActionProps,
descriptions: plugins['content-manager'].apis.getDocumentActions('preview'),
children: (actions)=>{
const filteredActions = actions.filter((action)=>[
action.position
].flat().includes('preview'));
const [primaryAction, secondaryAction] = filteredActions;
if (!primaryAction && !secondaryAction) return null;
// Both actions are available when draft and publish enabled
if (primaryAction && secondaryAction) {
return /*#__PURE__*/ jsxs(Fragment, {
children: [
/*#__PURE__*/ jsx(DocumentActionButton, {
...secondaryAction,
variant: secondaryAction.variant || 'secondary'
}),
/*#__PURE__*/ jsx(DocumentActionButton, {
...primaryAction,
variant: primaryAction.variant || 'default'
})
]
});
}
// Otherwise we just have the save action
return /*#__PURE__*/ jsx(DocumentActionButton, {
...primaryAction,
variant: primaryAction.variant || 'secondary'
});
}
})
]
})
]
})
]
});
};
const PreviewTitle = styled(Typography)`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StatusTab = styled(Tabs.Trigger)`
text-transform: uppercase;
`;
const TitleContainer = styled(Flex)`
border-right: 1px solid ${({ theme })=>theme.colors.neutral150};
`;
export { PreviewHeader };
//# sourceMappingURL=PreviewHeader.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"PreviewHeader.mjs","sources":["../../../../admin/src/preview/components/PreviewHeader.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n DescriptionComponentRenderer,\n useClipboard,\n useHistory,\n useNotification,\n useQueryParams,\n useStrapiApp,\n} from '@strapi/admin/strapi-admin';\nimport { IconButton, Tabs, Typography, Flex } from '@strapi/design-system';\nimport { Cross, Link as LinkIcon } from '@strapi/icons';\nimport { stringify } from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Link, type To } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { InjectionZone } from '../../components/InjectionZone';\nimport { DocumentActionButton } from '../../pages/EditView/components/DocumentActions';\nimport { DocumentStatus } from '../../pages/EditView/components/DocumentStatus';\nimport { getDocumentStatus } from '../../pages/EditView/EditViewPage';\nimport { usePreviewContext } from '../pages/Preview';\n\nimport type { ContentManagerPlugin, DocumentActionProps } from '../../content-manager';\n\n/* -------------------------------------------------------------------------------------------------\n * ClosePreviewButton\n * -----------------------------------------------------------------------------------------------*/\n\nconst ClosePreviewButton = () => {\n const [{ query }] = useQueryParams<{\n plugins?: Record<string, unknown>;\n }>();\n const { formatMessage } = useIntl();\n\n const canGoBack = useHistory('BackButton', (state) => state.canGoBack);\n const goBack = useHistory('BackButton', (state) => state.goBack);\n const history = useHistory('BackButton', (state) => state.history);\n const locationIndex = useHistory('BackButton', (state) => state.currentLocationIndex);\n\n /**\n * Get the link destination from the history.\n * Rely on a fallback (the parent edit view page) if there's no page to go back .\n */\n const historyTo = canGoBack ? history.at(locationIndex - 2) : undefined;\n const fallback = {\n pathname: '..',\n search: stringify(query, { encode: false }),\n } satisfies To;\n const toWithFallback = historyTo ?? fallback;\n\n const handleClick = (e: React.MouseEvent) => {\n if (canGoBack) {\n // Prevent normal link behavior, go back in the history stack instead\n e.preventDefault();\n goBack();\n return;\n }\n\n // Otherwise rely on native link behavior to go back to the edit view. We don't use navigate()\n // here in order to get the relative=\"path\" functionality from the Link component.\n };\n\n return (\n <IconButton\n variant=\"ghost\"\n tag={Link}\n relative=\"path\"\n to={toWithFallback}\n onClick={handleClick}\n label={formatMessage({\n id: 'content-manager.preview.header.close',\n defaultMessage: 'Close preview',\n })}\n >\n <Cross />\n </IconButton>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Status\n * -----------------------------------------------------------------------------------------------*/\n\nconst Status = () => {\n // Get status\n const document = usePreviewContext('PreviewHeader', (state) => state.document);\n const schema = usePreviewContext('PreviewHeader', (state) => state.schema);\n const meta = usePreviewContext('PreviewHeader', (state) => state.meta);\n const hasDraftAndPublished = schema?.options?.draftAndPublish ?? false;\n\n if (!hasDraftAndPublished) {\n return null;\n }\n\n const status = getDocumentStatus(document, meta);\n\n return <DocumentStatus status={status} size=\"XS\" />;\n};\n\nconst PreviewTabs = () => {\n const { formatMessage } = useIntl();\n\n // URL query params\n const [{ query }, setQuery] = useQueryParams<{ status: 'draft' | 'published' }>();\n\n // Get status\n const document = usePreviewContext('PreviewHeader', (state) => state.document);\n const schema = usePreviewContext('PreviewHeader', (state) => state.schema);\n const meta = usePreviewContext('PreviewHeader', (state) => state.meta);\n const hasDraftAndPublish = schema?.options?.draftAndPublish ?? false;\n const documentStatus = getDocumentStatus(document, meta);\n\n const handleTabChange = (status: string) => {\n if (status === 'published' || status === 'draft') {\n setQuery({ status }, 'push', true);\n }\n };\n\n if (!hasDraftAndPublish) {\n return null;\n }\n\n return (\n <Tabs.Root variant=\"simple\" value={query.status || 'draft'} onValueChange={handleTabChange}>\n <Tabs.List\n aria-label={formatMessage({\n id: 'preview.tabs.label',\n defaultMessage: 'Document status',\n })}\n >\n <StatusTab value=\"draft\">\n {formatMessage({\n id: 'content-manager.containers.List.draft',\n defaultMessage: 'draft',\n })}\n </StatusTab>\n <StatusTab value=\"published\" disabLine truncated
@@ -0,0 +1,91 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
require('react');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var designSystem = require('@strapi/design-system');
var qs = require('qs');
var reactIntl = require('react-intl');
var reactRouterDom = require('react-router-dom');
var preview = require('../services/preview.js');
const ConditionalTooltip = ({ isShown, label, children })=>{
if (isShown) {
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
label: label,
children: children
});
}
return children;
};
const PreviewSidePanel = ({ model, documentId, document })=>{
const { formatMessage } = reactIntl.useIntl();
const { trackUsage } = strapiAdmin.useTracking();
const { pathname } = reactRouterDom.useLocation();
const [{ query }] = strapiAdmin.useQueryParams();
const isModified = strapiAdmin.useForm('PreviewSidePanel', (state)=>state.modified);
/**
* The preview URL isn't used in this component, we just fetch it to know if preview is enabled
* for the content type. If it's not, the panel is not displayed. If it is, we display a link to
* /preview, and the URL will already be loaded in the RTK query cache.
*/ const { data, error } = preview.useGetPreviewUrlQuery({
params: {
contentType: model
},
query: {
documentId,
locale: document?.locale,
status: document?.status
}
});
if (!data?.data?.url || error) {
return null;
}
const trackNavigation = ()=>{
// Append /preview to the current URL
const destinationPathname = pathname.replace(/\/$/, '') + '/preview';
trackUsage('willNavigate', {
from: pathname,
to: destinationPathname
});
};
return {
title: formatMessage({
id: 'content-manager.preview.panel.title',
defaultMessage: 'Preview'
}),
content: /*#__PURE__*/ jsxRuntime.jsx(ConditionalTooltip, {
label: formatMessage({
id: 'content-manager.preview.panel.button-disabled-tooltip',
defaultMessage: 'Please save to open the preview'
}),
isShown: isModified,
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
cursor: "not-allowed",
width: "100%",
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
variant: "tertiary",
tag: reactRouterDom.Link,
to: {
pathname: 'preview',
search: qs.stringify(query, {
encode: false
})
},
onClick: trackNavigation,
width: "100%",
disabled: isModified,
pointerEvents: isModified ? 'none' : undefined,
tabIndex: isModified ? -1 : undefined,
children: formatMessage({
id: 'content-manager.preview.panel.button',
defaultMessage: 'Open preview'
})
})
})
})
};
};
exports.PreviewSidePanel = PreviewSidePanel;
//# sourceMappingURL=PreviewSidePanel.js.map
@@ -0,0 +1 @@
{"version":3,"file":"PreviewSidePanel.js","sources":["../../../../admin/src/preview/components/PreviewSidePanel.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useQueryParams, useTracking, useForm } from '@strapi/admin/strapi-admin';\nimport { Box, Button, Tooltip, type TooltipProps } from '@strapi/design-system';\nimport { stringify } from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Link, useLocation } from 'react-router-dom';\n\nimport { useGetPreviewUrlQuery } from '../services/preview';\n\nimport type { PanelComponent } from '@strapi/content-manager/strapi-admin';\nimport type { UID } from '@strapi/types';\n\ninterface ConditionalTooltipProps {\n isShown: boolean;\n label: TooltipProps['label'];\n children: React.ReactNode;\n}\n\nconst ConditionalTooltip = ({ isShown, label, children }: ConditionalTooltipProps) => {\n if (isShown) {\n return <Tooltip label={label}>{children}</Tooltip>;\n }\n\n return children;\n};\n\nconst PreviewSidePanel: PanelComponent = ({ model, documentId, document }) => {\n const { formatMessage } = useIntl();\n const { trackUsage } = useTracking();\n const { pathname } = useLocation();\n const [{ query }] = useQueryParams();\n const isModified = useForm('PreviewSidePanel', (state) => state.modified);\n\n /**\n * The preview URL isn't used in this component, we just fetch it to know if preview is enabled\n * for the content type. If it's not, the panel is not displayed. If it is, we display a link to\n * /preview, and the URL will already be loaded in the RTK query cache.\n */\n const { data, error } = useGetPreviewUrlQuery({\n params: {\n contentType: model as UID.ContentType,\n },\n query: {\n documentId,\n locale: document?.locale,\n status: document?.status,\n },\n });\n\n if (!data?.data?.url || error) {\n return null;\n }\n\n const trackNavigation = () => {\n // Append /preview to the current URL\n const destinationPathname = pathname.replace(/\\/$/, '') + '/preview';\n trackUsage('willNavigate', { from: pathname, to: destinationPathname });\n };\n\n return {\n title: formatMessage({ id: 'content-manager.preview.panel.title', defaultMessage: 'Preview' }),\n content: (\n <ConditionalTooltip\n label={formatMessage({\n id: 'content-manager.preview.panel.button-disabled-tooltip',\n defaultMessage: 'Please save to open the preview',\n })}\n isShown={isModified}\n >\n <Box cursor=\"not-allowed\" width=\"100%\">\n <Button\n variant=\"tertiary\"\n tag={Link}\n to={{ pathname: 'preview', search: stringify(query, { encode: false }) }}\n onClick={trackNavigation}\n width=\"100%\"\n disabled={isModified}\n pointerEvents={isModified ? 'none' : undefined}\n tabIndex={isModified ? -1 : undefined}\n >\n {formatMessage({\n id: 'content-manager.preview.panel.button',\n defaultMessage: 'Open preview',\n })}\n </Button>\n </Box>\n </ConditionalTooltip>\n ),\n };\n};\n\nexport { PreviewSidePanel };\n"],"names":["ConditionalTooltip","isShown","label","children","_jsx","Tooltip","PreviewSidePanel","model","documentId","document","formatMessage","useIntl","trackUsage","useTracking","pathname","useLocation","query","useQueryParams","isModified","useForm","state","modified","data","error","useGetPreviewUrlQuery","params","contentType","locale","status","url","trackNavigation","destinationPathname","replace","from","to","title","id","defaultMessage","content","Box","cursor","width","Button","variant","tag","Link","search","stringify","encode","onClick","disabled","pointerEvents","undefined","tabIndex"],"mappings":";;;;;;;;;;;AAmBA,MAAMA,kBAAAA,GAAqB,CAAC,EAAEC,OAAO,EAAEC,KAAK,EAAEC,QAAQ,EAA2B,GAAA;AAC/E,IAAA,IAAIF,OAAS,EAAA;AACX,QAAA,qBAAOG,cAACC,CAAAA,oBAAAA,EAAAA;YAAQH,KAAOA,EAAAA,KAAAA;AAAQC,YAAAA,QAAAA,EAAAA;;AACjC;IAEA,OAAOA,QAAAA;AACT,CAAA;AAEMG,MAAAA,gBAAAA,GAAmC,CAAC,EAAEC,KAAK,EAAEC,UAAU,EAAEC,QAAQ,EAAE,GAAA;IACvE,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;IAC1B,MAAM,EAAEC,UAAU,EAAE,GAAGC,uBAAAA,EAAAA;IACvB,MAAM,EAAEC,QAAQ,EAAE,GAAGC,0BAAAA,EAAAA;AACrB,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,CAAC,GAAGC,0BAAAA,EAAAA;AACpB,IAAA,MAAMC,aAAaC,mBAAQ,CAAA,kBAAA,EAAoB,CAACC,KAAAA,GAAUA,MAAMC,QAAQ,CAAA;AAExE;;;;AAIC,MACD,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGC,6BAAsB,CAAA;QAC5CC,MAAQ,EAAA;YACNC,WAAanB,EAAAA;AACf,SAAA;QACAS,KAAO,EAAA;AACLR,YAAAA,UAAAA;AACAmB,YAAAA,MAAAA,EAAQlB,QAAUkB,EAAAA,MAAAA;AAClBC,YAAAA,MAAAA,EAAQnB,QAAUmB,EAAAA;AACpB;AACF,KAAA,CAAA;AAEA,IAAA,IAAI,CAACN,IAAAA,EAAMA,IAAMO,EAAAA,GAAAA,IAAON,KAAO,EAAA;QAC7B,OAAO,IAAA;AACT;AAEA,IAAA,MAAMO,eAAkB,GAAA,IAAA;;AAEtB,QAAA,MAAMC,mBAAsBjB,GAAAA,QAAAA,CAASkB,OAAO,CAAC,OAAO,EAAM,CAAA,GAAA,UAAA;AAC1DpB,QAAAA,UAAAA,CAAW,cAAgB,EAAA;YAAEqB,IAAMnB,EAAAA,QAAAA;YAAUoB,EAAIH,EAAAA;AAAoB,SAAA,CAAA;AACvE,KAAA;IAEA,OAAO;AACLI,Line truncated
@@ -0,0 +1,89 @@
import { jsx } from 'react/jsx-runtime';
import 'react';
import { useTracking, useQueryParams, useForm } from '@strapi/admin/strapi-admin';
import { Box, Button, Tooltip } from '@strapi/design-system';
import { stringify } from 'qs';
import { useIntl } from 'react-intl';
import { useLocation, Link } from 'react-router-dom';
import { useGetPreviewUrlQuery } from '../services/preview.mjs';
const ConditionalTooltip = ({ isShown, label, children })=>{
if (isShown) {
return /*#__PURE__*/ jsx(Tooltip, {
label: label,
children: children
});
}
return children;
};
const PreviewSidePanel = ({ model, documentId, document })=>{
const { formatMessage } = useIntl();
const { trackUsage } = useTracking();
const { pathname } = useLocation();
const [{ query }] = useQueryParams();
const isModified = useForm('PreviewSidePanel', (state)=>state.modified);
/**
* The preview URL isn't used in this component, we just fetch it to know if preview is enabled
* for the content type. If it's not, the panel is not displayed. If it is, we display a link to
* /preview, and the URL will already be loaded in the RTK query cache.
*/ const { data, error } = useGetPreviewUrlQuery({
params: {
contentType: model
},
query: {
documentId,
locale: document?.locale,
status: document?.status
}
});
if (!data?.data?.url || error) {
return null;
}
const trackNavigation = ()=>{
// Append /preview to the current URL
const destinationPathname = pathname.replace(/\/$/, '') + '/preview';
trackUsage('willNavigate', {
from: pathname,
to: destinationPathname
});
};
return {
title: formatMessage({
id: 'content-manager.preview.panel.title',
defaultMessage: 'Preview'
}),
content: /*#__PURE__*/ jsx(ConditionalTooltip, {
label: formatMessage({
id: 'content-manager.preview.panel.button-disabled-tooltip',
defaultMessage: 'Please save to open the preview'
}),
isShown: isModified,
children: /*#__PURE__*/ jsx(Box, {
cursor: "not-allowed",
width: "100%",
children: /*#__PURE__*/ jsx(Button, {
variant: "tertiary",
tag: Link,
to: {
pathname: 'preview',
search: stringify(query, {
encode: false
})
},
onClick: trackNavigation,
width: "100%",
disabled: isModified,
pointerEvents: isModified ? 'none' : undefined,
tabIndex: isModified ? -1 : undefined,
children: formatMessage({
id: 'content-manager.preview.panel.button',
defaultMessage: 'Open preview'
})
})
})
})
};
};
export { PreviewSidePanel };
//# sourceMappingURL=PreviewSidePanel.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"PreviewSidePanel.mjs","sources":["../../../../admin/src/preview/components/PreviewSidePanel.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useQueryParams, useTracking, useForm } from '@strapi/admin/strapi-admin';\nimport { Box, Button, Tooltip, type TooltipProps } from '@strapi/design-system';\nimport { stringify } from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Link, useLocation } from 'react-router-dom';\n\nimport { useGetPreviewUrlQuery } from '../services/preview';\n\nimport type { PanelComponent } from '@strapi/content-manager/strapi-admin';\nimport type { UID } from '@strapi/types';\n\ninterface ConditionalTooltipProps {\n isShown: boolean;\n label: TooltipProps['label'];\n children: React.ReactNode;\n}\n\nconst ConditionalTooltip = ({ isShown, label, children }: ConditionalTooltipProps) => {\n if (isShown) {\n return <Tooltip label={label}>{children}</Tooltip>;\n }\n\n return children;\n};\n\nconst PreviewSidePanel: PanelComponent = ({ model, documentId, document }) => {\n const { formatMessage } = useIntl();\n const { trackUsage } = useTracking();\n const { pathname } = useLocation();\n const [{ query }] = useQueryParams();\n const isModified = useForm('PreviewSidePanel', (state) => state.modified);\n\n /**\n * The preview URL isn't used in this component, we just fetch it to know if preview is enabled\n * for the content type. If it's not, the panel is not displayed. If it is, we display a link to\n * /preview, and the URL will already be loaded in the RTK query cache.\n */\n const { data, error } = useGetPreviewUrlQuery({\n params: {\n contentType: model as UID.ContentType,\n },\n query: {\n documentId,\n locale: document?.locale,\n status: document?.status,\n },\n });\n\n if (!data?.data?.url || error) {\n return null;\n }\n\n const trackNavigation = () => {\n // Append /preview to the current URL\n const destinationPathname = pathname.replace(/\\/$/, '') + '/preview';\n trackUsage('willNavigate', { from: pathname, to: destinationPathname });\n };\n\n return {\n title: formatMessage({ id: 'content-manager.preview.panel.title', defaultMessage: 'Preview' }),\n content: (\n <ConditionalTooltip\n label={formatMessage({\n id: 'content-manager.preview.panel.button-disabled-tooltip',\n defaultMessage: 'Please save to open the preview',\n })}\n isShown={isModified}\n >\n <Box cursor=\"not-allowed\" width=\"100%\">\n <Button\n variant=\"tertiary\"\n tag={Link}\n to={{ pathname: 'preview', search: stringify(query, { encode: false }) }}\n onClick={trackNavigation}\n width=\"100%\"\n disabled={isModified}\n pointerEvents={isModified ? 'none' : undefined}\n tabIndex={isModified ? -1 : undefined}\n >\n {formatMessage({\n id: 'content-manager.preview.panel.button',\n defaultMessage: 'Open preview',\n })}\n </Button>\n </Box>\n </ConditionalTooltip>\n ),\n };\n};\n\nexport { PreviewSidePanel };\n"],"names":["ConditionalTooltip","isShown","label","children","_jsx","Tooltip","PreviewSidePanel","model","documentId","document","formatMessage","useIntl","trackUsage","useTracking","pathname","useLocation","query","useQueryParams","isModified","useForm","state","modified","data","error","useGetPreviewUrlQuery","params","contentType","locale","status","url","trackNavigation","destinationPathname","replace","from","to","title","id","defaultMessage","content","Box","cursor","width","Button","variant","tag","Link","search","stringify","encode","onClick","disabled","pointerEvents","undefined","tabIndex"],"mappings":";;;;;;;;;AAmBA,MAAMA,kBAAAA,GAAqB,CAAC,EAAEC,OAAO,EAAEC,KAAK,EAAEC,QAAQ,EAA2B,GAAA;AAC/E,IAAA,IAAIF,OAAS,EAAA;AACX,QAAA,qBAAOG,GAACC,CAAAA,OAAAA,EAAAA;YAAQH,KAAOA,EAAAA,KAAAA;AAAQC,YAAAA,QAAAA,EAAAA;;AACjC;IAEA,OAAOA,QAAAA;AACT,CAAA;AAEMG,MAAAA,gBAAAA,GAAmC,CAAC,EAAEC,KAAK,EAAEC,UAAU,EAAEC,QAAQ,EAAE,GAAA;IACvE,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;IAC1B,MAAM,EAAEC,UAAU,EAAE,GAAGC,WAAAA,EAAAA;IACvB,MAAM,EAAEC,QAAQ,EAAE,GAAGC,WAAAA,EAAAA;AACrB,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,CAAC,GAAGC,cAAAA,EAAAA;AACpB,IAAA,MAAMC,aAAaC,OAAQ,CAAA,kBAAA,EAAoB,CAACC,KAAAA,GAAUA,MAAMC,QAAQ,CAAA;AAExE;;;;AAIC,MACD,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGC,qBAAsB,CAAA;QAC5CC,MAAQ,EAAA;YACNC,WAAanB,EAAAA;AACf,SAAA;QACAS,KAAO,EAAA;AACLR,YAAAA,UAAAA;AACAmB,YAAAA,MAAAA,EAAQlB,QAAUkB,EAAAA,MAAAA;AAClBC,YAAAA,MAAAA,EAAQnB,QAAUmB,EAAAA;AACpB;AACF,KAAA,CAAA;AAEA,IAAA,IAAI,CAACN,IAAAA,EAAMA,IAAMO,EAAAA,GAAAA,IAAON,KAAO,EAAA;QAC7B,OAAO,IAAA;AACT;AAEA,IAAA,MAAMO,eAAkB,GAAA,IAAA;;AAEtB,QAAA,MAAMC,mBAAsBjB,GAAAA,QAAAA,CAASkB,OAAO,CAAC,OAAO,EAAM,CAAA,GAAA,UAAA;AAC1DpB,QAAAA,UAAAA,CAAW,cAAgB,EAAA;YAAEqB,IAAMnB,EAAAA,QAAAA;YAAUoB,EAAIH,EAAAA;AAAoB,SAAA,CAAA;AACvE,KAAA;IAEA,OAAO;AACLI,QAAAA,KLine truncated
@@ -0,0 +1,15 @@
'use strict';
var PreviewSidePanel = require('./components/PreviewSidePanel.js');
const previewAdmin = {
bootstrap (app) {
const contentManagerPluginApis = app.getPlugin('content-manager').apis;
contentManagerPluginApis.addEditViewSidePanel([
PreviewSidePanel.PreviewSidePanel
]);
}
};
exports.previewAdmin = previewAdmin;
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":["../../../admin/src/preview/index.ts"],"sourcesContent":["/* eslint-disable check-file/no-index */\n\nimport { PreviewSidePanel } from './components/PreviewSidePanel';\n\nimport type { ContentManagerPlugin } from '../content-manager';\nimport type { PluginDefinition } from '@strapi/admin/strapi-admin';\n\nconst previewAdmin: Partial<PluginDefinition> = {\n bootstrap(app) {\n const contentManagerPluginApis = app.getPlugin('content-manager')\n .apis as ContentManagerPlugin['config']['apis'];\n\n contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);\n },\n};\n\nexport { previewAdmin };\n"],"names":["previewAdmin","bootstrap","app","contentManagerPluginApis","getPlugin","apis","addEditViewSidePanel","PreviewSidePanel"],"mappings":";;;;AAOA,MAAMA,YAA0C,GAAA;AAC9CC,IAAAA,SAAAA,CAAAA,CAAUC,GAAG,EAAA;AACX,QAAA,MAAMC,wBAA2BD,GAAAA,GAAAA,CAAIE,SAAS,CAAC,mBAC5CC,IAAI;AAEPF,QAAAA,wBAAAA,CAAyBG,oBAAoB,CAAC;AAACC,YAAAA;AAAiB,SAAA,CAAA;AAClE;AACF;;;;"}
@@ -0,0 +1,13 @@
import { PreviewSidePanel } from './components/PreviewSidePanel.mjs';
const previewAdmin = {
bootstrap (app) {
const contentManagerPluginApis = app.getPlugin('content-manager').apis;
contentManagerPluginApis.addEditViewSidePanel([
PreviewSidePanel
]);
}
};
export { previewAdmin };
//# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","sources":["../../../admin/src/preview/index.ts"],"sourcesContent":["/* eslint-disable check-file/no-index */\n\nimport { PreviewSidePanel } from './components/PreviewSidePanel';\n\nimport type { ContentManagerPlugin } from '../content-manager';\nimport type { PluginDefinition } from '@strapi/admin/strapi-admin';\n\nconst previewAdmin: Partial<PluginDefinition> = {\n bootstrap(app) {\n const contentManagerPluginApis = app.getPlugin('content-manager')\n .apis as ContentManagerPlugin['config']['apis'];\n\n contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);\n },\n};\n\nexport { previewAdmin };\n"],"names":["previewAdmin","bootstrap","app","contentManagerPluginApis","getPlugin","apis","addEditViewSidePanel","PreviewSidePanel"],"mappings":";;AAOA,MAAMA,YAA0C,GAAA;AAC9CC,IAAAA,SAAAA,CAAAA,CAAUC,GAAG,EAAA;AACX,QAAA,MAAMC,wBAA2BD,GAAAA,GAAAA,CAAIE,SAAS,CAAC,mBAC5CC,IAAI;AAEPF,QAAAA,wBAAAA,CAAyBG,oBAAoB,CAAC;AAACC,YAAAA;AAAiB,SAAA,CAAA;AAClE;AACF;;;;"}
@@ -0,0 +1,286 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var designSystem = require('@strapi/design-system');
var Icons = require('@strapi/icons');
var reactIntl = require('react-intl');
var reactRouterDom = require('react-router-dom');
var styledComponents = require('styled-components');
var collections = require('../../constants/collections.js');
var DocumentRBAC = require('../../features/DocumentRBAC.js');
var useDocument = require('../../hooks/useDocument.js');
var useDocumentLayout = require('../../hooks/useDocumentLayout.js');
var FormLayout = require('../../pages/EditView/components/FormLayout.js');
var api = require('../../utils/api.js');
var validation = require('../../utils/validation.js');
var PreviewHeader = require('../components/PreviewHeader.js');
var preview = require('../services/preview.js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
const [PreviewProvider, usePreviewContext] = strapiAdmin.createContext('PreviewPage');
/* -------------------------------------------------------------------------------------------------
* PreviewPage
* -----------------------------------------------------------------------------------------------*/ const AnimatedArrow = styledComponents.styled(Icons.ArrowLineLeft)`
will-change: transform;
rotate: ${(props)=>props.isSideEditorOpen ? '0deg' : '180deg'};
transition: rotate 0.2s ease-in-out;
`;
const PreviewPage = ()=>{
const location = reactRouterDom.useLocation();
const { formatMessage } = reactIntl.useIntl();
const iframeRef = React__namespace.useRef(null);
const [isSideEditorOpen, setIsSideEditorOpen] = React__namespace.useState(true);
// Read all the necessary data from the URL to find the right preview URL
const { slug: model, id: documentId, collectionType } = reactRouterDom.useParams();
const [{ query }] = strapiAdmin.useQueryParams();
const params = React__namespace.useMemo(()=>api.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');
}
// Only collection types must have a documentId
if (collectionType === collections.COLLECTION_TYPES && !documentId) {
throw new Error('Could not find documentId in url params');
}
const previewUrlResponse = preview.useGetPreviewUrlQuery({
params: {
contentType: model
},
query: {
documentId,
locale: params.locale,
status: params.status
}
});
const documentResponse = useDocument.useDocument({
model,
collectionType,
documentId,
params
});
const documentLayoutResponse = useDocumentLayout.useDocumentLayout(model);
const isLoading = previewUrlResponse.isLoading || documentLayoutResponse.isLoading || documentResponse.isLoading;
if (isLoading && !documentResponse.document?.documentId) {
return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.Loading, {});
}
const initialValues = documentResponse.getInitialFormValues();
if (previewUrlResponse.error || documentLayoutResponse.error || !documentResponse.document || !documentResponse.meta || !documentResponse.schema || !initialValues) {
return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.Error, {});
}
if (!previewUrlResponse.data?.data?.url) {
return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.NoData, {});
}
const documentTitle = documentResponse.getTitle(documentLayoutResponse.edit.settings.mainField);
const validateSync = (values, options)=>{
const yupSchema = validation.createYupSchema(documentResponse.schema?.attributes, documentResponse.components, {
status: documentResponse.document?.status,
...options
});
return yupSchema.validateSync(values, {
abortEarly: false
});
};
const previewUrl = previewUrlResponse.data.data.url;
const onPreview = ()=>{
iframeRef?.current?.contentWindow?.postMessage({
type: 'strapiUpdate'
}, // The iframe origin is safe to use since it must be provided through the allowedOrigins config
new URL(iframeRef.current.src).origin);
};
const hasAdvancedPreview = window.strapi.features.isEnabled('cms-advanced-preview');
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.Title, {
children: formatMessage({
id: 'content-manager.preview.page-title',
defaultMessage: '{contentType} preview'
}, {
contentType: documentTitle
})
}),
/*#__PURE__*/ jsxRuntime.jsx(PreviewProvider, {
url: previewUrl,
document: documentResponse.document,
title: documentTitle,
meta: documentResponse.meta,
schema: documentResponse.schema,
layout: documentLayoutResponse.edit,
onPreview: onPreview,
children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Form, {
method: "PUT",
disabled: query.status === 'published' && documentResponse && documentResponse.document.status !== 'draft',
initialValues: documentResponse.getInitialFormValues(),
initialErrors: location?.state?.forceValidation ? validateSync(initialValues, {}) : {},
height: "100%",
validate: (values, options)=>{
const yupSchema = validation.createYupSchema(documentResponse.schema?.attributes, documentResponse.components, {
status: documentResponse.document?.status,
...options
});
return yupSchema.validate(values, {
abortEarly: false
});
},
children: ({ resetForm })=>/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
direction: "column",
height: "100%",
alignItems: "stretch",
children: [
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Blocker, {
onProceed: resetForm
}),
/*#__PURE__*/ jsxRuntime.jsx(PreviewHeader.PreviewHeader, {}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
flex: 1,
overflow: "auto",
alignItems: "stretch",
children: [
hasAdvancedPreview && /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
overflow: "auto",
width: isSideEditorOpen ? '50%' : 0,
borderWidth: "0 1px 0 0",
borderColor: "neutral150",
paddingTop: 6,
paddingBottom: 6,
// Remove horizontal padding when the editor is closed or it won't fully disappear
paddingLeft: isSideEditorOpen ? 6 : 0,
paddingRight: isSideEditorOpen ? 6 : 0,
transition: "all 0.2s ease-in-out",
children: /*#__PURE__*/ jsxRuntime.jsx(FormLayout.FormLayout, {
layout: documentLayoutResponse.edit.layout,
document: documentResponse,
hasBackground: false
})
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
position: "relative",
flex: 1,
height: "100%",
overflow: "hidden",
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
"data-testid": "preview-iframe",
ref: iframeRef,
src: previewUrl,
title: formatMessage({
id: 'content-manager.preview.panel.title',
defaultMessage: 'Preview'
}),
width: "100%",
height: "100%",
borderWidth: 0,
tag: "iframe"
}, previewUrl),
hasAdvancedPreview && /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
variant: "tertiary",
label: formatMessage(isSideEditorOpen ? {
id: 'content-manager.preview.content.close-editor',
defaultMessage: 'Close editor'
} : {
id: 'content-manager.preview.content.open-editor',
defaultMessage: 'Open editor'
}),
onClick: ()=>setIsSideEditorOpen((prev)=>!prev),
position: "absolute",
top: 2,
left: 2,
children: /*#__PURE__*/ jsxRuntime.jsx(AnimatedArrow, {
isSideEditorOpen: isSideEditorOpen
})
})
]
})
]
})
]
})
})
})
]
});
};
/* -------------------------------------------------------------------------------------------------
* ProtectedPreviewPage
* -----------------------------------------------------------------------------------------------*/ const ProtectedPreviewPageImpl = ()=>{
const { slug: model } = reactRouterDom.useParams();
const { permissions = [], isLoading, error } = strapiAdmin.useRBAC([
{
action: 'plugin::content-manager.explorer.read',
subject: model
},
{
action: 'plugin::content-manager.explorer.update',
subject: model
},
{
action: 'plugin::content-manager.explorer.publish',
subject: model
}
]);
if (isLoading) {
return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.Loading, {});
}
if (error || !model) {
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
height: "100vh",
width: "100vw",
position: "fixed",
top: 0,
left: 0,
zIndex: 2,
background: "neutral0",
children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.Error, {})
});
}
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
height: "100vh",
width: "100vw",
position: "fixed",
top: 0,
left: 0,
zIndex: 2,
background: "neutral0",
children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.Protect, {
permissions: permissions.filter((permission)=>permission.action.includes('explorer.read')),
children: /*#__PURE__*/ jsxRuntime.jsx(DocumentRBAC.DocumentRBAC, {
permissions: permissions,
children: /*#__PURE__*/ jsxRuntime.jsx(PreviewPage, {})
})
})
});
};
const ProtectedPreviewPage = ()=>{
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Portal, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.FocusTrap, {
children: /*#__PURE__*/ jsxRuntime.jsx(ProtectedPreviewPageImpl, {})
})
});
};
exports.ProtectedPreviewPage = ProtectedPreviewPage;
exports.usePreviewContext = usePreviewContext;
//# sourceMappingURL=Preview.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Preview.js","sources":["../../../../admin/src/preview/pages/Preview.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Page,\n useQueryParams,\n useRBAC,\n createContext,\n Form as FormContext,\n Blocker,\n} from '@strapi/admin/strapi-admin';\nimport { Box, Flex, FocusTrap, IconButton, Portal } from '@strapi/design-system';\nimport { ArrowLineLeft } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useLocation, useParams } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { GetPreviewUrl } from '../../../../shared/contracts/preview';\nimport { COLLECTION_TYPES } from '../../constants/collections';\nimport { DocumentRBAC } from '../../features/DocumentRBAC';\nimport { type UseDocument, useDocument } from '../../hooks/useDocument';\nimport { type EditLayout, useDocumentLayout } from '../../hooks/useDocumentLayout';\nimport { FormLayout } from '../../pages/EditView/components/FormLayout';\nimport { buildValidParams } from '../../utils/api';\nimport { createYupSchema } from '../../utils/validation';\nimport { PreviewHeader } from '../components/PreviewHeader';\nimport { useGetPreviewUrlQuery } from '../services/preview';\n\nimport type { UID } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * PreviewProvider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface PreviewContextValue {\n url: string;\n title: string;\n document: NonNullable<ReturnType<UseDocument>['document']>;\n meta: NonNullable<ReturnType<UseDocument>['meta']>;\n schema: NonNullable<ReturnType<UseDocument>['schema']>;\n layout: EditLayout;\n onPreview: () => void;\n}\n\nconst [PreviewProvider, usePreviewContext] = createContext<PreviewContextValue>('PreviewPage');\n\n/* -------------------------------------------------------------------------------------------------\n * PreviewPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst AnimatedArrow = styled(ArrowLineLeft)<{ isSideEditorOpen: boolean }>`\n will-change: transform;\n rotate: ${(props) => (props.isSideEditorOpen ? '0deg' : '180deg')};\n transition: rotate 0.2s ease-in-out;\n`;\n\nconst PreviewPage = () => {\n const location = useLocation();\n const { formatMessage } = useIntl();\n\n const iframeRef = React.useRef<HTMLIFrameElement>(null);\n const [isSideEditorOpen, setIsSideEditorOpen] = React.useState(true);\n\n // Read all the necessary data from the URL to find the right preview URL\n const {\n slug: model,\n id: documentId,\n collectionType,\n } = useParams<{\n slug: UID.ContentType;\n id: string;\n collectionType: string;\n }>();\n const [{ query }] = useQueryParams<{\n plugins?: Record<string, unknown>;\n status?: string;\n }>();\n\n const params = React.useMemo(() => buildValidParams(query), [query]);\n\n if (!collectionType) {\n throw new Error('Could not find collectionType in url params');\n }\n\n if (!model) {\n throw new Error('Could not find model in url params');\n }\n\n // Only collection types must have a documentId\n if (collectionType === COLLECTION_TYPES && !documentId) {\n throw new Error('Could not find documentId in url params');\n }\n\n const previewUrlResponse = useGetPreviewUrlQuery({\n params: {\n contentType: model,\n },\n query: {\n documentId,\n locale: params.locale,\n status: params.status as GetPreviewUrl.Request['query']['status'],\n },\n });\n const documentResponse = useDocument({\n model,\n collectionType,\n documentId,\n params,\n });\n const documentLayoutResponse = useDocumentLayout(model);\n\n const isLoading =\n previewUrlResponse.isLoading || documentLayoutResponse.isLoading || documentResponse.isLoading;\n if (isLoading && !documentResponse.document?.documentId) {\n return <Page.Loading />;\n }\n\n const initialValues = documentResponse.getInitialFormValues();\n\n if (\n previewUrlResponse.error ||\n documentLayoutResponse.error ||\n !documentResponse.document ||\n !documentResponse.meta ||\n !documentResponse.schema ||\n !initialValues\n ) {\n return <Page.Error />;\n }\n\n if (!previewUrlResponse.data?.data?.url) {\n return <Page.NoData />;\n }\n\n const documentTitle = documentResponse.getTitle(documentLayoutResponse.edit.settings.mainField);\n\n const validateSync = (values: Record<string, unknown>, options: Record<string, string>) => {\n const yupSchema = createYupSchema(\n documentResponse.schema?.attributes,\n documentResponse.components,\n {\n status: documentResponse.document?.status,\n ...options,\n }\n );\n\n return yupSchema.validateSync(values, { abortEarly: false });\n };\n\n const previewUrl = previewUrlResponse.data.data.url;\n\n const onPLine truncated
@@ -0,0 +1,264 @@
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import * as React from 'react';
import { createContext, useRBAC, Page, useQueryParams, Form, Blocker } from '@strapi/admin/strapi-admin';
import { Portal, FocusTrap, Box, Flex, IconButton } from '@strapi/design-system';
import { ArrowLineLeft } from '@strapi/icons';
import { useIntl } from 'react-intl';
import { useParams, useLocation } from 'react-router-dom';
import { styled } from 'styled-components';
import { COLLECTION_TYPES } from '../../constants/collections.mjs';
import { DocumentRBAC } from '../../features/DocumentRBAC.mjs';
import { useDocument } from '../../hooks/useDocument.mjs';
import { useDocumentLayout } from '../../hooks/useDocumentLayout.mjs';
import { FormLayout } from '../../pages/EditView/components/FormLayout.mjs';
import { buildValidParams } from '../../utils/api.mjs';
import { createYupSchema } from '../../utils/validation.mjs';
import { PreviewHeader } from '../components/PreviewHeader.mjs';
import { useGetPreviewUrlQuery } from '../services/preview.mjs';
const [PreviewProvider, usePreviewContext] = createContext('PreviewPage');
/* -------------------------------------------------------------------------------------------------
* PreviewPage
* -----------------------------------------------------------------------------------------------*/ const AnimatedArrow = styled(ArrowLineLeft)`
will-change: transform;
rotate: ${(props)=>props.isSideEditorOpen ? '0deg' : '180deg'};
transition: rotate 0.2s ease-in-out;
`;
const PreviewPage = ()=>{
const location = useLocation();
const { formatMessage } = useIntl();
const iframeRef = React.useRef(null);
const [isSideEditorOpen, setIsSideEditorOpen] = React.useState(true);
// Read all the necessary data from the URL to find the right preview URL
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');
}
// Only collection types must have a documentId
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);
const isLoading = previewUrlResponse.isLoading || documentLayoutResponse.isLoading || documentResponse.isLoading;
if (isLoading && !documentResponse.document?.documentId) {
return /*#__PURE__*/ jsx(Page.Loading, {});
}
const initialValues = documentResponse.getInitialFormValues();
if (previewUrlResponse.error || documentLayoutResponse.error || !documentResponse.document || !documentResponse.meta || !documentResponse.schema || !initialValues) {
return /*#__PURE__*/ jsx(Page.Error, {});
}
if (!previewUrlResponse.data?.data?.url) {
return /*#__PURE__*/ jsx(Page.NoData, {});
}
const documentTitle = documentResponse.getTitle(documentLayoutResponse.edit.settings.mainField);
const validateSync = (values, options)=>{
const yupSchema = createYupSchema(documentResponse.schema?.attributes, documentResponse.components, {
status: documentResponse.document?.status,
...options
});
return yupSchema.validateSync(values, {
abortEarly: false
});
};
const previewUrl = previewUrlResponse.data.data.url;
const onPreview = ()=>{
iframeRef?.current?.contentWindow?.postMessage({
type: 'strapiUpdate'
}, // The iframe origin is safe to use since it must be provided through the allowedOrigins config
new URL(iframeRef.current.src).origin);
};
const hasAdvancedPreview = window.strapi.features.isEnabled('cms-advanced-preview');
return /*#__PURE__*/ jsxs(Fragment, {
children: [
/*#__PURE__*/ jsx(Page.Title, {
children: formatMessage({
id: 'content-manager.preview.page-title',
defaultMessage: '{contentType} preview'
}, {
contentType: documentTitle
})
}),
/*#__PURE__*/ jsx(PreviewProvider, {
url: previewUrl,
document: documentResponse.document,
title: documentTitle,
meta: documentResponse.meta,
schema: documentResponse.schema,
layout: documentLayoutResponse.edit,
onPreview: onPreview,
children: /*#__PURE__*/ jsx(Form, {
method: "PUT",
disabled: query.status === 'published' && documentResponse && documentResponse.document.status !== 'draft',
initialValues: documentResponse.getInitialFormValues(),
initialErrors: location?.state?.forceValidation ? validateSync(initialValues, {}) : {},
height: "100%",
validate: (values, options)=>{
const yupSchema = createYupSchema(documentResponse.schema?.attributes, documentResponse.components, {
status: documentResponse.document?.status,
...options
});
return yupSchema.validate(values, {
abortEarly: false
});
},
children: ({ resetForm })=>/*#__PURE__*/ jsxs(Flex, {
direction: "column",
height: "100%",
alignItems: "stretch",
children: [
/*#__PURE__*/ jsx(Blocker, {
onProceed: resetForm
}),
/*#__PURE__*/ jsx(PreviewHeader, {}),
/*#__PURE__*/ jsxs(Flex, {
flex: 1,
overflow: "auto",
alignItems: "stretch",
children: [
hasAdvancedPreview && /*#__PURE__*/ jsx(Box, {
overflow: "auto",
width: isSideEditorOpen ? '50%' : 0,
borderWidth: "0 1px 0 0",
borderColor: "neutral150",
paddingTop: 6,
paddingBottom: 6,
// Remove horizontal padding when the editor is closed or it won't fully disappear
paddingLeft: isSideEditorOpen ? 6 : 0,
paddingRight: isSideEditorOpen ? 6 : 0,
transition: "all 0.2s ease-in-out",
children: /*#__PURE__*/ jsx(FormLayout, {
layout: documentLayoutResponse.edit.layout,
document: documentResponse,
hasBackground: false
})
}),
/*#__PURE__*/ jsxs(Box, {
position: "relative",
flex: 1,
height: "100%",
overflow: "hidden",
children: [
/*#__PURE__*/ jsx(Box, {
"data-testid": "preview-iframe",
ref: iframeRef,
src: previewUrl,
title: formatMessage({
id: 'content-manager.preview.panel.title',
defaultMessage: 'Preview'
}),
width: "100%",
height: "100%",
borderWidth: 0,
tag: "iframe"
}, previewUrl),
hasAdvancedPreview && /*#__PURE__*/ jsx(IconButton, {
variant: "tertiary",
label: formatMessage(isSideEditorOpen ? {
id: 'content-manager.preview.content.close-editor',
defaultMessage: 'Close editor'
} : {
id: 'content-manager.preview.content.open-editor',
defaultMessage: 'Open editor'
}),
onClick: ()=>setIsSideEditorOpen((prev)=>!prev),
position: "absolute",
top: 2,
left: 2,
children: /*#__PURE__*/ jsx(AnimatedArrow, {
isSideEditorOpen: isSideEditorOpen
})
})
]
})
]
})
]
})
})
})
]
});
};
/* -------------------------------------------------------------------------------------------------
* ProtectedPreviewPage
* -----------------------------------------------------------------------------------------------*/ const ProtectedPreviewPageImpl = ()=>{
const { slug: model } = useParams();
const { permissions = [], isLoading, error } = useRBAC([
{
action: 'plugin::content-manager.explorer.read',
subject: model
},
{
action: 'plugin::content-manager.explorer.update',
subject: model
},
{
action: 'plugin::content-manager.explorer.publish',
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: permissions.filter((permission)=>permission.action.includes('explorer.read')),
children: /*#__PURE__*/ jsx(DocumentRBAC, {
permissions: permissions,
children: /*#__PURE__*/ jsx(PreviewPage, {})
})
})
});
};
const ProtectedPreviewPage = ()=>{
return /*#__PURE__*/ jsx(Portal, {
children: /*#__PURE__*/ jsx(FocusTrap, {
children: /*#__PURE__*/ jsx(ProtectedPreviewPageImpl, {})
})
});
};
export { ProtectedPreviewPage, usePreviewContext };
//# sourceMappingURL=Preview.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"Preview.mjs","sources":["../../../../admin/src/preview/pages/Preview.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Page,\n useQueryParams,\n useRBAC,\n createContext,\n Form as FormContext,\n Blocker,\n} from '@strapi/admin/strapi-admin';\nimport { Box, Flex, FocusTrap, IconButton, Portal } from '@strapi/design-system';\nimport { ArrowLineLeft } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useLocation, useParams } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { GetPreviewUrl } from '../../../../shared/contracts/preview';\nimport { COLLECTION_TYPES } from '../../constants/collections';\nimport { DocumentRBAC } from '../../features/DocumentRBAC';\nimport { type UseDocument, useDocument } from '../../hooks/useDocument';\nimport { type EditLayout, useDocumentLayout } from '../../hooks/useDocumentLayout';\nimport { FormLayout } from '../../pages/EditView/components/FormLayout';\nimport { buildValidParams } from '../../utils/api';\nimport { createYupSchema } from '../../utils/validation';\nimport { PreviewHeader } from '../components/PreviewHeader';\nimport { useGetPreviewUrlQuery } from '../services/preview';\n\nimport type { UID } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * PreviewProvider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface PreviewContextValue {\n url: string;\n title: string;\n document: NonNullable<ReturnType<UseDocument>['document']>;\n meta: NonNullable<ReturnType<UseDocument>['meta']>;\n schema: NonNullable<ReturnType<UseDocument>['schema']>;\n layout: EditLayout;\n onPreview: () => void;\n}\n\nconst [PreviewProvider, usePreviewContext] = createContext<PreviewContextValue>('PreviewPage');\n\n/* -------------------------------------------------------------------------------------------------\n * PreviewPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst AnimatedArrow = styled(ArrowLineLeft)<{ isSideEditorOpen: boolean }>`\n will-change: transform;\n rotate: ${(props) => (props.isSideEditorOpen ? '0deg' : '180deg')};\n transition: rotate 0.2s ease-in-out;\n`;\n\nconst PreviewPage = () => {\n const location = useLocation();\n const { formatMessage } = useIntl();\n\n const iframeRef = React.useRef<HTMLIFrameElement>(null);\n const [isSideEditorOpen, setIsSideEditorOpen] = React.useState(true);\n\n // Read all the necessary data from the URL to find the right preview URL\n const {\n slug: model,\n id: documentId,\n collectionType,\n } = useParams<{\n slug: UID.ContentType;\n id: string;\n collectionType: string;\n }>();\n const [{ query }] = useQueryParams<{\n plugins?: Record<string, unknown>;\n status?: string;\n }>();\n\n const params = React.useMemo(() => buildValidParams(query), [query]);\n\n if (!collectionType) {\n throw new Error('Could not find collectionType in url params');\n }\n\n if (!model) {\n throw new Error('Could not find model in url params');\n }\n\n // Only collection types must have a documentId\n if (collectionType === COLLECTION_TYPES && !documentId) {\n throw new Error('Could not find documentId in url params');\n }\n\n const previewUrlResponse = useGetPreviewUrlQuery({\n params: {\n contentType: model,\n },\n query: {\n documentId,\n locale: params.locale,\n status: params.status as GetPreviewUrl.Request['query']['status'],\n },\n });\n const documentResponse = useDocument({\n model,\n collectionType,\n documentId,\n params,\n });\n const documentLayoutResponse = useDocumentLayout(model);\n\n const isLoading =\n previewUrlResponse.isLoading || documentLayoutResponse.isLoading || documentResponse.isLoading;\n if (isLoading && !documentResponse.document?.documentId) {\n return <Page.Loading />;\n }\n\n const initialValues = documentResponse.getInitialFormValues();\n\n if (\n previewUrlResponse.error ||\n documentLayoutResponse.error ||\n !documentResponse.document ||\n !documentResponse.meta ||\n !documentResponse.schema ||\n !initialValues\n ) {\n return <Page.Error />;\n }\n\n if (!previewUrlResponse.data?.data?.url) {\n return <Page.NoData />;\n }\n\n const documentTitle = documentResponse.getTitle(documentLayoutResponse.edit.settings.mainField);\n\n const validateSync = (values: Record<string, unknown>, options: Record<string, string>) => {\n const yupSchema = createYupSchema(\n documentResponse.schema?.attributes,\n documentResponse.components,\n {\n status: documentResponse.document?.status,\n ...options,\n }\n );\n\n return yupSchema.validateSync(values, { abortEarly: false });\n };\n\n const previewUrl = previewUrlResponse.data.data.url;\n\n const onLine truncated
@@ -0,0 +1,39 @@
'use strict';
var React = require('react');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
const ProtectedPreviewPage = /*#__PURE__*/ React__namespace.lazy(()=>Promise.resolve().then(function () { return require('./pages/Preview.js'); }).then((mod)=>({
default: mod.ProtectedPreviewPage
})));
const routes = [
{
path: ':collectionType/:slug/:id/preview',
Component: ProtectedPreviewPage
},
{
path: ':collectionType/:slug/preview',
Component: ProtectedPreviewPage
}
];
exports.routes = routes;
//# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
{"version":3,"file":"routes.js","sources":["../../../admin/src/preview/routes.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport * as React from 'react';\n\nimport type { PathRouteProps } from 'react-router-dom';\n\nconst ProtectedPreviewPage = React.lazy(() =>\n import('./pages/Preview').then((mod) => ({ default: mod.ProtectedPreviewPage }))\n);\n\nconst routes: PathRouteProps[] = [\n {\n path: ':collectionType/:slug/:id/preview',\n Component: ProtectedPreviewPage,\n },\n {\n path: ':collectionType/:slug/preview',\n Component: ProtectedPreviewPage,\n },\n];\n\nexport { routes };\n"],"names":["ProtectedPreviewPage","React","lazy","then","mod","default","routes","path","Component"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAKA,MAAMA,oBAAuBC,iBAAAA,gBAAAA,CAAMC,IAAI,CAAC,IACtC,oDAAO,oBAAA,KAAA,CAAmBC,IAAI,CAAC,CAACC,GAAAA,IAAS;AAAEC,YAAAA,OAAAA,EAASD,IAAIJ;SAAqB,CAAA,CAAA,CAAA;AAG/E,MAAMM,MAA2B,GAAA;AAC/B,IAAA;QACEC,IAAM,EAAA,mCAAA;QACNC,SAAWR,EAAAA;AACb,KAAA;AACA,IAAA;QACEO,IAAM,EAAA,+BAAA;QACNC,SAAWR,EAAAA;AACb;AACD;;;;"}
@@ -0,0 +1,18 @@
import * as React from 'react';
const ProtectedPreviewPage = /*#__PURE__*/ React.lazy(()=>import('./pages/Preview.mjs').then((mod)=>({
default: mod.ProtectedPreviewPage
})));
const routes = [
{
path: ':collectionType/:slug/:id/preview',
Component: ProtectedPreviewPage
},
{
path: ':collectionType/:slug/preview',
Component: ProtectedPreviewPage
}
];
export { routes };
//# sourceMappingURL=routes.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"routes.mjs","sources":["../../../admin/src/preview/routes.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport * as React from 'react';\n\nimport type { PathRouteProps } from 'react-router-dom';\n\nconst ProtectedPreviewPage = React.lazy(() =>\n import('./pages/Preview').then((mod) => ({ default: mod.ProtectedPreviewPage }))\n);\n\nconst routes: PathRouteProps[] = [\n {\n path: ':collectionType/:slug/:id/preview',\n Component: ProtectedPreviewPage,\n },\n {\n path: ':collectionType/:slug/preview',\n Component: ProtectedPreviewPage,\n },\n];\n\nexport { routes };\n"],"names":["ProtectedPreviewPage","React","lazy","then","mod","default","routes","path","Component"],"mappings":";;AAKA,MAAMA,oBAAuBC,iBAAAA,KAAAA,CAAMC,IAAI,CAAC,IACtC,OAAO,qBAAA,CAAA,CAAmBC,IAAI,CAAC,CAACC,GAAAA,IAAS;AAAEC,YAAAA,OAAAA,EAASD,IAAIJ;SAAqB,CAAA,CAAA,CAAA;AAG/E,MAAMM,MAA2B,GAAA;AAC/B,IAAA;QACEC,IAAM,EAAA,mCAAA;QACNC,SAAWR,EAAAA;AACb,KAAA;AACA,IAAA;QACEO,IAAM,EAAA,+BAAA;QACNC,SAAWR,EAAAA;AACb;AACD;;;;"}
@@ -0,0 +1,23 @@
'use strict';
var api = require('../../services/api.js');
const previewApi = api.contentManagerApi.injectEndpoints({
endpoints: (builder)=>({
getPreviewUrl: builder.query({
query ({ query, params }) {
return {
url: `/content-manager/preview/url/${params.contentType}`,
method: 'GET',
config: {
params: query
}
};
}
})
})
});
const { useGetPreviewUrlQuery } = previewApi;
exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
//# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
{"version":3,"file":"preview.js","sources":["../../../../admin/src/preview/services/preview.ts"],"sourcesContent":["import { GetPreviewUrl } from '../../../../shared/contracts/preview';\nimport { contentManagerApi } from '../../services/api';\n\nconst previewApi = contentManagerApi.injectEndpoints({\n endpoints: (builder) => ({\n getPreviewUrl: builder.query<GetPreviewUrl.Response, GetPreviewUrl.Request>({\n query({ query, params }) {\n return {\n url: `/content-manager/preview/url/${params.contentType}`,\n method: 'GET',\n config: {\n params: query,\n },\n };\n },\n }),\n }),\n});\n\nconst { useGetPreviewUrlQuery } = previewApi;\n\nexport { useGetPreviewUrlQuery };\n"],"names":["previewApi","contentManagerApi","injectEndpoints","endpoints","builder","getPreviewUrl","query","params","url","contentType","method","config","useGetPreviewUrlQuery"],"mappings":";;;;AAGA,MAAMA,UAAAA,GAAaC,qBAAkBC,CAAAA,eAAe,CAAC;IACnDC,SAAW,EAAA,CAACC,WAAa;YACvBC,aAAeD,EAAAA,OAAAA,CAAQE,KAAK,CAAgD;AAC1EA,gBAAAA,KAAAA,CAAAA,CAAM,EAAEA,KAAK,EAAEC,MAAM,EAAE,EAAA;oBACrB,OAAO;AACLC,wBAAAA,GAAAA,EAAK,CAAC,6BAA6B,EAAED,MAAOE,CAAAA,WAAW,CAAC,CAAC;wBACzDC,MAAQ,EAAA,KAAA;wBACRC,MAAQ,EAAA;4BACNJ,MAAQD,EAAAA;AACV;AACF,qBAAA;AACF;AACF,aAAA;SACF;AACF,CAAA,CAAA;AAEM,MAAA,EAAEM,qBAAqB,EAAE,GAAGZ;;;;"}
@@ -0,0 +1,21 @@
import { contentManagerApi } from '../../services/api.mjs';
const previewApi = contentManagerApi.injectEndpoints({
endpoints: (builder)=>({
getPreviewUrl: builder.query({
query ({ query, params }) {
return {
url: `/content-manager/preview/url/${params.contentType}`,
method: 'GET',
config: {
params: query
}
};
}
})
})
});
const { useGetPreviewUrlQuery } = previewApi;
export { useGetPreviewUrlQuery };
//# sourceMappingURL=preview.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"preview.mjs","sources":["../../../../admin/src/preview/services/preview.ts"],"sourcesContent":["import { GetPreviewUrl } from '../../../../shared/contracts/preview';\nimport { contentManagerApi } from '../../services/api';\n\nconst previewApi = contentManagerApi.injectEndpoints({\n endpoints: (builder) => ({\n getPreviewUrl: builder.query<GetPreviewUrl.Response, GetPreviewUrl.Request>({\n query({ query, params }) {\n return {\n url: `/content-manager/preview/url/${params.contentType}`,\n method: 'GET',\n config: {\n params: query,\n },\n };\n },\n }),\n }),\n});\n\nconst { useGetPreviewUrlQuery } = previewApi;\n\nexport { useGetPreviewUrlQuery };\n"],"names":["previewApi","contentManagerApi","injectEndpoints","endpoints","builder","getPreviewUrl","query","params","url","contentType","method","config","useGetPreviewUrlQuery"],"mappings":";;AAGA,MAAMA,UAAAA,GAAaC,iBAAkBC,CAAAA,eAAe,CAAC;IACnDC,SAAW,EAAA,CAACC,WAAa;YACvBC,aAAeD,EAAAA,OAAAA,CAAQE,KAAK,CAAgD;AAC1EA,gBAAAA,KAAAA,CAAAA,CAAM,EAAEA,KAAK,EAAEC,MAAM,EAAE,EAAA;oBACrB,OAAO;AACLC,wBAAAA,GAAAA,EAAK,CAAC,6BAA6B,EAAED,MAAOE,CAAAA,WAAW,CAAC,CAAC;wBACzDC,MAAQ,EAAA,KAAA;wBACRC,MAAQ,EAAA;4BACNJ,MAAQD,EAAAA;AACV;AACF,qBAAA;AACF;AACF,aAAA;SACF;AACF,CAAA,CAAA;AAEM,MAAA,EAAEM,qBAAqB,EAAE,GAAGZ;;;;"}