Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/cmsui/acceptance/tests/content-types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,8 @@ test.describe('A content type, on a backend with @content-types', () => {
await openNewType(page, 'settings');

await page.getByText('Show in search results', { exact: true }).click();
// New types aren't in the navigation.
await page.getByText('Show in navigation', { exact: true }).click();
await page
.getByRole('radiogroup', { name: 'Versioning' })
.getByText('Automatic', { exact: true })
Expand All @@ -518,6 +520,9 @@ test.describe('A content type, on a backend with @content-types', () => {
await expect(
page.getByRole('switch', { name: 'Show in search results' }),
).not.toBeChecked();
await expect(
page.getByRole('switch', { name: 'Show in navigation' }),
).toBeChecked();
await expect(page.getByRole('radio', { name: /^Automatic/ })).toBeChecked();
});

Expand Down
1 change: 1 addition & 0 deletions packages/controlpanels/news/+restapi-review.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Follow the reviewed plone.restapi content types API (plone/plone.restapi#2070, #2090): a type's number of items is `content_count`, the Settings tab has "Show in navigation" instead of "Can be used as a folder's default page", and the Workflow tab says when a type's chain has other workflows, which changing the workflow replaces. The capability and settings field `defaultPage` is now `inNavigation`. @sneridagh
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export function SettingsTab({ type, types }: SettingsTabProps) {
const missing =
!capabilities.globalAllow ||
!capabilities.searchable ||
!capabilities.defaultPage ||
!capabilities.inNavigation ||
!capabilities.allowDiscussion ||
!capabilities.versioning;

Expand All @@ -203,7 +203,7 @@ export function SettingsTab({ type, types }: SettingsTabProps) {
</Section>
)}
{type.folderish && <ContentsSection types={types} />}
{(capabilities.searchable || capabilities.defaultPage) && (
{(capabilities.searchable || capabilities.inNavigation) && (
<Section title={t(messages.visibility)}>
{capabilities.searchable && (
<SettingSwitch
Expand All @@ -212,11 +212,11 @@ export function SettingsTab({ type, types }: SettingsTabProps) {
description={t(messages.searchableHelp)}
/>
)}
{capabilities.defaultPage && (
{capabilities.inNavigation && (
<SettingSwitch
path="defaultPage"
label={t(messages.defaultPage)}
description={t(messages.defaultPageHelp)}
path="inNavigation"
label={t(messages.inNavigation)}
description={t(messages.inNavigationHelp)}
/>
)}
</Section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ async function openAndChoose(name: RegExp) {
}

describe('WorkflowTab', () => {
it('mentions the other workflows of a chain', async () => {
const base = createMockDriver();
const driver = {
...base,
getType: async (id: string) => {
const type = await base.getType(id);
return {
...type,
workflow: {
workflow: 'simple_publication_workflow',
chain: ['simple_publication_workflow', 'intranet_workflow'],
followsDefault: false,
},
};
},
};
renderWorkflow(driver);
expect(
await screen.findByText(/Its chain also has Intranet/),
).toHaveTextContent('Changing the workflow replaces the whole chain.');
});

it('shows the states of the current workflow', async () => {
renderWorkflow();
const states = await screen.findByRole('list', { name: 'States' });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ export function WorkflowTab({
{workflow?.description && (
<p className="text-sm text-quanta-pigeon">{workflow.description}</p>
)}
{assignment.chain && assignment.chain.length > 1 && (
<p className="text-sm text-quanta-iron">
{t(messages.otherWorkflows, {
workflows: assignment.chain
.slice(1)
.map(
(id) =>
workflows.find((entry) => entry.id === id)?.title ?? id,
)
.join(', '),
})}
</p>
)}
{workflow ? (
<ul
aria-label={t(messages.workflowStates)}
Expand Down
4 changes: 2 additions & 2 deletions packages/controlpanels/src/content-types/driver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export interface ContentTypesCapabilities {
/** Read and change whether a type shows in search results. */
searchable: boolean;
/** Read and change whether a type can be a folder's default page. */
defaultPage: boolean;
inNavigation: boolean;
/** Read and change whether a type allows comments. */
allowDiscussion: boolean;
/** Read and change a type's versioning policy. */
Expand Down Expand Up @@ -110,7 +110,7 @@ export interface ContentTypesDriver {
export const NO_CAPABILITIES: ContentTypesCapabilities = {
globalAllow: false,
searchable: false,
defaultPage: false,
inNavigation: false,
allowDiscussion: false,
versioning: false,
behaviorOrder: false,
Expand Down
10 changes: 5 additions & 5 deletions packages/controlpanels/src/content-types/editableSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type EditableSettings = { schema?: TypeSchema } & Required<
| 'allowedContents'
| 'globalAllow'
| 'searchable'
| 'defaultPage'
| 'inNavigation'
| 'allowDiscussion'
| 'versioning'
>;
Expand All @@ -33,7 +33,7 @@ export const TAB_FIELDS: Partial<
'allowedContents',
'globalAllow',
'searchable',
'defaultPage',
'inNavigation',
'allowDiscussion',
'versioning',
],
Expand All @@ -53,7 +53,7 @@ export function toEditableSettings(
allowedContents,
globalAllow,
searchable,
defaultPage,
inNavigation,
allowDiscussion,
versioning,
} = settings;
Expand All @@ -64,7 +64,7 @@ export function toEditableSettings(
...(allowedContents && { allowedContents }),
...(globalAllow !== undefined && { globalAllow }),
...(searchable !== undefined && { searchable }),
...(defaultPage !== undefined && { defaultPage }),
...(inNavigation !== undefined && { inNavigation }),
...(allowDiscussion !== undefined && { allowDiscussion }),
...(versioning !== undefined && { versioning }),
...(schema && { schema }),
Expand Down Expand Up @@ -106,7 +106,7 @@ export const SETTING_CAPABILITIES: Partial<
> = {
globalAllow: 'globalAllow',
searchable: 'searchable',
defaultPage: 'defaultPage',
inNavigation: 'inNavigation',
allowDiscussion: 'allowDiscussion',
versioning: 'versioning',
};
18 changes: 11 additions & 7 deletions packages/controlpanels/src/content-types/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,14 +426,18 @@ export const messages = defineMessages({
defaultMessage:
'Turn off for helper types that should never appear in site search.',
},
defaultPage: {
id: 'controlpanels.contentTypes.defaultPage',
defaultMessage: "Can be used as a folder's default page",
},
defaultPageHelp: {
id: 'controlpanels.contentTypes.defaultPageHelp',
otherWorkflows: {
id: 'controlpanels.contentTypes.otherWorkflows',
defaultMessage:
'Lets editors pick an item of this type as the page a folder shows.',
'Its chain also has {{workflows}}. Changing the workflow replaces the whole chain.',
},
inNavigation: {
id: 'controlpanels.contentTypes.inNavigation',
defaultMessage: 'Show in navigation',
},
inNavigationHelp: {
id: 'controlpanels.contentTypes.inNavigationHelp',
defaultMessage: "Lists items of this type in the site's navigation.",
},
comments: {
id: 'controlpanels.contentTypes.comments',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function createMockDriver(
const capabilities: ContentTypesCapabilities = {
globalAllow: true,
searchable: true,
defaultPage: true,
inNavigation: true,
allowDiscussion: true,
versioning: true,
behaviorOrder: true,
Expand Down Expand Up @@ -134,7 +134,7 @@ export function createMockDriver(
const result: ContentTypeSettings = { ...type };
if (!capabilities.globalAllow) delete result.globalAllow;
if (!capabilities.searchable) delete result.searchable;
if (!capabilities.defaultPage) delete result.defaultPage;
if (!capabilities.inNavigation) delete result.inNavigation;
if (!capabilities.allowDiscussion) delete result.allowDiscussion;
if (!capabilities.versioning) delete result.versioning;
if (capabilities.workflows) result.workflow = assignment(type.id);
Expand Down Expand Up @@ -250,7 +250,7 @@ export function createMockDriver(
allowedContents: { mode: 'all' },
globalAllow: data.siteDefaults.globalAllow,
searchable: true,
defaultPage: false,
inNavigation: false,
allowDiscussion: false,
versioning: data.siteDefaults.versioning,
behaviors: ['plone.dublincore', 'plone.namefromtitle'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const settings = (
folderish: false,
globalAllow: true,
searchable: true,
defaultPage: false,
inNavigation: false,
allowDiscussion: false,
versioning: 'manual',
...type,
Expand All @@ -82,14 +82,14 @@ export const mockData: MockData = {
'plone.namefromtitle',
'plone.collection',
],
defaultPage: true,
inNavigation: true,
}),
settings({
id: 'Document',
title: 'Page',
folderish: true,
allowedContents: { mode: 'all' },
defaultPage: true,
inNavigation: true,
behaviors: PAGE_BEHAVIORS,
}),
settings({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ const event: ContentTypeResponse = {
'@id': 'http://localhost:55001/plone/@content-types/Event',
id: 'Event',
title: 'Event',
items_total: 3,
content_count: 3,
data: {
title: 'Event',
description: 'Events can be shown in calendars.',
global_allow: true,
allowed_content_types_mode: { token: 'selected', title: 'Selected types' },
allowed_content_types: [{ token: 'Image', title: 'Image' }],
searchable: true,
default_page: true,
in_navigation: true,
allow_discussion: false,
versioning: { token: 'automatic', title: 'Automatic' },
behaviors: [
Expand All @@ -38,7 +38,7 @@ const event: ContentTypeResponse = {
{ id: 'behaviors', fields: ['behaviors'] },
],
},
workflow: { id: 'simple_publication_workflow', follows_default: true },
workflow: { chain: ['simple_publication_workflow'], follows_default: true },
};

// Trimmed from `GET @workflows/simple_publication_workflow`.
Expand Down Expand Up @@ -113,7 +113,7 @@ describe('toSettings and toSummary', () => {
allowedContents: { mode: 'selected', types: ['Image'] },
globalAllow: true,
searchable: true,
defaultPage: true,
inNavigation: true,
allowDiscussion: false,
versioning: 'automatic',
behaviors: ['plone.eventbasic', 'plone.dublincore'],
Expand All @@ -129,6 +129,22 @@ describe('toSettings and toSummary', () => {
});
});

it('keeps the chain of a type with several workflows', () => {
const chain = ['simple_publication_workflow', 'comment_review_workflow'];
expect(
toSettings({ ...event, workflow: { chain, follows_default: false } })
.workflow,
).toEqual({
workflow: 'simple_publication_workflow',
chain,
followsDefault: false,
});
expect(
toSettings({ ...event, workflow: { chain: [], follows_default: false } })
.workflow,
).toEqual({ workflow: null, followsDefault: false });
});

it('tells the site and types without behaviors apart', () => {
expect(toSummary({ ...event, id: 'Plone Site' }).kind).toBe('site');
expect(
Expand All @@ -146,13 +162,13 @@ describe('toContentTypePatch', () => {
expect(
toContentTypePatch({
globalAllow: false,
defaultPage: true,
inNavigation: true,
allowedContents: { mode: 'selected', types: ['File'] },
behaviors: ['plone.dublincore'],
}),
).toEqual({
global_allow: false,
default_page: true,
in_navigation: true,
allowed_content_types_mode: 'selected',
allowed_content_types: ['File'],
behaviors: ['plone.dublincore'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function toCapabilities(
...(backend.contentTypes && {
globalAllow: true,
searchable: true,
defaultPage: true,
inNavigation: true,
allowDiscussion: true,
versioning: true,
copyType: true,
Expand All @@ -58,22 +58,24 @@ export interface ContentTypeResponse {
'@id': string;
id: string;
title: string;
items_total: number;
/** The number of items of the type. */
content_count: number;
data: {
title?: string;
description?: string;
global_allow?: boolean;
allowed_content_types_mode?: Term;
allowed_content_types?: Term[];
searchable?: boolean;
default_page?: boolean;
in_navigation?: boolean;
allow_discussion?: boolean;
versioning?: Term;
behaviors?: Term[];
[field: string]: unknown;
};
schema: { fieldsets: Array<{ id: string; fields: string[] }> };
workflow?: { id: string | null; follows_default: boolean };
/** The workflows of the type's chain, in order, the first setting the state. */
workflow?: { chain: string[]; follows_default: boolean };
/** Not sent yet: every type counts as folderish without it. */
folderish?: boolean;
}
Expand All @@ -91,7 +93,10 @@ const kindOf = (response: ContentTypeResponse) =>

const workflowOf = (response: ContentTypeResponse) =>
response.workflow && {
workflow: response.workflow.id,
workflow: response.workflow.chain[0] ?? null,
...(response.workflow.chain.length > 1 && {
chain: response.workflow.chain,
}),
followsDefault: response.workflow.follows_default,
};

Expand All @@ -103,7 +108,7 @@ export function toSummary(response: ContentTypeResponse): ContentTypeSummary {
title: data.title || response.title,
description: data.description || undefined,
kind: kindOf(response),
count: response.items_total ?? 0,
count: response.content_count ?? 0,
globalAllow: data.global_allow,
workflow: workflowOf(response),
versioning: tokenOf(data.versioning) as VersioningPolicy | undefined,
Expand Down Expand Up @@ -131,7 +136,7 @@ export function toSettings(response: ContentTypeResponse): ContentTypeSettings {
...(folderish && { allowedContents }),
globalAllow: data.global_allow,
searchable: data.searchable,
defaultPage: data.default_page,
inNavigation: data.in_navigation,
allowDiscussion: data.allow_discussion,
versioning: tokenOf(data.versioning) as VersioningPolicy | undefined,
behaviors: (data.behaviors ?? [])
Expand All @@ -151,7 +156,7 @@ export function toContentTypePatch(
['description', 'description'],
['globalAllow', 'global_allow'],
['searchable', 'searchable'],
['defaultPage', 'default_page'],
['inNavigation', 'in_navigation'],
['allowDiscussion', 'allow_discussion'],
['versioning', 'versioning'],
['behaviors', 'behaviors'],
Expand Down
Loading
Loading