/**
* 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,
} )
);