/** * WordPress dependencies */ import { useDispatch, useSelect } from '@wordpress/data'; import { _x } from '@wordpress/i18n'; /** * External dependencies */ import { trim } from 'lodash'; import { ReusableEntitiesDialog } from '@nab/components'; import { store as NAB_DATA } from '@nab/data'; import type { Segment, ReusableSegment } from '@nab/types'; /** * Internal dependencies */ import { store as NAB_EDITOR } from '../../store'; import { createSegment, isDefined } from '@nab/utils'; import { createSegmentationRule } from '@nab/segmentation-rules'; export const ReusableSegmentDialog = (): JSX.Element | null => { const dialog = useReusableDialog(); const { closeReusableDialog: onClose } = useDispatch( NAB_EDITOR ); const { activeSegment, areThereSegmentationRules, currentSegments, isSaving, reusableSegments, } = useSelect( ( select ) => ( { activeSegment: select( NAB_EDITOR ).getActiveSegment(), areThereSegmentationRules: select( NAB_EDITOR ) .getSegments() .some( ( s ) => !! select( NAB_EDITOR ).getSegmentationRules( s.id ) .length ), currentSegments: select( NAB_EDITOR ).getSegments(), isSaving: select( NAB_DATA ).isSavingReusableEntities(), reusableSegments: select( NAB_DATA ).getReusableSegments(), } ), [] ); const segmentationRules = useSelect( ( select ) => activeSegment?.id ? select( NAB_EDITOR ).getSegmentationRules( activeSegment.id ) : [], [ activeSegment ] ); const { saveReusableSegments } = useDispatch( NAB_DATA ); const { addSegmentationRulesIntoSegment, addSegments, removeSegments, setActiveSegment, } = useDispatch( NAB_EDITOR ); const mustUseReplace = currentSegments.every( ( g ) => ! trim( g.attributes.name ) ) && ! areThereSegmentationRules; if ( 'manage-segments' === dialog ) { return ( mode="manage" labels={ { title: _x( 'Reusable Segments', 'text', 'nelio-ab-testing' ), manageElements: _x( 'Edit or delete the following reusable segments:', 'user', 'nelio-ab-testing' ), replace: mustUseReplace ? _x( 'Import', 'command', 'nelio-ab-testing' ) : undefined, selectMultiple: _x( 'Select one or more reusable segments:', 'user', 'nelio-ab-testing' ), } } items={ reusableSegments } saving={ isSaving } onAdd={ mustUseReplace ? undefined : ( selection ) => { const newSegments = selection.map( segmentify ); void addSegments( newSegments ); newSegments.forEach( ( s ) => void addSegmentationRulesIntoSegment( s.id, s.segmentationRules ) ); if ( newSegments[ 0 ] ) { void setActiveSegment( newSegments[ 0 ].id ); } } } onReplace={ ( selection ) => { void removeSegments( currentSegments.map( ( g ) => g.id ) ); const newSegments = selection.map( segmentify ); void addSegments( newSegments ); if ( newSegments[ 0 ] ) { void setActiveSegment( newSegments[ 0 ].id ); } newSegments.forEach( ( s ) => addSegmentationRulesIntoSegment( s.id, s.segmentationRules ) ); } } onSave={ saveReusableSegments } onClose={ onClose } /> ); } if ( activeSegment && 'save-segment' === dialog ) { return ( mode="save" labels={ { title: _x( 'Reusable Segments', 'text', 'nelio-ab-testing' ), collectionName: _x( 'Reusable Segments', 'text', 'nelio-ab-testing' ), nameField: _x( 'Name', 'text', 'nelio-ab-testing' ), newItemOption: _x( 'New Reusable Segment', 'text', 'nelio-ab-testing' ), } } item={ { ...activeSegment, segmentationRules } } items={ reusableSegments } saving={ isSaving } onSave={ saveReusableSegments } onClose={ onClose } /> ); } return null; }; // ===== // HOOKS // ===== const useReusableDialog = () => useSelect( ( select ) => select( NAB_EDITOR ).getReusableDialog(), [] ); const segmentify = ( rs: ReusableSegment ): Segment => ( { ...createSegment(), attributes: rs.attributes, segmentationRules: rs.segmentationRules .map( ( r ) => { const newRule = createSegmentationRule( r.type ); if ( ! newRule ) { return undefined; } return { ...r, id: newRule.id }; } ) .filter( isDefined ), } );