/**
* WordPress dependencies
*/
import { CheckboxControl, SelectControl } from '@safe-wordpress/components';
import { useState } from '@safe-wordpress/element';
import { _x } from '@safe-wordpress/i18n';
import {
select as doSelect,
useDispatch,
useSelect,
} from '@safe-wordpress/data';
/**
* External dependencies
*/
import clsx from 'clsx';
import { filter, map } from 'lodash';
import { PostSearcher } from '@nab/components';
import { store as NAB_DATA } from '@nab/data';
import {
createAlternative,
isEmpty,
isMultiArray,
isSingleton,
} from '@nab/utils';
import type { PostSearcherProps } from '@nab/components';
import type {
Alternative,
ExperimentEditProps,
EntityKind,
Maybe,
} from '@nab/types';
// NOTE. Dependency loop with @nab package.
import type { store as editorStore } from '@nab/editor';
const NAB_EDITOR = 'nab/editor' as unknown as typeof editorStore;
/**
* Internal dependencies
*/
import './style.scss';
import { usePostTypes } from '../../hooks';
import type { ControlAttributes } from '../../types';
type Attributes< T extends string > = {
[ K in keyof ControlAttributes ]: K extends 'postType'
? T
: ControlAttributes[ K ];
};
export type OriginalProps< T extends string > = ExperimentEditProps<
Attributes< T >
> & {
readonly disableExistingContentSelect?: boolean;
readonly validPostFilter?: PostSearcherProps[ 'filter' ];
};
export const Original = < T extends string >( {
attributes,
setAttributes,
disableExistingContentSelect,
validPostFilter,
experimentType,
}: OriginalProps< T > ): JSX.Element => {
const isSubscribed = !! useSubscription();
const isPaused = useIsPaused();
const toggleExistingContent = useExistingContentToggler( setAttributes );
const { postTypes, showSinglePostType, isLoadingPostTypes } =
usePostTypes( experimentType );
const defaultPostType = postTypes[ 0 ]?.name;
const postType = attributes.postType || defaultPostType;
const selectablePostTypes = postTypes.map( ( type ) => ( {
value: type.name,
label: type.labels.singular_name,
} ) );
return (
{ ! disableExistingContentSelect && (
<>
{ !! attributes.testAgainstExistingContent && (
setAttributes( { useControlUrl } )
}
/>
) }
>
) }
);
};
// =====
// HOOKS
// =====
const useSubscription = () =>
useSelect(
( select ) =>
select( NAB_DATA ).getPluginSetting( 'subscription' ) || false,
[]
);
const useIsPaused = () =>
useSelect(
( select ) =>
`${ select( NAB_EDITOR ).getExperimentAttribute(
'status'
) }`.includes( 'paused' ),
[]
);
const useExistingContentToggler = (
setAttributes: (
props: Partial<
Pick< ControlAttributes, 'testAgainstExistingContent' >
>
) => void
) => {
const [ prevAlts, setPrevAlts ] = useState( [ createAlternative() ] );
const { replaceAlternatives } = useDispatch( NAB_EDITOR );
return ( checked: boolean ) => {
const alts = filter(
doSelect( NAB_EDITOR ).getAlternatives(),
( { id }: Alternative ) => 'control' !== id
);
void replaceAlternatives( map( alts, 'id' ), prevAlts );
setPrevAlts( alts );
setAttributes( {
testAgainstExistingContent: checked ? true : undefined,
...( ! checked ? { useControlUrl: undefined } : {} ),
} );
};
};
// =======
// HELPERS
// =======
function getExistingContentLabel(
type: Maybe< string >,
isSubscribed: boolean
): string {
switch ( type ) {
case 'page':
return isSubscribed
? _x(
'Test against already existing pages',
'command',
'nelio-ab-testing'
)
: _x(
'Test against an already existing page',
'command',
'nelio-ab-testing'
);
case 'post':
return isSubscribed
? _x(
'Test against already existing posts',
'command',
'nelio-ab-testing'
)
: _x(
'Test against an already existing post',
'command',
'nelio-ab-testing'
);
default:
return _x(
'Test against already existing content',
'command',
'nelio-ab-testing'
);
}
}
function getPlaceholder(
postTypes: ReadonlyArray< EntityKind >,
isLoading: boolean
): Maybe< string > {
if ( isLoading ) {
return _x(
'Loading compatible post types…',
'text',
'nelio-ab-testing'
);
}
if ( isEmpty( postTypes ) ) {
return _x(
'There are no compatible post types to select.',
'text',
'nelio-ab-testing'
);
}
if ( postTypes?.length > 1 ) {
return _x(
'First select the post type and then the actual content…',
'user',
'nelio-ab-testing'
);
}
return undefined;
}