fix: onPreview is not called when updating a relation (#23122)

This commit is contained in:
markkaylor 2025-03-12 13:22:52 +01:00 committed by GitHub
parent 5fe0fbb87f
commit 664f08e085
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 40 additions and 28 deletions

View File

@ -11,7 +11,11 @@ const PreviewComponent = () => {
const { document, refetch } = useDocument({
model,
documentId,
params: { locale, status },
params: {
locale,
status,
populate: '*',
},
collectionType,
});

View File

@ -35,6 +35,7 @@ interface DocumentContextValue {
changeDocument: (newRelation: DocumentMeta) => void;
documentHistory: DocumentMeta[];
setDocumentHistory: React.Dispatch<React.SetStateAction<DocumentMeta[]>>;
onPreview?: () => void;
}
const [DocumentProvider, useDocumentContext] =
@ -55,9 +56,11 @@ const [DocumentProvider, useDocumentContext] =
const DocumentContextProvider = ({
children,
initialDocument,
onPreview,
}: {
children: React.ReactNode | React.ReactNode[];
initialDocument: DocumentMeta;
onPreview?: () => void;
}) => {
/**
* Initialize with the "root" document and expose a setter method to change to
@ -84,6 +87,7 @@ const DocumentContextProvider = ({
meta={currentDocumentMeta}
documentHistory={documentHistory}
setDocumentHistory={setDocumentHistory}
onPreview={onPreview}
>
{children}
</DocumentProvider>

View File

@ -70,23 +70,23 @@ const [RelationModalProvider, useRelationModal] = createContext<RelationModalCon
}
);
const RelationModalWrapper = ({ relation, triggerButtonLabel }: RelationModalProps) => {
const RelationModalForm = ({ relation, triggerButtonLabel }: RelationModalProps) => {
const navigate = useNavigate();
const { pathname, search } = useLocation();
const { formatMessage } = useIntl();
const [triggerRefetchDocument] = useLazyGetDocumentQuery();
const currentDocument = useDocumentContext('RelationModalBody', (state) => state.document);
const currentDocument = useDocumentContext('RelationModalForm', (state) => state.document);
const rootDocumentMeta = useDocumentContext(
'RelationModalBody',
'RelationModalForm',
(state) => state.rootDocumentMeta
);
const currentDocumentMeta = useDocumentContext('RelationModalBody', (state) => state.meta);
const changeDocument = useDocumentContext('RelationModalBody', (state) => state.changeDocument);
const documentHistory = useDocumentContext('RelationModalBody', (state) => state.documentHistory);
const currentDocumentMeta = useDocumentContext('RelationModalForm', (state) => state.meta);
const changeDocument = useDocumentContext('RelationModalForm', (state) => state.changeDocument);
const documentHistory = useDocumentContext('RelationModalForm', (state) => state.documentHistory);
const setDocumentHistory = useDocumentContext(
'RelationModalBody',
'RelationModalForm',
(state) => state.setDocumentHistory
);
@ -98,7 +98,7 @@ const RelationModalWrapper = ({ relation, triggerButtonLabel }: RelationModalPro
const [isModalOpen, setIsModalOpen] = React.useState(false);
// NOTE: Not sure about this relation modal context, maybe we should move this to DocumentContext?
// Get parent modal context if it exists
const parentContext = useRelationModal('RelationModalWrapper', (state) => state);
const parentContext = useRelationModal('RelationModalForm', (state) => state);
// Get depth of nested modals
const depth = parentContext ? parentContext.depth + 1 : 0;
// Check if this is a nested modal
@ -361,6 +361,7 @@ const RelationModalBody = ({ children }: RelationModalBodyProps) => {
const documentMeta = useDocumentContext('RelationModalBody', (state) => state.meta);
const documentResponse = useDocumentContext('RelationModalBody', (state) => state.document);
const onPreview = useDocumentContext('RelationModalBody', (state) => state.onPreview);
const documentLayoutResponse = useDocumentLayout(documentMeta.model);
const plugins = useStrapiApp('RelationModalBody', (state) => state.plugins);
@ -422,6 +423,7 @@ const RelationModalBody = ({ children }: RelationModalBodyProps) => {
documentId: documentMeta.documentId,
document: documentResponse.document,
meta: documentResponse.meta,
onPreview,
} satisfies DocumentActionProps;
return (
@ -498,4 +500,4 @@ const RelationModalBody = ({ children }: RelationModalBodyProps) => {
);
};
export { RelationModalWrapper };
export { RelationModalForm };

View File

@ -52,7 +52,7 @@ import { getRelationLabel } from '../../../../../utils/relations';
import { getTranslation } from '../../../../../utils/translations';
import { DocumentStatus } from '../../DocumentStatus';
import { useComponent } from '../ComponentContext';
import { RelationModalWrapper, getCollectionType } from '../Relations/RelationModal';
import { RelationModalForm, getCollectionType } from '../Relations/RelationModal';
import type { Schema } from '@strapi/types';
@ -1065,7 +1065,7 @@ const ListItem = ({ data, index, style }: ListItemProps) => {
) : null}
<Flex width="100%" minWidth={0} justifyContent="space-between">
<Box minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
<RelationModalWrapper
<RelationModalForm
triggerButtonLabel={label}
relation={{
documentId: documentId ?? apiData?.documentId,

View File

@ -2,7 +2,7 @@ import { render, screen, fireEvent } from '@tests/utils';
import { useNavigate } from 'react-router-dom';
import { DocumentContextProvider } from '../../../../../../features/DocumentContext';
import { RelationModalWrapper } from '../RelationModal';
import { RelationModalForm } from '../RelationModal';
const relationContext = {
initialDocument: {
@ -217,7 +217,7 @@ describe('<RelationModal />', () => {
it('renders the trigger button correctly', () => {
render(
<DocumentContextProvider {...relationContext}>
<RelationModalWrapper triggerButtonLabel="Open Modal" relation={relation} />
<RelationModalForm triggerButtonLabel="Open Modal" relation={relation} />
</DocumentContextProvider>
);
@ -227,7 +227,7 @@ describe('<RelationModal />', () => {
it('does not render the modal by default', () => {
render(
<DocumentContextProvider {...relationContext}>
<RelationModalWrapper triggerButtonLabel="Open Modal" relation={relation} />
<RelationModalForm triggerButtonLabel="Open Modal" relation={relation} />
</DocumentContextProvider>
);
@ -237,7 +237,7 @@ describe('<RelationModal />', () => {
it('opens the modal when clicking the trigger button', () => {
render(
<DocumentContextProvider {...relationContext}>
<RelationModalWrapper triggerButtonLabel="Open Modal" relation={relation} />
<RelationModalForm triggerButtonLabel="Open Modal" relation={relation} />
</DocumentContextProvider>
);
@ -259,7 +259,7 @@ describe('<RelationModal />', () => {
it('closes the modal when clicking the cancel button', () => {
render(
<DocumentContextProvider {...relationContext}>
<RelationModalWrapper triggerButtonLabel="Open Modal" relation={relation} />
<RelationModalForm triggerButtonLabel="Open Modal" relation={relation} />
</DocumentContextProvider>
);
@ -277,7 +277,7 @@ describe('<RelationModal />', () => {
it('navigates to full page when "Go to entry" is clicked', () => {
render(
<DocumentContextProvider {...relationContext}>
<RelationModalWrapper triggerButtonLabel="Open Modal" relation={relation} />
<RelationModalForm triggerButtonLabel="Open Modal" relation={relation} />
</DocumentContextProvider>
);

View File

@ -16,6 +16,7 @@ import { Link, type To } from 'react-router-dom';
import { styled } from 'styled-components';
import { InjectionZone } from '../../components/InjectionZone';
import { useDocumentContext } from '../../features/DocumentContext';
import { DocumentActionButton } from '../../pages/EditView/components/DocumentActions';
import { DocumentStatus } from '../../pages/EditView/components/DocumentStatus';
import { getDocumentStatus } from '../../pages/EditView/EditViewPage';
@ -156,7 +157,7 @@ const UnstablePreviewHeader = () => {
const schema = usePreviewContext('PreviewHeader', (state) => state.schema);
const meta = usePreviewContext('PreviewHeader', (state) => state.meta);
const plugins = useStrapiApp('PreviewHeader', (state) => state.plugins);
const iframeRef = usePreviewContext('PreviewHeader', (state) => state.iframeRef);
const onPreview = useDocumentContext('PreviewHeader', (state) => state.onPreview);
const [{ query }] = useQueryParams<{
status?: 'draft' | 'published';
@ -184,13 +185,7 @@ const UnstablePreviewHeader = () => {
documentId: document.documentId,
document,
meta,
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
);
},
onPreview,
} satisfies DocumentActionProps;
return (

View File

@ -40,7 +40,6 @@ interface PreviewContextValue {
meta: NonNullable<ReturnType<UseDocument>['meta']>;
schema: NonNullable<ReturnType<UseDocument>['schema']>;
layout: EditLayout;
iframeRef?: React.RefObject<HTMLIFrameElement>;
}
const [PreviewProvider, usePreviewContext] = createContext<PreviewContextValue>('PreviewPage');
@ -150,6 +149,14 @@ const PreviewPage = () => {
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
);
};
return (
<>
<Page.Title>
@ -169,6 +176,7 @@ const PreviewPage = () => {
model,
collectionType,
}}
onPreview={onPreview}
>
<PreviewProvider
url={previewUrl}
@ -177,7 +185,6 @@ const PreviewPage = () => {
meta={documentResponse.meta}
schema={documentResponse.schema}
layout={documentLayoutResponse.edit}
iframeRef={iframeRef}
>
<FormContext
method="PUT"