diff --git a/packages/components/src/card-settings-group/index.tsx b/packages/components/src/card-settings-group/index.tsx
index 375f6d3501..14a650f47b 100644
--- a/packages/components/src/card-settings-group/index.tsx
+++ b/packages/components/src/card-settings-group/index.tsx
@@ -12,6 +12,7 @@ const CardSettingsGroup = ( {
actionType = 'none',
children,
icon = null,
+ headerAction,
title = '',
description = '',
isActive = false,
@@ -21,6 +22,16 @@ const CardSettingsGroup = ( {
children?: React.ReactNode;
icon?: React.ReactNode;
title: string;
+ headerAction?: {
+ label: string;
+ icon?: React.ReactNode;
+ href?: string;
+ onClick?: () => void;
+ disabled?: boolean;
+ destructive?: boolean;
+ tone?: 'primary' | 'secondary' | 'tertiary' | 'link';
+ variant?: 'primary' | 'secondary' | 'tertiary' | 'link';
+ };
description?: string;
isActive?: boolean;
onEnable?: () => void;
@@ -38,7 +49,8 @@ const CardSettingsGroup = ( {
{ description &&
{ description }
}
>
),
- onHeaderClick: onEnable,
+ headerAction,
+ onToggle: onEnable,
icon,
iconBackgroundColor: true,
isActive,
diff --git a/packages/components/src/card/core-card.js b/packages/components/src/card/core-card.js
index 7ccbeb3413..4acbdbce62 100644
--- a/packages/components/src/card/core-card.js
+++ b/packages/components/src/card/core-card.js
@@ -7,7 +7,7 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { Button, Card as CardWrapper, CardHeader, CardFooter, DropdownMenu, MenuItem, ToggleControl } from '@wordpress/components';
+import { Button, Card as CardWrapper, CardHeader, CardFooter, DropdownMenu, MenuGroup, MenuItem, ToggleControl } from '@wordpress/components';
import { Icon, chevronDown, chevronRight, chevronUp, dragHandle, moreVertical } from '@wordpress/icons';
/**
@@ -28,6 +28,7 @@ const CoreCard = ( {
className,
footer,
header,
+ headerAction,
headerStyle,
childrenStyle,
footerStyle,
@@ -140,20 +141,58 @@ const CoreCard = ( {
{ actions?.length > 0 && (
{ () =>
- actions.map( ( action, index ) => (
-
- ) )
+ actions.map( ( action, index ) => {
+ // Actions can be an array of sub-actions, which are rendered within a MenuGroup.
+ if ( Array.isArray( action ) ) {
+ return (
+
+ { action.map( ( subAction, i ) => {
+ return (
+
+ );
+ } ) }
+
+ );
+ }
+ return (
+
+ );
+ } )
}
) }
+ { headerAction && (
+
+ ) }
) }
{ children && (
diff --git a/packages/components/src/card/style-core.scss b/packages/components/src/card/style-core.scss
index 47aad36865..641b8513eb 100644
--- a/packages/components/src/card/style-core.scss
+++ b/packages/components/src/card/style-core.scss
@@ -52,6 +52,7 @@
}
&__header {
color: wp-colors.$gray-700;
+ flex-wrap: wrap;
position: relative;
.newspack-card--core__action {
margin: 0;
@@ -79,6 +80,11 @@
right: 0;
top: 0;
}
+ &__action {
+ background-color: wp-colors.$white;
+ flex: 1 100%;
+ justify-content: center !important;
+ }
}
&__header--is-draggable {
padding-left: 80px !important;
@@ -161,7 +167,7 @@
&__is-active:not(.newspack-card--core__is-draggable) {
border-color: var(--wp-admin-theme-color);
box-shadow: var(--wp-admin-theme-color) 0 0 0 1px;
- button.newspack-card--core__header {
+ .newspack-card--core__header {
background-color: rgba( var(--wp-admin-theme-color--rgb), 0.04 );
color: var(--wp-admin-theme-color);
h1,
@@ -178,7 +184,7 @@
}
&.newspack-card--core__has-children {
- button.newspack-card--core__header {
+ .newspack-card--core__header {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
@@ -214,7 +220,7 @@
}
}
&.is-destructive {
- button.newspack-card--core__header {
+ .newspack-card--core__header {
h1,
h2,
h3,
diff --git a/src/wizards/audience/views/content-gates/content-gate-settings.tsx b/src/wizards/audience/views/content-gates/content-gate-settings.tsx
index d618b27697..c8f72c836a 100644
--- a/src/wizards/audience/views/content-gates/content-gate-settings.tsx
+++ b/src/wizards/audience/views/content-gates/content-gate-settings.tsx
@@ -9,7 +9,7 @@ import { createInterpolateElement, useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
-import { Badge, Button, Card, Grid, Router, useConfirmDialog } from '../../../../../packages/components/src';
+import { Badge, Card, Grid, Router, useConfirmDialog } from '../../../../../packages/components/src';
import { useWizardData } from '../../../../../packages/components/src/wizard/store/utils';
import { useWizardApiFetch } from '../../../hooks/use-wizard-api-fetch';
import { WIZARD_STORE_NAMESPACE } from '../../../../../packages/components/src/wizard/store';
@@ -118,6 +118,46 @@ export default function ContentGateSettings( {
);
};
+ const actions = [
+ [
+ {
+ label: __( 'Edit', 'newspack-plugin' ),
+ action: () => history.push( `/edit/${ gate.id }` ),
+ disabled: isFetching,
+ },
+ {
+ label: gate.status !== 'publish' ? __( 'Activate', 'newspack-plugin' ) : __( 'Deactivate', 'newspack-plugin' ),
+ action: () => updateStatus.current?.( gate.status === 'publish' ? 'draft' : 'publish' ),
+ disabled: isFetching,
+ },
+ {
+ label: __( 'Delete', 'newspack-plugin' ),
+ action: () => requestDelete( handleDelete ),
+ disabled: isFetching,
+ destructive: true,
+ },
+ ],
+ ];
+ const hasRegistrationLayout = ! isNewsletter && gate.registration?.active && gate.registration.gate_layout_id;
+ const hasCustomAccessLayout =
+ ! isNewsletter && gate.custom_access?.active && gate.custom_access.access_rules?.length > 0 && gate.custom_access.gate_layout_id;
+ const layoutOptions: { label: string; action?: () => void; href?: string }[] = [];
+ if ( hasRegistrationLayout ) {
+ layoutOptions.push( {
+ label: __( 'Edit registered access layout', 'newspack-plugin' ),
+ href: getEditGateLayoutUrl( gate.id, 'registration' ),
+ } );
+ }
+ if ( hasCustomAccessLayout ) {
+ layoutOptions.push( {
+ label: __( 'Edit paid access layout', 'newspack-plugin' ),
+ href: getEditGateLayoutUrl( gate.id, 'custom_access' ),
+ } );
+ }
+ if ( layoutOptions.length > 0 ) {
+ actions.push( layoutOptions );
+ }
+
return (
<>
{ deleteDialog }
@@ -137,24 +177,7 @@ export default function ContentGateSettings( {
>
),
- actions: [
- {
- label: __( 'Edit', 'newspack-plugin' ),
- action: () => history.push( `/edit/${ gate.id }` ),
- disabled: isFetching,
- },
- {
- label: gate.status !== 'publish' ? __( 'Activate', 'newspack-plugin' ) : __( 'Deactivate', 'newspack-plugin' ),
- action: () => updateStatus.current?.( gate.status === 'publish' ? 'draft' : 'publish' ),
- disabled: isFetching,
- },
- {
- label: __( 'Delete', 'newspack-plugin' ),
- action: () => requestDelete( handleDelete ),
- disabled: isFetching,
- destructive: true,
- },
- ],
+ actions,
} }
>
@@ -198,11 +221,6 @@ export default function ContentGateSettings( {
) }
{ ! gate.registration?.active && { __( 'N/A', 'newspack-plugin' ) }
}
- { gate.registration?.active && gate.registration.gate_layout_id && (
-
- ) }
) }
@@ -242,14 +260,6 @@ export default function ContentGateSettings( {
{ ( ! gate.custom_access?.active || gate.custom_access.access_rules?.length === 0 ) && (
{ __( 'N/A', 'newspack-plugin' ) }
) }
- { gate.custom_access?.active &&
- gate.custom_access.access_rules?.length > 0 &&
- gate.custom_access.gate_layout_id &&
- ! isNewsletter && (
-
- ) }
diff --git a/src/wizards/audience/views/content-gates/edit/custom-access.tsx b/src/wizards/audience/views/content-gates/edit/custom-access.tsx
index 2564f99157..a4852f6894 100644
--- a/src/wizards/audience/views/content-gates/edit/custom-access.tsx
+++ b/src/wizards/audience/views/content-gates/edit/custom-access.tsx
@@ -42,15 +42,15 @@ export default function CustomAccess( { customAccess, onChange, isNewsletter = f
return (
<>
-
{ ! isNewsletter && (
<>
-
handleChange( { metering } ) } />
+
>
) }
+
>
);
}
diff --git a/src/wizards/audience/views/content-gates/edit/index.tsx b/src/wizards/audience/views/content-gates/edit/index.tsx
index 2c95e60fde..e9c1be77cc 100644
--- a/src/wizards/audience/views/content-gates/edit/index.tsx
+++ b/src/wizards/audience/views/content-gates/edit/index.tsx
@@ -9,7 +9,7 @@ import { __, sprintf } from '@wordpress/i18n';
import { __experimentalVStack as VStack } from '@wordpress/components'; // eslint-disable-line @wordpress/no-unsafe-wp-apis
import { useDispatch } from '@wordpress/data';
import { createInterpolateElement, useCallback, useEffect, useRef, useState } from '@wordpress/element';
-import { commentAuthorAvatar, currencyDollar, envelope, postList, settings } from '@wordpress/icons';
+import { commentAuthorAvatar, currencyDollar, envelope, pencil, postList, settings } from '@wordpress/icons';
/**
* Internal dependencies
@@ -22,7 +22,7 @@ import { useWizardApiFetch } from '../../../../hooks/use-wizard-api-fetch';
import ContentRules from './content-rules';
import Registration from './registration';
import CustomAccess from './custom-access';
-import { getGateStatus, getGateStatusBadgeLevel } from '../utils';
+import { getEditGateLayoutUrl, getGateStatus, getGateStatusBadgeLevel } from '../utils';
const { useHistory } = Router;
@@ -121,44 +121,51 @@ const Edit = ( { match, updateGatesData, slug = AUDIENCE_CONTENT_GATES_WIZARD_SL
),
} );
- const handleCreate = useCallback( () => {
- if ( isFetching ) {
- return;
- }
- isSaving.current = true;
- resetNotices();
- resetError();
- const _gate = {
- ...gate,
- title,
- content_rules: contentRules,
- registration,
- custom_access: customAccess,
- };
- wizardApiFetch< Gate >(
- {
- path: `/newspack/v1/wizard/${ slug }`,
- method: 'POST',
- data: { gate: _gate },
- },
- {
- onSuccess( data ) {
- updateGatesData( [ ...gatesRef.current, { ...data } ] );
- history.push( `/content-gates` );
- addNotice( {
- // translators: %s is the gate title.
- message: sprintf( __( '"%s" gate created.', 'newspack-plugin' ), title ),
- type: 'success',
- id: 'content-gate-created',
- actions: [ { label: __( 'Edit', 'newspack-plugin' ), url: `#/edit/${ data.id }` } ],
- } );
- },
- onFinally: () => {
- isSaving.current = false;
- },
+ const handleCreate = useCallback(
+ ( redirectToLayout: '' | 'registration' | 'custom_access' = '' ) => {
+ if ( isFetching ) {
+ return;
}
- );
- }, [ gate, contentRules, registration, customAccess, status, title ] );
+ isSaving.current = true;
+ resetNotices();
+ resetError();
+ const _gate = {
+ ...gate,
+ title,
+ content_rules: contentRules,
+ registration,
+ custom_access: customAccess,
+ };
+ wizardApiFetch< Gate >(
+ {
+ path: `/newspack/v1/wizard/${ slug }`,
+ method: 'POST',
+ data: { gate: _gate },
+ },
+ {
+ onSuccess( data ) {
+ updateGatesData( [ ...gatesRef.current, { ...data } ] );
+ if ( redirectToLayout !== '' ) {
+ window.location.assign( getEditGateLayoutUrl( data.id, redirectToLayout ) );
+ } else {
+ history.push( '/content-gates' );
+ }
+ addNotice( {
+ // translators: %s is the gate title.
+ message: sprintf( __( '"%s" gate created.', 'newspack-plugin' ), title ),
+ type: 'success',
+ id: 'content-gate-created',
+ actions: [ { label: __( 'Edit', 'newspack-plugin' ), url: `#/edit/${ data.id }` } ],
+ } );
+ },
+ onFinally: () => {
+ isSaving.current = false;
+ },
+ }
+ );
+ },
+ [ gate, contentRules, registration, customAccess, status, title ]
+ );
const handleSave = useCallback( () => {
if ( isFetching ) {
@@ -550,6 +557,17 @@ const Edit = ( { match, updateGatesData, slug = AUDIENCE_CONTENT_GATES_WIZARD_SL
__( 'Readers must log in to view %s.', 'newspack-plugin' ),
isNewsletter ? __( 'these lists', 'newspack-plugin' ) : __( 'this content', 'newspack-plugin' )
) }
+ headerAction={
+ registration?.active
+ ? {
+ label: __( 'Edit layout', 'newspack-plugin' ),
+ href:
+ ! isNew && registration.gate_layout_id ? getEditGateLayoutUrl( gate.id, 'registration' ) : undefined,
+ onClick: ! isNew && registration.gate_layout_id ? undefined : () => handleCreate( 'registration' ),
+ icon: pencil,
+ }
+ : undefined
+ }
icon={ commentAuthorAvatar }
isActive={ registration?.active }
onEnable={ () => setRegistration( { ...registration, active: ! registration.active } ) }
@@ -564,6 +582,16 @@ const Edit = ( { match, updateGatesData, slug = AUDIENCE_CONTENT_GATES_WIZARD_SL
'Set conditions like subscriptions, domain, and more. Readers must meet at least one condition to gain access.',
'newspack-plugin'
) }
+ headerAction={
+ customAccess?.active
+ ? {
+ label: __( 'Edit layout', 'newspack-plugin' ),
+ href: ! isNew && customAccess.gate_layout_id ? getEditGateLayoutUrl( gate.id, 'custom_access' ) : undefined,
+ onClick: ! isNew && customAccess.gate_layout_id ? undefined : () => handleCreate( 'custom_access' ),
+ icon: pencil,
+ }
+ : undefined
+ }
icon={ currencyDollar }
isActive={ customAccess?.active }
onEnable={ () => setCustomAccess( { ...customAccess, active: ! customAccess.active } ) }
diff --git a/src/wizards/audience/views/content-gates/edit/registration.tsx b/src/wizards/audience/views/content-gates/edit/registration.tsx
index bc96797725..b96b911914 100644
--- a/src/wizards/audience/views/content-gates/edit/registration.tsx
+++ b/src/wizards/audience/views/content-gates/edit/registration.tsx
@@ -32,17 +32,8 @@ export default function Registration( { registration, onChange, isNewsletter = f
);
return (
<>
-
- handleChange( { require_verification: ! registration.require_verification } ) }
- />
-
{ ! isNewsletter && (
<>
-
handleChange( { metering } ) }
/>
+
>
) }
+
+ handleChange( { require_verification: ! registration.require_verification } ) }
+ />
+
>
);
}