Skip to content

Commit 73d19bf

Browse files
authored
Improve post type settings (#75)
* Split sections into two scripts * Simplify implementation * Display icon * Add more labels
1 parent 55a4400 commit 73d19bf

File tree

4 files changed

+218
-117
lines changed

4 files changed

+218
-117
lines changed

includes/manager/class-content-model-loader.php

+47-6
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ private function __construct() {
4949

5050
$this->register_post_type();
5151
$this->maybe_enqueue_the_attribute_binder();
52+
$this->maybe_enqueue_the_cpt_settings_panel();
5253
$this->maybe_enqueue_the_fields_ui();
5354
$this->maybe_enqueue_content_model_length_restrictor();
5455

@@ -123,18 +124,19 @@ private function register_post_type() {
123124
)
124125
);
125126

126-
$cpt_fields = [
127-
'plural_label' => [
127+
$cpt_fields = array(
128+
'plural_label' => array(
128129
'type' => 'string',
129130
'single' => true,
130131
'show_in_rest' => true,
131-
],
132-
'description' => [
132+
),
133+
'icon' => array(
133134
'type' => 'string',
134135
'single' => true,
135136
'show_in_rest' => true,
136-
],
137-
];
137+
'default' => 'admin-site',
138+
),
139+
);
138140

139141
foreach ( $cpt_fields as $field_name => $field_args ) {
140142
register_post_meta(
@@ -187,6 +189,45 @@ function () {
187189
);
188190
}
189191

192+
/**
193+
* Conditionally enqueues the CPT settings script for the content model editor.
194+
*
195+
* Checks if the current post is of the correct type before enqueueing the script.
196+
*
197+
* @return void
198+
*/
199+
private function maybe_enqueue_the_cpt_settings_panel() {
200+
add_action(
201+
'enqueue_block_editor_assets',
202+
function () {
203+
global $post;
204+
205+
if ( ! $post || Content_Model_Manager::POST_TYPE_NAME !== $post->post_type ) {
206+
return;
207+
}
208+
209+
$asset_file = include CONTENT_MODEL_PLUGIN_PATH . 'includes/manager/dist/cpt-settings-panel.asset.php';
210+
211+
wp_register_script(
212+
'data-types/cpt-settings-panel',
213+
CONTENT_MODEL_PLUGIN_URL . '/includes/manager/dist/cpt-settings-panel.js',
214+
$asset_file['dependencies'],
215+
$asset_file['version'],
216+
true
217+
);
218+
219+
wp_localize_script(
220+
'data-types/cpt-settings-panel',
221+
'contentModelFields',
222+
array(
223+
'postType' => Content_Model_Manager::POST_TYPE_NAME,
224+
)
225+
);
226+
227+
wp_enqueue_script( 'data-types/cpt-settings-panel' );
228+
}
229+
);
230+
}
190231

191232

192233
/**
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { registerPlugin } from '@wordpress/plugins';
2+
import { PluginDocumentSettingPanel } from '@wordpress/editor';
3+
import { TextControl, Dashicon } from '@wordpress/components';
4+
import { __ } from '@wordpress/i18n';
5+
import {
6+
useLayoutEffect,
7+
useRef,
8+
createInterpolateElement,
9+
} from '@wordpress/element';
10+
import { useEntityProp } from '@wordpress/core-data';
11+
12+
const CreateContentModelCptSettings = function () {
13+
const [ meta, setMeta ] = useEntityProp(
14+
'postType',
15+
window.contentModelFields.postType,
16+
'meta'
17+
);
18+
19+
const [ title, setTitle ] = useEntityProp(
20+
'postType',
21+
window.contentModelFields.postType,
22+
'title'
23+
);
24+
25+
const lastTitle = useRef( title );
26+
27+
useLayoutEffect( () => {
28+
if ( title !== lastTitle.current ) {
29+
lastTitle.current = title;
30+
setMeta( { ...meta, plural_label: `${ title }s` } );
31+
}
32+
}, [ title, meta, setMeta ] );
33+
34+
const dashicon = meta.icon.replace( 'dashicons-', '' );
35+
36+
return (
37+
<>
38+
<PluginDocumentSettingPanel
39+
name="create-content-model-post-settings"
40+
title={ __( 'Post Type' ) }
41+
className="create-content-model-post-settings"
42+
>
43+
<TextControl
44+
label={ __( 'Singular Label' ) }
45+
value={ title }
46+
onChange={ setTitle }
47+
help={ __( 'This is synced with the post title' ) }
48+
/>
49+
<TextControl
50+
label={ __( 'Plural Label' ) }
51+
value={ meta.plural_label }
52+
onChange={ ( value ) =>
53+
setMeta( { ...meta, plural_label: value } )
54+
}
55+
help={ __(
56+
'This is the label that will be used for the plural form of the post type'
57+
) }
58+
/>
59+
<div style={ { position: 'relative' } }>
60+
<TextControl
61+
label={ __( 'Icon name' ) }
62+
value={ meta.icon }
63+
onChange={ ( icon ) => setMeta( { ...meta, icon } ) }
64+
help={ createInterpolateElement(
65+
__(
66+
'The icon for the post type. <a>See reference</a>'
67+
),
68+
{
69+
a: (
70+
// eslint-disable-next-line jsx-a11y/anchor-has-content
71+
<a
72+
target="_blank"
73+
href="https://developer.wordpress.org/resource/dashicons/"
74+
rel="noreferrer"
75+
/>
76+
),
77+
}
78+
) }
79+
/>
80+
{ dashicon && (
81+
<div
82+
style={ {
83+
position: 'absolute',
84+
top: '30px',
85+
right: '8px',
86+
} }
87+
>
88+
{ ' ' }
89+
<Dashicon icon={ dashicon } />{ ' ' }
90+
</div>
91+
) }
92+
</div>
93+
</PluginDocumentSettingPanel>
94+
</>
95+
);
96+
};
97+
98+
// Register the plugin.
99+
registerPlugin( 'create-content-model-cpt-settings', {
100+
render: CreateContentModelCptSettings,
101+
} );

includes/manager/fields-ui.js

+36-106
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { PluginDocumentSettingPanel } from '@wordpress/editor';
33
import {
44
Button,
55
Modal,
6-
TextControl,
76
__experimentalVStack as VStack,
87
__experimentalItemGroup as ItemGroup,
98
__experimentalItem as Item,
@@ -19,31 +18,15 @@ import { seen, unseen, blockDefault } from '@wordpress/icons';
1918

2019
import EditFieldForm from './_edit-field';
2120

22-
/**
23-
* Our base plugin component.
24-
* @returns CreateContentModelPageSettings
25-
*/
2621
const CreateContentModelPageSettings = function () {
2722
const [ isFieldsOpen, setFieldsOpen ] = useState( false );
2823

29-
const [ meta, setMeta ] = useEntityProp(
24+
const [ meta ] = useEntityProp(
3025
'postType',
31-
contentModelFields.postType,
26+
window.contentModelFields.postType,
3227
'meta'
3328
);
3429

35-
const [ slug, setSlug ] = useEntityProp(
36-
'postType',
37-
contentModelFields.postType,
38-
'slug'
39-
);
40-
41-
const [ title, setTitle ] = useEntityProp(
42-
'postType',
43-
contentModelFields.postType,
44-
'title'
45-
);
46-
4730
// Saving the fields as serialized JSON because I was tired of fighting the REST API.
4831
const fields = meta?.fields ? JSON.parse( meta.fields ) : [];
4932

@@ -54,94 +37,45 @@ const CreateContentModelPageSettings = function () {
5437
}
5538
} );
5639

57-
const textControlFields = [
58-
{
59-
key: 'slug',
60-
label: __( 'Slug' ),
61-
value: slug,
62-
onChange: ( value ) => setSlug( value ),
63-
help: __(
64-
'Warning: Changing the slug will break existing content.'
65-
),
66-
},
67-
{
68-
key: 'singular_label',
69-
label: __( 'Singular Label' ),
70-
value: title,
71-
onChange: ( value ) => setTitle( value ),
72-
help: __( 'Synced with the title of the post type.' ),
73-
},
74-
{
75-
key: 'plural_label',
76-
label: __( 'Plural Label' ),
77-
value: meta.plural_label || `${ title }s`,
78-
onChange: ( value ) => setMeta( { ...meta, plural_label: value } ),
79-
help: __(
80-
'This is the label that will be used for the plural form of the post type.'
81-
),
82-
},
83-
{
84-
key: 'description',
85-
label: __( 'Description' ),
86-
value: meta.description,
87-
onChange: ( value ) => setMeta( { ...meta, description: value } ),
88-
help: __( 'Description for the post type.' ),
89-
},
90-
];
91-
9240
return (
9341
<>
94-
<PluginDocumentSettingPanel
95-
name="create-content-model-post-settings"
96-
title={ __( 'Post Type' ) }
97-
className="create-content-model-post-settings"
98-
>
99-
{ textControlFields.map( ( field ) => (
100-
<TextControl
101-
key={ field.key }
102-
label={ field.label }
103-
value={ field.value }
104-
onChange={ field.onChange }
105-
disabled={ field.disabled }
106-
help={ field.help }
107-
/>
108-
) ) }
109-
</PluginDocumentSettingPanel>
11042
<PluginDocumentSettingPanel
11143
name="create-content-model-field-settings"
11244
title={ __( 'Custom Fields' ) }
11345
className="create-content-model-field-settings"
11446
>
115-
<ItemGroup isBordered isSeparated>
116-
{ fields.map( ( field ) => (
117-
<Item key={ field.uuid }>
118-
<Flex>
119-
<FlexBlock>{ field.label }</FlexBlock>
120-
<FlexItem>
121-
<code>{ field.slug }</code>
122-
</FlexItem>
123-
124-
{ field.visible && (
47+
{ fields.length > 0 && (
48+
<ItemGroup isBordered isSeparated>
49+
{ fields.map( ( field ) => (
50+
<Item key={ field.uuid }>
51+
<Flex>
52+
<FlexBlock>{ field.label }</FlexBlock>
12553
<FlexItem>
126-
<Icon icon={ seen } />
54+
<code>{ field.slug }</code>
12755
</FlexItem>
128-
) }
129-
{ ! field.visible &&
130-
field.type.indexOf( 'core' ) > -1 && (
131-
<FlexItem>
132-
<Icon icon={ blockDefault } />
133-
</FlexItem>
134-
) }
135-
{ ! field.visible &&
136-
field.type.indexOf( 'core' ) < 0 && (
56+
57+
{ field.visible && (
13758
<FlexItem>
138-
<Icon icon={ unseen } />
59+
<Icon icon={ seen } />
13960
</FlexItem>
14061
) }
141-
</Flex>
142-
</Item>
143-
) ) }
144-
</ItemGroup>
62+
{ ! field.visible &&
63+
field.type.indexOf( 'core' ) > -1 && (
64+
<FlexItem>
65+
<Icon icon={ blockDefault } />
66+
</FlexItem>
67+
) }
68+
{ ! field.visible &&
69+
field.type.indexOf( 'core' ) < 0 && (
70+
<FlexItem>
71+
<Icon icon={ unseen } />
72+
</FlexItem>
73+
) }
74+
</Flex>
75+
</Item>
76+
) ) }
77+
</ItemGroup>
78+
) }
14579

14680
<Button
14781
variant="secondary"
@@ -164,14 +98,10 @@ const CreateContentModelPageSettings = function () {
16498
);
16599
};
166100

167-
/**
168-
* Display the list of fields inside the modal.
169-
* @returns FieldsList
170-
*/
171101
const FieldsList = () => {
172102
const [ meta, setMeta ] = useEntityProp(
173103
'postType',
174-
contentModelFields.postType,
104+
window.contentModelFields.postType,
175105
'meta'
176106
);
177107

@@ -215,22 +145,22 @@ const FieldsList = () => {
215145
index={ fields.findIndex(
216146
( f ) => f.uuid === field.uuid
217147
) }
218-
onMoveUp={ ( field ) => {
148+
onMoveUp={ ( movedField ) => {
219149
const index = fields.findIndex(
220-
( f ) => f.uuid === field.uuid
150+
( f ) => f.uuid === movedField.uuid
221151
);
222152
const newFields = [ ...fields ];
223153
newFields.splice( index, 1 );
224-
newFields.splice( index - 1, 0, field );
154+
newFields.splice( index - 1, 0, movedField );
225155
setFields( newFields );
226156
} }
227-
onMoveDown={ ( field ) => {
157+
onMoveDown={ ( movedField ) => {
228158
const index = fields.findIndex(
229-
( f ) => f.uuid === field.uuid
159+
( f ) => f.uuid === movedField.uuid
230160
);
231161
const newFields = [ ...fields ];
232162
newFields.splice( index, 1 );
233-
newFields.splice( index + 1, 0, field );
163+
newFields.splice( index + 1, 0, movedField );
234164
setFields( newFields );
235165
} }
236166
/>

0 commit comments

Comments
 (0)