Skip to content

Commit 05935db

Browse files
authored
DataViews: Support email type of the form field (#103579)
* Dataviews: Support email type of the form field * Add the email control to dataform * Try to remove the duplicate validation * Add email field to story * Add required to ValidationContext * Revert "Try to remove the duplicate validation" This reverts commit c0573e0. * Revert "Add required to ValidationContext" This reverts commit fe787dc. * Fix naming
1 parent ad24cbe commit 05935db

File tree

7 files changed

+122
-1
lines changed

7 files changed

+122
-1
lines changed

packages/dataviews/CHANGELOG.automattic.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- Add user input filter support based on the `Edit` property of the field type definitions.
1414
- Add new filter operators: `lessThan`, `greaterThan`, `lessThanOrEqual`, and `greaterThanOrEqual` for numeric and comparable fields.
1515
- Add new filter operators: `contains`, `notContains`, `startsWith` for text fields.
16+
- Add `email` type to the fields of the form.
1617

1718
## 0.1.1
1819

packages/dataviews/src/components/dataform/stories/index.story.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ const fields = [
9595
{ value: 'private', label: 'Private' },
9696
],
9797
},
98+
{
99+
id: 'email',
100+
label: 'Email',
101+
type: 'email' as const,
102+
},
98103
{
99104
id: 'password',
100105
label: 'Password',
@@ -123,6 +128,7 @@ export const Default = ( {
123128
author: 1,
124129
status: 'draft',
125130
reviewer: 'fulano',
131+
126132
date: '2021-01-01T12:00:00',
127133
birthdate: '1950-02-23T12:00:00',
128134
sticky: false,
@@ -139,6 +145,7 @@ export const Default = ( {
139145
'author',
140146
'status',
141147
'reviewer',
148+
'email',
142149
'password',
143150
'date',
144151
'birthdate',
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { TextControl } from '@wordpress/components';
5+
import { useCallback } from '@wordpress/element';
6+
7+
/**
8+
* Internal dependencies
9+
*/
10+
import type { DataFormControlProps } from '../types';
11+
12+
export default function Email< Item >( {
13+
data,
14+
field,
15+
onChange,
16+
hideLabelFromVision,
17+
}: DataFormControlProps< Item > ) {
18+
const { id, label, placeholder } = field;
19+
const value = field.getValue( { item: data } );
20+
21+
const onChangeControl = useCallback(
22+
( newValue: string ) =>
23+
onChange( {
24+
[ id ]: newValue,
25+
} ),
26+
[ id, onChange ]
27+
);
28+
29+
return (
30+
<TextControl
31+
type="email"
32+
label={ label }
33+
placeholder={ placeholder }
34+
value={ value ?? '' }
35+
onChange={ onChangeControl }
36+
__next40pxDefaultSize
37+
__nextHasNoMarginBottom
38+
hideLabelFromVision={ hideLabelFromVision }
39+
/>
40+
);
41+
}

packages/dataviews/src/dataform-controls/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
FieldTypeDefinition,
1313
} from '../types';
1414
import datetime from './datetime';
15+
import email from './email';
1516
import integer from './integer';
1617
import radio from './radio';
1718
import select from './select';
@@ -26,6 +27,7 @@ interface FormControls {
2627
const FORM_CONTROLS: FormControls = {
2728
boolean,
2829
datetime,
30+
email,
2931
integer,
3032
radio,
3133
select,
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { isEmail } from '@wordpress/url';
5+
6+
/**
7+
* Internal dependencies
8+
*/
9+
import type {
10+
DataViewRenderFieldProps,
11+
SortDirection,
12+
ValidationContext,
13+
Operator,
14+
} from '../types';
15+
import { renderFromElements } from '../utils';
16+
import { OPERATOR_IS_ANY, OPERATOR_IS_NONE } from '../constants';
17+
18+
function sort( valueA: any, valueB: any, direction: SortDirection ) {
19+
return direction === 'asc'
20+
? valueA.localeCompare( valueB )
21+
: valueB.localeCompare( valueA );
22+
}
23+
24+
function isValid( value: any, context?: ValidationContext ) {
25+
// TODO: this implicitly means the value is required.
26+
if ( value === '' ) {
27+
return false;
28+
}
29+
30+
if ( ! isEmail( value ) ) {
31+
return false;
32+
}
33+
34+
if ( context?.elements ) {
35+
const validValues = context?.elements?.map( ( f ) => f.value );
36+
if ( ! validValues.includes( value ) ) {
37+
return false;
38+
}
39+
}
40+
41+
return true;
42+
}
43+
44+
const operators: Operator[] = [ OPERATOR_IS_ANY, OPERATOR_IS_NONE ];
45+
46+
export default {
47+
sort,
48+
isValid,
49+
Edit: 'email',
50+
render: ( { item, field }: DataViewRenderFieldProps< any > ) => {
51+
return field.elements
52+
? renderFromElements( { item, field } )
53+
: field.getValue( { item } );
54+
},
55+
enableSorting: true,
56+
filterBy: {
57+
operators,
58+
},
59+
};

packages/dataviews/src/field-types/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
SortDirection,
99
ValidationContext,
1010
} from '../types';
11+
import { default as email } from './email';
1112
import { default as integer } from './integer';
1213
import { default as text } from './text';
1314
import { default as datetime } from './datetime';
@@ -24,6 +25,10 @@ import { renderFromElements } from '../utils';
2425
export default function getFieldTypeDefinition< Item >(
2526
type?: FieldType
2627
): FieldTypeDefinition< Item > {
28+
if ( 'email' === type ) {
29+
return email;
30+
}
31+
2732
if ( 'integer' === type ) {
2833
return integer;
2934
}

packages/dataviews/src/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,13 @@ export type Operator =
5454
| 'notContains'
5555
| 'startsWith';
5656

57-
export type FieldType = 'text' | 'integer' | 'datetime' | 'media' | 'boolean';
57+
export type FieldType =
58+
| 'text'
59+
| 'integer'
60+
| 'datetime'
61+
| 'media'
62+
| 'boolean'
63+
| 'email';
5864

5965
export type ValidationContext = {
6066
elements?: Option[];

0 commit comments

Comments
 (0)