chore(preview): prepare layout for side editor (#22767)

This commit is contained in:
markkaylor 2025-01-31 12:30:31 +01:00 committed by GitHub
parent d6a56e1783
commit 88f5d2bfb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 120 additions and 11 deletions

View File

@ -1 +1,5 @@
module.exports = ({ env }) => ({});
module.exports = ({ env }) => ({
future: {
unstablePreviewSideEditor: true,
},
});

View File

@ -1,10 +1,41 @@
import * as React from 'react';
import { Box } from '@strapi/design-system';
import { Box, Flex } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { usePreviewContext } from '../pages/Preview';
const UnstablePreviewContent = () => {
const previewUrl = usePreviewContext('PreviewContent', (state) => state.url);
const { formatMessage } = useIntl();
return (
<Flex height="100%">
<Box flex={1}>TODO: Side editor</Box>
<Box
src={previewUrl}
/**
* For some reason, changing an iframe's src tag causes the browser to add a new item in the
* history stack. This is an issue for us as it means clicking the back button will not let us
* go back to the edit view. To fix it, we need to trick the browser into thinking this is a
* different iframe when the preview URL changes. So we set a key prop to force React
* to mount a different node when the src changes.
*/
key={previewUrl}
title={formatMessage({
id: 'content-manager.preview.panel.title',
defaultMessage: 'Preview',
})}
flex={1}
height="100%"
borderWidth={0}
tag="iframe"
/>
</Flex>
);
};
const PreviewContent = () => {
const previewUrl = usePreviewContext('PreviewContent', (state) => state.url);
@ -33,4 +64,4 @@ const PreviewContent = () => {
);
};
export { PreviewContent };
export { PreviewContent, UnstablePreviewContent };

View File

@ -6,7 +6,7 @@ import {
useNotification,
useQueryParams,
} from '@strapi/admin/strapi-admin';
import { IconButton, Tabs, Typography, Grid } from '@strapi/design-system';
import { IconButton, Tabs, Typography, Grid, Flex } from '@strapi/design-system';
import { Cross, Link as LinkIcon } from '@strapi/icons';
import { stringify } from 'qs';
import { useIntl } from 'react-intl';
@ -57,6 +57,7 @@ const ClosePreviewButton = () => {
return (
<IconButton
variant="ghost"
tag={Link}
relative="path"
to={toWithFallback}
@ -145,6 +146,62 @@ const PreviewTabs = () => {
* PreviewHeader
* -----------------------------------------------------------------------------------------------*/
const UnstablePreviewHeader = () => {
// Get the document title
const title = usePreviewContext('PreviewHeader', (state) => state.title);
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 (
<Flex gap={4} background="neutral0" borderColor="neutral150" tag="header">
{/* Title and status */}
<TitleContainer height="100%" paddingLeft={2} paddingRight={4}>
<ClosePreviewButton />
<PreviewTitle
tag="h1"
title={title}
maxWidth="200px"
fontSize={2}
paddingLeft={2}
paddingRight={3}
fontWeight={600}
>
{title}
</PreviewTitle>
<Status />
</TitleContainer>
{/* Tabs and actions */}
<Flex flex={1} paddingRight={2} justifyContent="space-between">
<PreviewTabs />
<IconButton
type="button"
label={formatMessage({
id: 'preview.copy.label',
defaultMessage: 'Copy preview link',
})}
onClick={handleCopyLink}
>
<LinkIcon />
</IconButton>
</Flex>
</Flex>
);
};
const PreviewHeader = () => {
// Get the document title
const title = usePreviewContext('PreviewHeader', (state) => state.title);
@ -213,4 +270,8 @@ const StatusTab = styled(Tabs.Trigger)`
text-transform: uppercase;
`;
export { PreviewHeader };
const TitleContainer = styled(Flex)`
border-right: 1px solid ${({ theme }) => theme.colors.neutral150};
`;
export { PreviewHeader, UnstablePreviewHeader };

View File

@ -11,8 +11,8 @@ import { DocumentRBAC } from '../../features/DocumentRBAC';
import { type UseDocument, useDocument } from '../../hooks/useDocument';
import { useDocumentLayout } from '../../hooks/useDocumentLayout';
import { buildValidParams } from '../../utils/api';
import { PreviewContent } from '../components/PreviewContent';
import { PreviewHeader } from '../components/PreviewHeader';
import { PreviewContent, UnstablePreviewContent } from '../components/PreviewContent';
import { PreviewHeader, UnstablePreviewHeader } from '../components/PreviewHeader';
import { useGetPreviewUrlQuery } from '../services/preview';
import type { UID } from '@strapi/types';
@ -132,8 +132,17 @@ const PreviewPage = () => {
schema={documentResponse.schema}
>
<Flex direction="column" height="100%" alignItems="stretch">
<PreviewHeader />
<PreviewContent />
{window.strapi.future.isEnabled('unstablePreviewSideEditor') ? (
<>
<UnstablePreviewHeader />
<UnstablePreviewContent />
</>
) : (
<>
<PreviewHeader />
<PreviewContent />
</>
)}
</Flex>
</PreviewProvider>
</>

View File

@ -1,5 +1,7 @@
export interface FeaturesConfig {
future?: object;
future?: {
unstablePreviewSideEditor?: boolean;
};
}
export interface FeaturesService {

View File

@ -1,3 +1,5 @@
module.exports = ({ env }) => ({
future: {},
future: {
unstablePreviewSideEditor: env.bool('STRAPI_FEATURES_UNSTABLE_PREVIEW_SIDE_EDITOR', false),
},
});