Add code to create segment from template
[MAILPOET-5394]
This commit is contained in:
committed by
Aschepikov
parent
41bed445e7
commit
dba4ba4dfc
@ -59,15 +59,30 @@
|
||||
|
||||
.mailpoet-templates-card {
|
||||
align-items: flex-end;
|
||||
border: 1px solid white;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
width: 336px;
|
||||
width: 334px;
|
||||
|
||||
> div {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #fff;
|
||||
border: 1px solid #dcdcde;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, .15);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: #2271b1;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, .15);
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.mailpoet-templates-card-header {
|
||||
@ -83,7 +98,7 @@
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
top: 0;
|
||||
top: -1px;
|
||||
width: 24px;
|
||||
|
||||
svg {
|
||||
@ -91,7 +106,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
a.is-link {
|
||||
button.is-link {
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
|
@ -13,11 +13,15 @@ import { storeName } from './store';
|
||||
export function Editor(): JSX.Element {
|
||||
const match = useRouteMatch<{ id: string }>();
|
||||
|
||||
const { pageLoaded } = useDispatch(storeName);
|
||||
const { pageLoaded, pageUnloaded } = useDispatch(storeName);
|
||||
|
||||
useEffect(() => {
|
||||
void pageLoaded(match.params.id);
|
||||
}, [match.params.id, pageLoaded]);
|
||||
|
||||
return () => {
|
||||
void pageUnloaded();
|
||||
};
|
||||
}, [match.params.id, pageLoaded, pageUnloaded]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -2,8 +2,10 @@ import { ChangeEvent } from 'react';
|
||||
import { select } from '@wordpress/data';
|
||||
import { MailPoet } from 'mailpoet';
|
||||
|
||||
import * as ROUTES from '../../routes';
|
||||
import {
|
||||
Actions,
|
||||
ActionType,
|
||||
AnyFormItem,
|
||||
SetSegmentActionType,
|
||||
SetErrorsActionType,
|
||||
@ -21,6 +23,12 @@ export function setSegment(segment: AnyFormItem): SetSegmentActionType {
|
||||
};
|
||||
}
|
||||
|
||||
function unsetSegment(): ActionType {
|
||||
return {
|
||||
type: Actions.UNSET_SEGMENT,
|
||||
};
|
||||
}
|
||||
|
||||
export function setErrors(errors: string[]): SetErrorsActionType {
|
||||
return {
|
||||
type: Actions.SET_ERRORS,
|
||||
@ -103,6 +111,10 @@ export function* pageLoaded(segmentId?: number | string): Generator<{
|
||||
MailPoet.Modal.loading(false);
|
||||
}
|
||||
|
||||
export function* pageUnloaded() {
|
||||
yield unsetSegment();
|
||||
}
|
||||
|
||||
const messages = {
|
||||
onUpdate: (): void => {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('dynamicSegmentUpdated'));
|
||||
@ -141,3 +153,26 @@ export function* handleSave(segmentId?: number): Generator<{
|
||||
yield setErrors(error as string[]);
|
||||
}
|
||||
}
|
||||
|
||||
export function* createFromTemplate(): Generator<{
|
||||
type: string;
|
||||
segment?: AnyFormItem;
|
||||
}> {
|
||||
MailPoet.Modal.loading(true);
|
||||
const segment = select(storeName).getSegment();
|
||||
yield setErrors([]);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore -- I don't know how to configure typescript to understand this
|
||||
const { error, success } = yield {
|
||||
type: 'SAVE_SEGMENT',
|
||||
segment,
|
||||
};
|
||||
|
||||
if (success) {
|
||||
window.location.href = `admin.php?page=mailpoet-segments#${ROUTES.EDIT_DYNAMIC_SEGMENT}/${segment.id}`;
|
||||
} else {
|
||||
yield setErrors(error as string[]);
|
||||
}
|
||||
|
||||
MailPoet.Modal.loading(false);
|
||||
}
|
||||
|
@ -55,12 +55,13 @@ export async function SAVE_SEGMENT(actionData): Promise<{
|
||||
}> {
|
||||
const segment: AnyFormItem = actionData.segment;
|
||||
try {
|
||||
await MailPoet.Ajax.post({
|
||||
const response = await MailPoet.Ajax.post({
|
||||
api_version: MailPoet.apiVersion,
|
||||
endpoint: 'dynamic_segments',
|
||||
action: 'save',
|
||||
data: segment,
|
||||
});
|
||||
segment.id = response.data.id;
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
|
@ -16,6 +16,13 @@ function setSegment(state: StateType, action: SetSegmentActionType): StateType {
|
||||
};
|
||||
}
|
||||
|
||||
function unsetSegment(state: StateType): StateType {
|
||||
return {
|
||||
...state,
|
||||
segment: { filters: [] },
|
||||
};
|
||||
}
|
||||
|
||||
function setErrors(state: StateType, action: SetErrorsActionType): StateType {
|
||||
return {
|
||||
...state,
|
||||
@ -69,6 +76,8 @@ export const createReducer =
|
||||
switch (action.type) {
|
||||
case Actions.SET_SEGMENT:
|
||||
return setSegment(state, action as SetSegmentActionType);
|
||||
case Actions.UNSET_SEGMENT:
|
||||
return unsetSegment(state);
|
||||
case Actions.SET_ERRORS:
|
||||
return setErrors(state, action as SetErrorsActionType);
|
||||
case Actions.UPDATE_SEGMENT:
|
||||
|
@ -9,8 +9,10 @@ import {
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { starFilled } from '@wordpress/icons';
|
||||
import { Tag } from '@woocommerce/components';
|
||||
import { SegmentTemplate } from 'segments/types';
|
||||
import { Segment, SegmentTemplate } from 'segments/types';
|
||||
import { getCategoryNameBySlug } from 'segments/dynamic/templates/templates';
|
||||
import { useDispatch, useSelect } from '@wordpress/data';
|
||||
import { storeName } from 'segments/dynamic/store';
|
||||
|
||||
type TemplateListItemProps = {
|
||||
template: SegmentTemplate;
|
||||
@ -19,8 +21,36 @@ type TemplateListItemProps = {
|
||||
export function TemplateListItem({
|
||||
template,
|
||||
}: TemplateListItemProps): JSX.Element {
|
||||
const segment: Segment = useSelect(
|
||||
(select) => select(storeName).getSegment(),
|
||||
[],
|
||||
);
|
||||
|
||||
const { updateSegment, createFromTemplate } = useDispatch(storeName);
|
||||
|
||||
function handleSelectTemplate(segmentTemplate: SegmentTemplate): void {
|
||||
segment.name = segmentTemplate.name;
|
||||
segment.description = segmentTemplate.description;
|
||||
segment.filters = segmentTemplate.filters;
|
||||
|
||||
if (segmentTemplate.filtersConnect) {
|
||||
segment.filters_connect = segmentTemplate.filtersConnect;
|
||||
}
|
||||
|
||||
updateSegment({
|
||||
...segment,
|
||||
});
|
||||
createFromTemplate();
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="mailpoet-templates-card">
|
||||
<Card
|
||||
className="mailpoet-templates-card"
|
||||
onClick={(e): void => {
|
||||
e.preventDefault();
|
||||
handleSelectTemplate(template);
|
||||
}}
|
||||
>
|
||||
<CardHeader className="mailpoet-templates-card-header">
|
||||
{template.isEssential && (
|
||||
<Tooltip text={__('Essential segment', 'mailpoet')}>
|
||||
@ -29,9 +59,7 @@ export function TemplateListItem({
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Button variant="link" href="#/">
|
||||
{template.name}
|
||||
</Button>
|
||||
<Button variant="link">{template.name}</Button>
|
||||
</CardHeader>
|
||||
<CardBody className="mailpoet-templates-card-body">
|
||||
<p>{template.description}</p>
|
||||
|
@ -17,6 +17,9 @@ import {
|
||||
templateCategories,
|
||||
} from 'segments/dynamic/templates/templates';
|
||||
import * as ROUTES from 'segments/routes';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { storeName } from 'segments/dynamic/store';
|
||||
import { APIErrorsNotice } from 'notices/api_errors_notice';
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
@ -47,6 +50,11 @@ templateCategories.forEach((category) => {
|
||||
});
|
||||
|
||||
export function SegmentTemplates(): JSX.Element {
|
||||
const errors: string[] = useSelect(
|
||||
(select) => select(storeName).getErrors(),
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mailpoet-templates-container">
|
||||
<HideScreenOptions />
|
||||
@ -79,6 +87,10 @@ export function SegmentTemplates(): JSX.Element {
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
|
||||
{errors.length > 0 && (
|
||||
<APIErrorsNotice errors={errors.map((error) => ({ message: error }))} />
|
||||
)}
|
||||
|
||||
<TabPanel tabs={tabs}>
|
||||
{(tab) => (
|
||||
<div className="mailpoet-templates-card-grid">
|
||||
|
@ -302,6 +302,7 @@ export interface StateType {
|
||||
export enum Actions {
|
||||
SET_SEGMENT = 'SET_SEGMENT',
|
||||
SET_ERRORS = 'SET_ERRORS',
|
||||
UNSET_SEGMENT = 'UNSET_SEGMENT',
|
||||
UPDATE_SEGMENT = 'UPDATE_SEGMENT',
|
||||
UPDATE_SEGMENT_FILTER = 'UPDATE_SEGMENT_FILTER',
|
||||
UPDATE_SUBSCRIBER_COUNT = 'UPDATE_SUBSCRIBER_COUNT',
|
||||
|
Reference in New Issue
Block a user