mirror of
https://github.com/strapi/strapi.git
synced 2025-09-27 09:25:46 +00:00
enhancement: promote preview configuration docs (#23961)
* enhancement: promote preview configuration docs * chore: add tests * fix: api test * fix: don't show panel in create mode
This commit is contained in:
parent
5aa166b6d1
commit
39b256a9a2
@ -31,22 +31,59 @@ const PreviewSidePanel: PanelComponent = ({ model, documentId, document }) => {
|
|||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
const [{ query }] = useQueryParams();
|
const [{ query }] = useQueryParams();
|
||||||
const isModified = useForm('PreviewSidePanel', (state) => state.modified);
|
const isModified = useForm('PreviewSidePanel', (state) => state.modified);
|
||||||
|
const isUnsaved = Boolean(!document || !document.id);
|
||||||
|
|
||||||
|
const title = formatMessage({
|
||||||
|
id: 'content-manager.preview.panel.title',
|
||||||
|
defaultMessage: 'Preview',
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The preview URL isn't used in this component, we just fetch it to know if preview is enabled
|
* 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
|
* 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.
|
* /preview, and the URL will already be loaded in the RTK query cache.
|
||||||
*/
|
*/
|
||||||
const { data, error } = useGetPreviewUrlQuery({
|
const { data, error } = useGetPreviewUrlQuery(
|
||||||
params: {
|
{
|
||||||
contentType: model as UID.ContentType,
|
params: {
|
||||||
|
contentType: model as UID.ContentType,
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
documentId,
|
||||||
|
locale: document?.locale,
|
||||||
|
status: document?.status,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
query: {
|
// Don't bother making the request since we won't show any UI
|
||||||
documentId,
|
{ skip: isUnsaved }
|
||||||
locale: document?.locale,
|
);
|
||||||
status: document?.status,
|
|
||||||
},
|
if (isUnsaved) {
|
||||||
});
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview was not configured but not disabled either (otherwise it would be a success 204).
|
||||||
|
// So we encourage the user to set it up.
|
||||||
|
if (error && error.name === 'NotFoundError') {
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
content: (
|
||||||
|
<Button
|
||||||
|
variant="tertiary"
|
||||||
|
tag={Link}
|
||||||
|
to="https://docs.strapi.io/cms/features/preview"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
width="100%"
|
||||||
|
>
|
||||||
|
{formatMessage({
|
||||||
|
id: 'content-manager.preview.panel.button-configuration',
|
||||||
|
defaultMessage: 'Set up preview',
|
||||||
|
})}
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (!data?.data?.url || error) {
|
if (!data?.data?.url || error) {
|
||||||
return null;
|
return null;
|
||||||
@ -59,7 +96,7 @@ const PreviewSidePanel: PanelComponent = ({ model, documentId, document }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: formatMessage({ id: 'content-manager.preview.panel.title', defaultMessage: 'Preview' }),
|
title,
|
||||||
content: (
|
content: (
|
||||||
<ConditionalTooltip
|
<ConditionalTooltip
|
||||||
label={formatMessage({
|
label={formatMessage({
|
||||||
|
@ -241,6 +241,7 @@
|
|||||||
"popover.display-relations.label": "Display relations",
|
"popover.display-relations.label": "Display relations",
|
||||||
"preview.panel.title": "Preview",
|
"preview.panel.title": "Preview",
|
||||||
"preview.panel.button": "Open preview",
|
"preview.panel.button": "Open preview",
|
||||||
|
"preview.panel.button-configuration": "Set up preview",
|
||||||
"preview.panel.button-disabled-tooltip": "Please save to open the preview",
|
"preview.panel.button-disabled-tooltip": "Please save to open the preview",
|
||||||
"preview.page-title": "{contentType} preview",
|
"preview.page-title": "{contentType} preview",
|
||||||
"preview.header.close": "Close preview",
|
"preview.header.close": "Close preview",
|
||||||
|
@ -30,7 +30,49 @@ describe('Preview Config', () => {
|
|||||||
expect(createPreviewConfigService({ strapi }).isEnabled()).toBe(true);
|
expect(createPreviewConfigService({ strapi }).isEnabled()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Validation', () => {
|
describe('isConfigured', () => {
|
||||||
|
test('Is configured when preview is explicitly disabled', () => {
|
||||||
|
const strapi = {
|
||||||
|
config: {
|
||||||
|
get: () => ({ enabled: false }),
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
expect(createPreviewConfigService({ strapi }).isConfigured()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Is configured when handler is configured', () => {
|
||||||
|
const strapi = {
|
||||||
|
config: {
|
||||||
|
get: () => getConfig(true, () => {}),
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
expect(createPreviewConfigService({ strapi }).isConfigured()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Is not configured when preview is neither disabled nor configured', () => {
|
||||||
|
const strapi = {
|
||||||
|
config: {
|
||||||
|
get: () => ({ enabled: true }),
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
expect(createPreviewConfigService({ strapi }).isConfigured()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Is not configured when no config is provided', () => {
|
||||||
|
const strapi = {
|
||||||
|
config: {
|
||||||
|
get: () => undefined,
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
expect(createPreviewConfigService({ strapi }).isConfigured()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validate', () => {
|
||||||
test('Passes on valid configuration', () => {
|
test('Passes on valid configuration', () => {
|
||||||
const strapi = {
|
const strapi = {
|
||||||
config: {
|
config: {
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
import { errors } from '@strapi/utils';
|
||||||
|
import { createPreviewService } from '../preview';
|
||||||
|
|
||||||
|
const mockConfig = {
|
||||||
|
isConfigured: jest.fn(),
|
||||||
|
getPreviewHandler: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockStrapi = {
|
||||||
|
log: {
|
||||||
|
error: jest.fn(),
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
const mockGetService = jest.fn().mockReturnValue(mockConfig);
|
||||||
|
|
||||||
|
jest.mock('../../utils', () => ({
|
||||||
|
getService: jest.fn().mockImplementation(() => mockGetService()),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('Preview Service', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Throws 404 when preview is not configured', async () => {
|
||||||
|
mockConfig.isConfigured.mockReturnValue(false);
|
||||||
|
|
||||||
|
const previewService = createPreviewService({ strapi: mockStrapi });
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
previewService.getPreviewUrl('api::article.article', {
|
||||||
|
documentId: '',
|
||||||
|
locale: '',
|
||||||
|
status: 'published',
|
||||||
|
})
|
||||||
|
).rejects.toThrow(new errors.NotFoundError('Preview config not found'));
|
||||||
|
|
||||||
|
expect(mockConfig.isConfigured).toHaveBeenCalled();
|
||||||
|
expect(mockConfig.getPreviewHandler).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Calls handler when preview is configured', async () => {
|
||||||
|
const mockHandler = jest.fn().mockResolvedValue('http://preview.example.com');
|
||||||
|
mockConfig.isConfigured.mockReturnValue(true);
|
||||||
|
mockConfig.getPreviewHandler.mockReturnValue(mockHandler);
|
||||||
|
|
||||||
|
const previewService = createPreviewService({ strapi: mockStrapi });
|
||||||
|
const params = { documentId: '1', locale: 'en', status: 'published' as const };
|
||||||
|
|
||||||
|
const result = await previewService.getPreviewUrl('api::article.article', params);
|
||||||
|
|
||||||
|
expect(result).toBe('http://preview.example.com');
|
||||||
|
expect(mockConfig.isConfigured).toHaveBeenCalled();
|
||||||
|
expect(mockConfig.getPreviewHandler).toHaveBeenCalled();
|
||||||
|
expect(mockHandler).toHaveBeenCalledWith('api::article.article', params);
|
||||||
|
});
|
||||||
|
});
|
@ -81,6 +81,11 @@ const createPreviewConfigService = ({ strapi }: { strapi: Core.Strapi }) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isConfigured() {
|
||||||
|
const config = strapi.config.get('admin.preview') as PreviewConfig;
|
||||||
|
return config?.enabled === false || config?.config?.handler != null;
|
||||||
|
},
|
||||||
|
|
||||||
isEnabled() {
|
isEnabled() {
|
||||||
const config = strapi.config.get('admin.preview') as PreviewConfig;
|
const config = strapi.config.get('admin.preview') as PreviewConfig;
|
||||||
|
|
||||||
@ -113,8 +118,6 @@ const createPreviewConfigService = ({ strapi }: { strapi: Core.Strapi }) => {
|
|||||||
* Utility to get the preview handler from the configuration
|
* Utility to get the preview handler from the configuration
|
||||||
*/
|
*/
|
||||||
getPreviewHandler(): PreviewConfig['config']['handler'] {
|
getPreviewHandler(): PreviewConfig['config']['handler'] {
|
||||||
const config = strapi.config.get('admin.preview') as PreviewConfig;
|
|
||||||
|
|
||||||
const emptyHandler = () => {
|
const emptyHandler = () => {
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
@ -123,6 +126,8 @@ const createPreviewConfigService = ({ strapi }: { strapi: Core.Strapi }) => {
|
|||||||
return emptyHandler;
|
return emptyHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const config = strapi.config.get('admin.preview') as PreviewConfig;
|
||||||
|
|
||||||
return config?.config?.handler || emptyHandler;
|
return config?.config?.handler || emptyHandler;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -12,6 +12,12 @@ const createPreviewService = ({ strapi }: { strapi: Core.Strapi }) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
async getPreviewUrl(uid: UID.ContentType, params: HandlerParams) {
|
async getPreviewUrl(uid: UID.ContentType, params: HandlerParams) {
|
||||||
|
const isConfigured = config.isConfigured();
|
||||||
|
|
||||||
|
if (!isConfigured) {
|
||||||
|
throw new errors.NotFoundError('Preview config not found');
|
||||||
|
}
|
||||||
|
|
||||||
const handler = config.getPreviewHandler();
|
const handler = config.getPreviewHandler();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user