/** * WordPress dependencies */ import { SelectControl, TextareaControl, TextControl, } from '@safe-wordpress/components'; import { useDispatch } from '@safe-wordpress/data'; import { _x, sprintf } from '@safe-wordpress/i18n'; /** * External dependencies */ import { countBy, drop, take, toPairs } from 'lodash'; import { createScopeRule } from '@nab/utils'; import type { QueryArgSetting, TestedUrlWithQueryArgsScopeRule, } from '@nab/types'; /** * Internal dependencies */ import './style.scss'; import { store as NAB_EDITOR } from '../../../../store'; export type TestedUrlWithQueryArgsScopeProps = { readonly rules: ReadonlyArray< TestedUrlWithQueryArgsScopeRule >; }; export const TestedUrlWithQueryArgsScope = ( { rules, }: TestedUrlWithQueryArgsScopeProps ): JSX.Element => { const { setScopeRules } = useDispatch( NAB_EDITOR ); const rule = rules[ 0 ] ?? DEFAULT_RULE; const values = rule.attributes.value.args ?? []; return (

{ _x( 'Test will be active on tested URLs if their query parameters match the following conditions:', 'text', 'nelio-ab-testing' ) }

setScopeRules( [ { ...rule, attributes: { ...rule.attributes, value: { ...rule.attributes.value, args, }, }, }, ] ) } />
); }; // ============ // HELPER VIEWS // ============ const QueryArgSettings = ( { value: args, onChange, }: { readonly value: ReadonlyArray< QueryArgSetting >; readonly onChange: ( args: ReadonlyArray< QueryArgSetting > ) => void; } ): JSX.Element => { const names = countBy( args, 'name' ); return (
{ [ ...args, NEW_ARG ].map( ( arg, index ) => ( = 2 } onChange={ ( newArg ) => onChange( [ ...take( args, index ), { ...arg, ...newArg }, ...drop( args, index + 1 ), ] ) } /> ) ) }
); }; const QueryArgSetting = ( { hasDuplicateName, value: setting, onChange, }: { readonly hasDuplicateName: boolean; readonly value: QueryArgSetting; readonly onChange: ( attrs: Partial< QueryArgSetting > ) => void; } ): JSX.Element => (
onChange( { name } ) } /> onChange( { condition } ) } />
onChange( { value } ) } />
{ hasDuplicateName && (
{ sprintf( /* translators: %s: Query parameter’s name. */ _x( 'Query parameter “%s” should only appear once in the test scope', 'text', 'nelio-ab-testing' ), setting.name ) }
) }
); const QueryArgValue = ( { type, value, onChange, }: { readonly type: QueryArgSetting[ 'condition' ]; readonly value: string; readonly onChange: ( value: string ) => void; } ): JSX.Element | null => { switch ( type ) { case 'exists': case 'does-not-exist': return null; case 'is-equal-to': case 'is-not-equal-to': case 'contains': case 'does-not-contain': return ( ); case 'is-any-of': case 'is-none-of': return ( ); } }; // ==== // DATA // ==== const NEW_ARG: QueryArgSetting = { name: '', condition: 'exists', value: '', }; const DEFAULT_RULE = createScopeRule( { type: 'tested-url-with-query-args', value: { urls: [], args: [] }, } ) as TestedUrlWithQueryArgsScopeRule; type Condition = QueryArgSetting[ 'condition' ]; const CONDITION_LABEL_RECORD: Record< Condition, string > = { exists: _x( 'Exists', 'text', 'nelio-ab-testing' ), 'does-not-exist': _x( 'Does not exist', 'text', 'nelio-ab-testing' ), 'is-equal-to': _x( 'Is equal to', 'text', 'nelio-ab-testing' ), 'is-not-equal-to': _x( 'Is not equal to', 'text', 'nelio-ab-testing' ), contains: _x( 'Contains', 'text', 'nelio-ab-testing' ), 'does-not-contain': _x( 'Does not contain', 'text', 'nelio-ab-testing' ), 'is-any-of': _x( 'Is any of', 'text', 'nelio-ab-testing' ), 'is-none-of': _x( 'Is none of', 'text', 'nelio-ab-testing' ), }; const CONDITIONS = toPairs( CONDITION_LABEL_RECORD ).map( ( [ value, label ] ) => ( { label, value, } ) );