Skip to content

Commit

Permalink
Implement validation slug
Browse files Browse the repository at this point in the history
  • Loading branch information
gigitux committed Nov 1, 2024
1 parent 3b9bb77 commit d021369
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 17 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions packages/dataviews/src/normalize-fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,8 @@ export function normalizeFields< Item >(

const isValid =
field.isValid ??
function isValid( item, context ) {
return fieldTypeDefinition.isValid(
getValue( { item } ),
context
);
function isValid( value, item, context ) {
return fieldTypeDefinition.isValid( value, context );
};

const Edit = getControl( field, fieldTypeDefinition );
Expand Down
8 changes: 6 additions & 2 deletions packages/dataviews/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ export type Field< Item > = {
/**
* Callback used to validate the field.
*/
isValid?: ( item: Item, context?: ValidationContext ) => boolean;
isValid?: (
value: any,
item?: Item,
context?: ValidationContext
) => boolean;

/**
* Callback used to decide if a field should be displayed.
Expand Down Expand Up @@ -167,7 +171,7 @@ export type NormalizedField< Item > = Field< Item > & {
render: ComponentType< DataViewRenderFieldProps< Item > >;
Edit: ComponentType< DataFormControlProps< Item > >;
sort: ( a: Item, b: Item, direction: SortDirection ) => number;
isValid: ( item: Item, context?: ValidationContext ) => boolean;
isValid: ( value: any, item: Item, context?: ValidationContext ) => boolean;
enableHiding: boolean;
enableSorting: boolean;
};
Expand Down
3 changes: 2 additions & 1 deletion packages/dataviews/src/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export function isItemValid< Item >(
fields.filter( ( { id } ) => !! form.fields?.includes( id ) )
);
return _fields.every( ( field ) => {
return field.isValid( item, { elements: field.elements } );
const value = field.getValue( { item } );
return field.isValid( value, item, { elements: field.elements } );
} );
}
1 change: 1 addition & 0 deletions packages/fields/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@wordpress/warning": "*",
"change-case": "4.1.2",
"client-zip": "^2.4.5",
"clsx": "^2.1.1",
"remove-accents": "^0.5.0"
},
"peerDependencies": {
Expand Down
6 changes: 5 additions & 1 deletion packages/fields/src/fields/slug/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ import type { BasePost } from '../../types';
import { __ } from '@wordpress/i18n';
import SlugEdit from './slug-edit';
import SlugView from './slug-view';
import { getSlug } from './utils';

const slugField: Field< BasePost > = {
id: 'slug',
type: 'text',
label: __( 'Slug' ),
getValue: ( { item } ) => item.slug,
getValue: ( { item } ) => getSlug( item ),
isValid: ( value ) => {
return ( value && value.length > 0 ) || false;
},
Edit: SlugEdit,
render: SlugView,
};
Expand Down
32 changes: 24 additions & 8 deletions packages/fields/src/fields/slug/slug-edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,21 @@ import {
import { copySmall } from '@wordpress/icons';
import { useCopyToClipboard, useInstanceId } from '@wordpress/compose';
import { useDispatch } from '@wordpress/data';
import { useCallback, useEffect, useRef } from '@wordpress/element';
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
import { store as noticesStore } from '@wordpress/notices';
import { safeDecodeURIComponent } from '@wordpress/url';
import type { DataFormControlProps } from '@wordpress/dataviews';
import { __ } from '@wordpress/i18n';

/**
* External dependencies
*/
import clsx from 'clsx';

/**
* Internal dependencies
*/
import type { BasePost } from '../../types';
import { getSlug } from './utils';

const SlugEdit = ( {
field,
Expand All @@ -30,7 +34,10 @@ const SlugEdit = ( {
}: DataFormControlProps< BasePost > ) => {
const { id } = field;

const slug = field.getValue( { item: data } ) || getSlug( data );
const slug = field.getValue( { item: data } );

const [ isValid, setIsValid ] = useState( true );

const permalinkTemplate = data.permalink_template || '';
const PERMALINK_POSTNAME_REGEX = /%(?:postname|pagename)%/;
const [ prefix, suffix ] = permalinkTemplate.split(
Expand All @@ -40,7 +47,7 @@ const SlugEdit = ( {
const permalinkSuffix = suffix;
const isEditable = PERMALINK_POSTNAME_REGEX.test( permalinkTemplate );
const originalSlugRef = useRef( slug );
const slugToDisplay = slug || originalSlugRef.current;
const slugToDisplay = slug;
const permalink = isEditable
? `${ permalinkPrefix }${ slugToDisplay }${ permalinkSuffix }`
: safeDecodeURIComponent( data.link || '' );
Expand All @@ -52,11 +59,13 @@ const SlugEdit = ( {
}, [ slug ] );

const onChangeControl = useCallback(
( newValue?: string ) =>
( newValue?: string ) => {
setIsValid( field.isValid( newValue ?? '' ) );
onChange( {
[ id ]: newValue,
} ),
[ id, onChange ]
} );
},
[ field, id, onChange ]
);

const { createNotice } = useDispatch( noticesStore );
Expand Down Expand Up @@ -106,7 +115,9 @@ const SlugEdit = ( {
autoComplete="off"
spellCheck="false"
type="text"
className="fields-controls__slug-input"
className={ clsx( 'fields-controls__slug-input', {
'fields-controls__slug-input--invalid': ! isValid,
} ) }
onChange={ ( newValue?: string ) => {
onChangeControl( newValue );
} }
Expand All @@ -117,6 +128,11 @@ const SlugEdit = ( {
} }
aria-describedby={ postUrlSlugDescriptionId }
/>
{ ! isValid && (
<div className="fields-controls__slug-error">
<span>{ __( 'The slug is invalid.' ) }</span>
</div>
) }
<div className="fields-controls__slug-help">
<span className="fields-controls__slug-help-visual-label">
{ __( 'Permalink:' ) }
Expand Down
12 changes: 12 additions & 0 deletions packages/fields/src/fields/slug/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
padding-inline-start: 0 !important;
}

.fields-controls__slug-input--invalid {
.components-input-control__backdrop,
.components-input-control__backdrop:focus-within {
border-color: $alert-red !important;
box-shadow: 0 0 0 0.5px $alert-red !important;
}
}

.fields-controls__slug-error {
color: $alert-red;
}

.fields-controls__slug-help-link {
word-break: break-word;
}
Expand Down

0 comments on commit d021369

Please sign in to comment.