Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HOLD] feat(popups): default segments UI #1524

Closed
wants to merge 9 commits into from
4 changes: 3 additions & 1 deletion assets/components/src/card/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ class Card extends Component {
buttonsCard,
className,
headerActions,
isNarrow,
isLarge,
isMedium,
isNarrow,
isSmall,
isWhite,
noBorder,
Expand All @@ -38,6 +39,7 @@ class Card extends Component {
className,
buttonsCard && 'newspack-card__buttons-card',
headerActions && 'newspack-card__header-actions',
isLarge && 'newspack-card__is-large',
isMedium && 'newspack-card__is-medium',
isNarrow && 'newspack-card__is-narrow',
isSmall && 'newspack-card__is-small',
Expand Down
20 changes: 20 additions & 0 deletions assets/components/src/card/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
margin-bottom: 0 !important;
margin-top: 0 !important;
}

.newspack-card__buttons-card {
margin-bottom: -16px !important;
}
}

// Is Narrow
Expand Down Expand Up @@ -90,6 +94,22 @@
}
}

// Is Large

&__is-large {
@media screen and ( min-width: 744px ) {
padding: 96px;

> *:first-child {
margin-top: 0 !important;
}

> *:last-child {
margin-bottom: 0 !important;
}
}
}

// Is White

&__is-white {
Expand Down
16 changes: 16 additions & 0 deletions assets/wizards/popups/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,21 @@ class PopupsWizard extends Component {
inFlight: false,
};
}

componentDidMount = () => {
const { setError } = this.props;
const { is_api_configured: isApiConfigured } = window.newspack_popups_wizard_data || {};

if ( ! isApiConfigured ) {
setError( {
message: __(
'Missing the required config file. Please create it to access this feature.',
'newspack'
),
} );
}
};

onWizardReady = () => {
this.refetch( { isInitial: true } );
};
Expand Down Expand Up @@ -264,6 +279,7 @@ class PopupsWizard extends Component {
duplicated,
promptsAnalyticsData,
} = this.state;

return (
<WebPreview
url={ previewUrl }
Expand Down
200 changes: 157 additions & 43 deletions assets/wizards/popups/views/segments/SegmentsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@
* WordPress dependencies.
*/
import { useEffect, useRef, useState, Fragment } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';
import { Draggable, MenuItem } from '@wordpress/components';
import { ESCAPE } from '@wordpress/keycodes';
import { Icon, chevronDown, chevronUp, dragHandle, moreVertical } from '@wordpress/icons';

/**
* Internal dependencies.
*/
import { ActionCard, Button, Card, Notice, Popover, Router } from '../../../../components/src';
import {
ActionCard,
Button,
Card,
Modal,
Notice,
Popover,
Router,
} from '../../../../components/src';
import { descriptionForSegment, getFavoriteCategoryNames } from '../../utils';

const { NavLink, useHistory } = Router;
Expand All @@ -23,6 +31,16 @@ const AddNewSegmentLink = () => (
</NavLink>
);

const GenerateDefaultSegmentsLink = ( { defaultsCreated, onClick } ) => (
<Button isSecondary isSmall onClick={ onClick }>
{ sprintf(
// Translators: button label for generating or resetting the default segments.
__( '%s Default Segments', 'newspack' ),
defaultsCreated ? __( 'Reset', 'newspack' ) : __( 'Generate', 'newspack' )
) }
</Button>
);

const SegmentActionCard = ( {
inFlight,
segment,
Expand Down Expand Up @@ -255,9 +273,33 @@ const SegmentActionCard = ( {
const SegmentsList = ( { wizardApiFetch, segments, setSegments, isLoading } ) => {
const [ dropTargetIndex, setDropTargetIndex ] = useState( null );
const [ sortedSegments, setSortedSegments ] = useState( null );
const [ showDefaultModal, setShowDefaultModal ] = useState( false );
const [ defaultsCreated, setDefaultsCreated ] = useState( false );
const [ inFlight, setInFlight ] = useState( false );
const [ error, setError ] = useState( null );
const ref = useRef();
const { default_segments: defaultSegments } = window.newspack_popups_wizard_data || {};

useEffect( () => {
if ( ! defaultSegments ) {
setInFlight( true );
wizardApiFetch( {
path: '/newspack/v1/wizard/newspack-popups-wizard/segmentation-defaults',
} )
.then( _defaultSegments => {
if ( _defaultSegments ) {
setDefaultsCreated( true );
}
} )
.catch( e => {
setError( e.message || __( 'Error getting default segments. Please try again.' ) );
} )
.finally( () => {
setInFlight( false );
} );
}
}, [] );

const deleteSegment = segment => {
setInFlight( true );
setError( null );
Expand Down Expand Up @@ -296,6 +338,26 @@ const SegmentsList = ( { wizardApiFetch, segments, setSegments, isLoading } ) =>
setSegments( segments );
} );
};
const generateDefaultSegments = () => {
setInFlight( true );
setError( null );
wizardApiFetch( {
path: '/newspack/v1/wizard/newspack-popups-wizard/segmentation-defaults',
method: 'POST',
quiet: true,
} )
.then( _segments => {
setSegments( _segments );
setDefaultsCreated( true );
} )
adekbadek marked this conversation as resolved.
Show resolved Hide resolved
.catch( e => {
setError( e.message || __( 'Error creating default segments. Please try again.' ) );
} )
.finally( () => {
setInFlight( false );
setShowDefaultModal( false );
} );
};

if ( segments === null ) {
return null;
Expand All @@ -304,47 +366,99 @@ const SegmentsList = ( { wizardApiFetch, segments, setSegments, isLoading } ) =>
// Optimistically update the order of the list while the sort request is pending.
const segmentsToShow = sortedSegments || segments;

return segments.length ? (
<Fragment>
{ error && <Notice noticeText={ error } isError /> }
<Card headerActions noBorder>
<h2>{ __( 'Audience segments', 'newspack' ) }</h2>
<AddNewSegmentLink />
</Card>
<div
className={ 'newspack-campaigns-wizard-segments__list' + ( inFlight ? ' is-loading' : '' ) }
ref={ ref }
>
{ segmentsToShow.map( ( segment, index ) => (
<SegmentActionCard
deleteSegment={ deleteSegment }
key={ segment.id }
inFlight={ inFlight || isLoading > 0 }
segment={ segment }
segments={ segments }
sortSegments={ sortSegments }
index={ index }
wrapperRef={ ref }
dropTargetIndex={ dropTargetIndex }
setDropTargetIndex={ setDropTargetIndex }
totalSegments={ segments.length }
/>
) ) }
</div>
</Fragment>
) : (
<Fragment>
<Card headerActions noBorder>
<h2>{ __( 'You have no saved audience segments.', 'newspack' ) }</h2>
<AddNewSegmentLink />
</Card>
<p>
{ __(
'Create audience segments to target visitors by engagement, activity, and more.',
'newspack'
) }
</p>
</Fragment>
return (
<>
{ segments.length ? (
<>
{ error && <Notice noticeText={ error } isError /> }
<Card headerActions noBorder>
<h2>{ __( 'Audience Segments', 'newspack' ) }</h2>
<Card noBorder buttonsCard>
<GenerateDefaultSegmentsLink
defaultsCreated={ defaultSegments || defaultsCreated }
onClick={ () => setShowDefaultModal( true ) }
/>
<AddNewSegmentLink />
</Card>
</Card>
<div
className={
'newspack-campaigns-wizard-segments__list' + ( inFlight ? ' is-loading' : '' )
}
ref={ ref }
>
{ segmentsToShow.map( ( segment, index ) => (
<SegmentActionCard
deleteSegment={ deleteSegment }
key={ segment.id }
inFlight={ inFlight || isLoading > 0 }
segment={ segment }
segments={ segments }
sortSegments={ sortSegments }
index={ index }
wrapperRef={ ref }
dropTargetIndex={ dropTargetIndex }
setDropTargetIndex={ setDropTargetIndex }
totalSegments={ segments.length }
/>
) ) }
</div>
</>
) : (
<>
<Card isLarge>
<Card noBorder isNarrow className="tc">
<h2>{ __( 'Ready to create your first segment?', 'newspack' ) }</h2>
<p>
{ __(
'Target specific groups of readers based on their interactions with your site. Audience segments allow you to target readers by engagement, activity, and more.',
'newspack'
) }
</p>
<Card noBorder buttonsCard className="justify-center">
<AddNewSegmentLink />
<GenerateDefaultSegmentsLink
defaultsCreated={ defaultSegments || defaultsCreated }
onClick={ () => setShowDefaultModal( true ) }
/>
</Card>
</Card>
</Card>
</>
) }
{ showDefaultModal && (
<Modal
title={ __( 'Default Segments', 'newspack' ) }
onRequestClose={ () => setShowDefaultModal( false ) }
isNarrow
>
<p>
{ sprintf(
// Translators: help message before generating default segments.
__(
'This will %1$s set of default segments that represent a basic engagement funnel.%2$s',
'newspack'
),
defaultSegments ? __( 'regenerate the', 'newspack' ) : __( 'generate a', 'newspack' ),
defaultSegments
? __(
' Any changes you’ve made to the default segments will be ovewritten.',
'newspack'
)
: ''
) }
</p>
<Card buttonsCard noBorder className="justify-end">
<Button isSecondary isSmall onClick={ () => setShowDefaultModal( false ) }>
{ __( 'Cancel', 'newspack' ) }
</Button>
<Button isPrimary isSmall onClick={ () => generateDefaultSegments() }>
{ __( 'Continue', 'newspack' ) }
</Button>
</Card>
</Modal>
) }
</>
);
};

Expand Down
1 change: 0 additions & 1 deletion assets/wizards/popups/views/segments/SingleSegment.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ const SingleSegment = ( { segmentId, setSegments, wizardApiFetch } ) => {
const history = useHistory();

const [ segmentInitially, setSegmentInitially ] = useState( null );

const isSegmentValid =
name.length > 0 && JSON.stringify( segmentConfig ) !== JSON.stringify( DEFAULT_CONFIG ); // Segment has a name. // Segment differs from the default config.

Expand Down
13 changes: 10 additions & 3 deletions assets/wizards/popups/views/segments/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,22 @@
margin: 16px 0;

&.is-dragging {
display: none;
.newspack-card {
border-color: $gray-100;
background: $gray-100;

> * {
visibility: hidden;
}
}
}

&.is-drop-target::before,
&.drop-target-after::after {
background-color: $primary-500;
content: '';
display: block;
height: 2px;
height: 4px;
margin-bottom: 16px;
margin-top: 16px;
width: 100%;
Expand Down Expand Up @@ -113,9 +120,9 @@
}

.newspack-action-card__region-top {
padding: 8px 16px 8px 0 !important;
flex: 1;
order: 2;
padding: 8px 16px 8px 0 !important;
}
}
}
Expand Down
Loading