diff --git a/packages/dataviews/src/components/dataform-controls/index.tsx b/packages/dataviews/src/components/dataform-controls/index.tsx
new file mode 100644
index 00000000000000..dd913269cd09ea
--- /dev/null
+++ b/packages/dataviews/src/components/dataform-controls/index.tsx
@@ -0,0 +1,46 @@
+/**
+ * External dependencies
+ */
+import type { ComponentType } from 'react';
+
+/**
+ * Internal dependencies
+ */
+import type {
+ DataFormControlProps,
+ Field,
+ FieldTypeDefinition,
+} from '../../types';
+import radio from './radio';
+
+interface FormControls {
+ [ key: string ]: ComponentType< DataFormControlProps< any > >;
+}
+
+const FORM_CONTROLS: FormControls = {
+ radio,
+};
+
+export function getControl< Item >(
+ field: Field< Item >,
+ fieldTypeDefinition: FieldTypeDefinition< Item >
+) {
+ if ( typeof field.Edit === 'function' ) {
+ return field.Edit;
+ }
+
+ let control;
+ if ( typeof field.Edit === 'string' ) {
+ control = getControlByType( field.Edit );
+ }
+
+ return control || fieldTypeDefinition.Edit;
+}
+
+export function getControlByType( type: string ) {
+ if ( Object.keys( FORM_CONTROLS ).includes( type ) ) {
+ return FORM_CONTROLS[ type ];
+ }
+
+ return null;
+}
diff --git a/packages/dataviews/src/components/dataform-controls/radio.tsx b/packages/dataviews/src/components/dataform-controls/radio.tsx
new file mode 100644
index 00000000000000..d264aa6c24b7fb
--- /dev/null
+++ b/packages/dataviews/src/components/dataform-controls/radio.tsx
@@ -0,0 +1,43 @@
+/**
+ * WordPress dependencies
+ */
+import { RadioControl } from '@wordpress/components';
+import { useCallback } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import type { DataFormControlProps } from '../../types';
+
+export default function Edit< Item >( {
+ data,
+ field,
+ onChange,
+ hideLabelFromVision,
+}: DataFormControlProps< Item > ) {
+ const { id, label } = field;
+ const value = field.getValue( { item: data } );
+
+ const onChangeControl = useCallback(
+ ( newValue: string ) =>
+ onChange( ( prevItem: Item ) => ( {
+ ...prevItem,
+ [ id ]: newValue,
+ } ) ),
+ [ id, onChange ]
+ );
+
+ if ( field.elements ) {
+ return (
+
+ );
+ }
+
+ return null;
+}
diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx
index 7808756b7b6557..7f3c5ff879b72a 100644
--- a/packages/dataviews/src/components/dataform/stories/index.story.tsx
+++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx
@@ -56,6 +56,17 @@ const fields = [
{ value: 2, label: 'John' },
],
},
+ {
+ id: 'reviewer',
+ label: 'Reviewer',
+ type: 'text' as const,
+ Edit: 'radio' as const,
+ elements: [
+ { value: 'fulano', label: 'Fulano' },
+ { value: 'mengano', label: 'Mengano' },
+ { value: 'zutano', label: 'Zutano' },
+ ],
+ },
{
id: 'status',
label: 'Status',
@@ -73,12 +84,21 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => {
order: 2,
author: 1,
status: 'draft',
+ reviewer: 'fulano',
date: '2021-01-01T12:00:00',
birthdate: '1950-02-23T12:00:00',
} );
const form = {
- fields: [ 'title', 'order', 'author', 'status', 'date', 'birthdate' ],
+ fields: [
+ 'title',
+ 'order',
+ 'author',
+ 'reviewer',
+ 'status',
+ 'date',
+ 'birthdate',
+ ],
};
return (
diff --git a/packages/dataviews/src/normalize-fields.ts b/packages/dataviews/src/normalize-fields.ts
index 680749df5344a6..54992ff22fe2ae 100644
--- a/packages/dataviews/src/normalize-fields.ts
+++ b/packages/dataviews/src/normalize-fields.ts
@@ -3,6 +3,7 @@
*/
import getFieldTypeDefinition from './field-types';
import type { Field, NormalizedField } from './types';
+import { getControl } from './components/dataform-controls';
/**
* Apply default values and normalize the fields config.
@@ -38,7 +39,7 @@ export function normalizeFields< Item >(
);
};
- const Edit = field.Edit || fieldTypeDefinition.Edit;
+ const Edit = getControl( field, fieldTypeDefinition );
const renderFromElements = ( { item }: { item: Item } ) => {
const value = getValue( { item } );
diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts
index 2e87d1371acb61..d8a5ee8f68ecef 100644
--- a/packages/dataviews/src/types.ts
+++ b/packages/dataviews/src/types.ts
@@ -53,6 +53,26 @@ export type ValidationContext = {
elements?: Option[];
};
+/**
+ * An abstract interface for Field based on the field type.
+ */
+export type FieldTypeDefinition< Item > = {
+ /**
+ * Callback used to sort the field.
+ */
+ sort: ( a: Item, b: Item, direction: SortDirection ) => number;
+
+ /**
+ * Callback used to validate the field.
+ */
+ isValid: ( item: Item, context?: ValidationContext ) => boolean;
+
+ /**
+ * Callback used to render an edit control for the field.
+ */
+ Edit: ComponentType< DataFormControlProps< Item > >;
+};
+
/**
* A dataview field for a specific property of a data type.
*/
@@ -90,7 +110,7 @@ export type Field< Item > = {
/**
* Callback used to render an edit control for the field.
*/
- Edit?: ComponentType< DataFormControlProps< Item > >;
+ Edit?: ComponentType< DataFormControlProps< Item > > | 'radio';
/**
* Callback used to sort the field.
diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js
index 35141f743cd2e3..0a56fdfe5786b7 100644
--- a/packages/edit-site/src/components/post-edit/index.js
+++ b/packages/edit-site/src/components/post-edit/index.js
@@ -51,7 +51,7 @@ function PostEditForm( { postType, postId } ) {
const { fields } = usePostFields();
const form = {
type: 'panel',
- fields: [ 'title', 'author', 'date' ],
+ fields: [ 'title', 'author', 'date', 'comment_status' ],
};
const [ edits, setEdits ] = useState( initialEdits );
const itemWithEdits = useMemo( () => {
diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js
index 44625fbfbfafb9..b03b2c6f5be3c4 100644
--- a/packages/edit-site/src/components/post-fields/index.js
+++ b/packages/edit-site/src/components/post-fields/index.js
@@ -345,6 +345,32 @@ function usePostFields( viewType ) {
return ;
},
},
+ {
+ id: 'comment_status',
+ label: __( 'Discussion' ),
+ type: 'text',
+ Edit: 'radio',
+ enableSorting: false,
+ filterBy: {
+ operators: [],
+ },
+ elements: [
+ {
+ value: 'open',
+ label: __( 'Open' ),
+ description: __(
+ 'Visitors can add new comments and replies.'
+ ),
+ },
+ {
+ value: 'closed',
+ label: __( 'Closed' ),
+ description: __(
+ 'Visitors cannot add new comments or replies. Existing comments remain visible.'
+ ),
+ },
+ ],
+ },
],
[ authors, viewType, frontPageId, postsPageId ]
);