Add different sections for welcome screen

[MAILPOET-4536]
This commit is contained in:
David Remer
2022-10-26 14:57:39 +03:00
committed by Jan Jakeš
parent a7bc4e7c70
commit d951ebd351
17 changed files with 370 additions and 39 deletions

View File

@ -0,0 +1,171 @@
:root {
--menu-width: 0;
@media screen and (min-width: 783px) {
--menu-width: 36px;
}
@media screen and (min-width: 961px) {
--menu-width: 160px;
}
}
@mixin full-width {
margin-left: calc(-50vw + var(--menu-width) / 2 + 50%);
padding-left: 104px;
padding-right: 104px;
width: calc(100vw - var(--menu-width));
}
.mailpoet-automation-section {
h2 {
font-size: 23px;
font-weight: 400;
line-height: 32px;
margin: 0;
padding: 0 0 8px;
}
p {
font-size: 14px;
font-weight: 400;
line-height: 22px;
margin: 0;
padding: 0 0 40px;
}
}
.mailpoet-automation-section-hero {
background: #fff;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-top: -20px;
padding: 65px;
@include full-width;
.mailpoet-automation-preheading {
display: block;
font-size: 11px;
letter-spacing: .2px;
line-height: 16px;
margin-bottom: 65px;
text-transform: uppercase;
}
h1 {
font-size: 32px;
font-weight: 400;
line-height: 40px;
}
p {
font-size: 14px;
line-height: 22px;
margin-bottom: 32px;
}
> div {
width: 400px;
}
}
.mailpoet-section-templates {
padding: 48px 84px;
.mailpoet-section-template-list {
display: flex;
justify-content: space-between;
margin-bottom: 40px;
li {
max-width: 336px;
button {
background: #fff;
border: 1px solid #dcdcde;
border-radius: 0;
color: #1d2327;
cursor: pointer;
height: auto;
padding: 24px;
text-align: left;
h3 {
font-size: 16px;
font-weight: 600;
line-height: 24px;
}
}
}
}
.components-button {
display: block;
font-size: 16px;
font-weight: 400;
line-height: 25px;
text-align: center;
text-underline-offset: 5px;
}
}
.mailpoet-section-build-your-own {
background: #fff;
display: flex;
justify-content: space-between;
padding: 64px;
@include full-width;
ol {
list-style: decimal-leading-zero;
margin: 0;
max-width: 373px;
padding: 0;
.mailpoet-section-build-list-button {
background: transparent;
border: 0;
color: #000;
cursor: pointer;
font-size: 16px;
font-weight: 400;
line-height: 24px;
text-align: left;
width: 100%;
}
> li {
border-bottom: 1px solid #dcdcde;
margin-bottom: 16px;
padding-bottom: 16px;
&::marker {
color: #ff5301;
font-size: 16px;
font-weight: 600;
line-height: 24px;
}
p {
display: none;
}
&.open {
p {
display: block;
}
.mailpoet-section-build-list-button {
font-weight: 600;
}
}
&:last-of-type {
border: 0;
}
}
}
}

View File

@ -9,7 +9,7 @@
.mailpoet-option-button-main {
border-radius: 2px 0 0 2px;
margin-right: 2px;
margin-right: 1px;
}
.mailpoet-option-button-opener {
@ -38,4 +38,14 @@
width: 100%;
}
}
.mailpoet-option-button-item {
background: transparent;
border: none;
color: #1d2327;
cursor: pointer;
font-size: 13px;
line-height: 21px;
text-align: left;
}
}

View File

@ -8,6 +8,7 @@
// automation listing
@import './components-automation-listing/sections';
@import './components-automation-listing/listing';
@import './components-automation-listing/header';
@import './components-automation-listing/search';

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,10 +1,8 @@
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { TopBarWithBeamer } from 'common/top_bar/top_bar';
import { plusIcon } from 'common/button/icon/plus';
import { Button, Flex, Popover, SlotFillProvider } from '@wordpress/components';
import { Popover, SlotFillProvider } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { initializeApi, useMutation } from './api';
import { registerTranslations } from './i18n';
import { createStore, storeName } from './listing/store';
@ -12,33 +10,28 @@ import { AutomationListing } from './listing';
import { registerApiErrorHandler } from './listing/api-error-handler';
import { Notices } from './listing/components/notices';
import { WorkflowListingNotices } from './listing/workflow-listing-notices';
import { Onboarding } from './onboarding';
import { BuildYourOwnSection, HeroSection, TemplatesSection } from './sections';
import {
CreateEmptyWorkflowButton,
CreateWorkflowFromTemplateButton,
} from './testing';
import { MailPoet } from '../mailpoet';
function Content(): JSX.Element {
const count = useSelect((select) => select(storeName).getWorkflowCount());
return count > 0 ? <AutomationListing /> : <Onboarding />;
const content = count > 0 ? <AutomationListing /> : <HeroSection />;
return (
<>
{content}
<TemplatesSection />
<BuildYourOwnSection />
</>
);
}
function Workflows(): JSX.Element {
return (
<>
<TopBarWithBeamer />
<Flex className="mailpoet-automation-listing-heading">
<h1 className="wp-heading-inline">{__('Automations', 'mailpoet')}</h1>
<Button
href={MailPoet.urls.automationTemplates}
icon={plusIcon}
variant="primary"
className="mailpoet-add-new-button"
>
{__('New automation', 'mailpoet')}
</Button>
</Flex>
<Notices />
<Content />
</>

View File

@ -1,19 +0,0 @@
import { __ } from '@wordpress/i18n';
export function Onboarding(): JSX.Element {
return (
<div className="mailpoet-automation onboarding">
<img src="" alt="" />
<h1>{__('Scale your business with advanced automations', 'mailpoet')}</h1>
<p>
{__(
'Automated workflow allows you to set up a chain of interactions with your subscribers with less efforts. You control all the flow with a visual scheme and a set of goals. Try it!',
'mailpoet',
)}
</p>
<a href="#" className="button secondary">
{__('Learn more', 'mailpoet')}
</a>
</div>
);
}

View File

@ -0,0 +1,79 @@
import { useState } from 'react';
import { __ } from '@wordpress/i18n';
import { MailPoet } from '../../mailpoet';
export function BuildYourOwnSection(): JSX.Element {
const [itemOpen, setItemOpen] = useState('start-with-a-trigger');
const list: { slug: string; title: string; text: string; image: string }[] = [
{
slug: 'start-with-a-trigger',
title: __('Start with a trigger', 'mailpoet'),
text: __(
'Deliver relevant messages to your customers based on who they are and how they interact with your business.',
'mailpoet',
),
image: `${MailPoet.urls.imageAssets}automations/sections/start-with-a-trigger.png`,
},
{
slug: 'customize-your-workflow',
title: __('Customize your workflow', 'mailpoet'),
text: __(
'Choose steps and create a custom journey to best suit your needs.',
'mailpoet',
),
image: `${MailPoet.urls.imageAssets}automations/sections/customize-your-workflow.png`,
},
{
slug: 'design-your-email',
title: __('Design your email', 'mailpoet'),
text: __(
'Modify one of our pre-made email templates or create your own design.',
'mailpoet',
),
image: `${MailPoet.urls.imageAssets}automations/sections/design-your-email.png`,
},
{
slug: 'start-engaging',
title: __('Start engaging', 'mailpoet'),
text: __(
'Activate the automation and start engaging with your customers as they interact with your business.',
'mailpoet',
),
image: `${MailPoet.urls.imageAssets}automations/sections/start-engaging.png`,
},
];
const selectedItem = list.filter((item) => item.slug === itemOpen)[0];
return (
<section className="mailpoet-automation-section mailpoet-section-build-your-own">
<div>
<h2>{__('Build your own automation workflows', 'mailpoet')}</h2>
<p>
{__(
'Create customized email sequences with our new automation editor.',
'mailpoet',
)}
</p>
<ol>
{list.map((item) => (
<li
key={item.slug}
className={itemOpen === item.slug ? 'open' : ''}
>
<button
type="button"
onClick={() => setItemOpen(item.slug)}
className="mailpoet-section-build-list-button"
>
{item.title}
</button>
<p>{item.text}</p>
</li>
))}
</ol>
</div>
<img src={selectedItem.image} alt={selectedItem.title} />
</section>
);
}

View File

@ -0,0 +1,41 @@
import { __ } from '@wordpress/i18n';
import { Hooks } from '../../hooks';
import { OptionButton } from '../components/option-button';
import { MailPoet } from '../../mailpoet';
export function HeroSection(): JSX.Element {
const buttonActions: JSX.Element[] = Hooks.applyFilters(
'mailpoet.automation.hero.actions',
[],
);
return (
<section className="mailpoet-automation-section mailpoet-automation-section-hero">
<div>
<span className="mailpoet-automation-preheading">
{__('Automations', 'mailpoet')}
</span>
<h1>{__('Better engagement begins with automation', 'mailpoet')}</h1>
<p>
{__(
'Send emails that inform, reward, and engage your audience through powerful segmenting, scheduling, and design tools.',
'mailpoet',
)}
</p>
<OptionButton
variant="primary"
onClick={() => {
window.location.href = MailPoet.urls.automationTemplates;
}}
title={__('Start with a template', 'mailpoet')}
>
{buttonActions}
</OptionButton>
</div>
<img
src={`${MailPoet.urls.imageAssets}automations/sections/hero.png`}
alt={__('Welcome', 'mailpoet')}
/>
</section>
);
}

View File

@ -0,0 +1,3 @@
export { HeroSection } from './hero-section';
export { TemplatesSection } from './templates-section';
export { BuildYourOwnSection } from './build-your-own-section';

View File

@ -0,0 +1,33 @@
import { __ } from '@wordpress/i18n';
import { Button } from '@wordpress/components';
import { MailPoet } from '../../mailpoet';
import { workflowTemplates } from '../templates/config';
import { TemplateListItem } from '../templates/components/template-list-item';
export function TemplatesSection(): JSX.Element {
const templates = workflowTemplates.slice(0, 3);
return (
<section className="mailpoet-automation-section mailpoet-section-templates">
<h2>{__('Start with essentials', 'mailpoet')}</h2>
<p>
{__(
'Choose from our list of pre-made templates and make it your own',
'mailpoet',
)}
</p>
<ul className="mailpoet-section-template-list">
{templates.map((template) => (
<TemplateListItem
key={template.slug}
template={template}
heading="h3"
/>
))}
</ul>
<Button variant="link" href={MailPoet.urls.automationTemplates}>
{__('Browse all templates →', 'mailpoet')}
</Button>
</section>
);
}

View File

@ -8,9 +8,11 @@ import { Notice } from '../../../notices/notice';
type TemplateListItemProps = {
template: WorkflowTemplate;
heading?: 'h2' | 'h3';
};
export function TemplateListItem({
template,
heading,
}: TemplateListItemProps): JSX.Element {
const [createWorkflowFromTemplate, { loading, error, data }] = useMutation(
'workflows/create-from-template',
@ -41,6 +43,7 @@ export function TemplateListItem({
);
}
const headingTag = heading ?? 'h2';
return (
<li className="mailpoet-automation-template-list-item">
{notice}
@ -50,7 +53,9 @@ export function TemplateListItem({
void createWorkflowFromTemplate();
}}
>
<h2>{template.name} </h2>
{headingTag === 'h3' && <h3>{template.name} </h3>}
{headingTag === 'h2' && <h2>{template.name} </h2>}
<p>{template.description}</p>
</Button>
</li>

View File

@ -3,9 +3,11 @@
namespace MailPoet\AdminPages\Pages;
use MailPoet\AdminPages\PageRenderer;
use MailPoet\Automation\Engine\Data\WorkflowTemplate;
use MailPoet\Automation\Engine\Migrations\Migrator;
use MailPoet\Automation\Engine\Storage\WorkflowStorage;
use MailPoet\Form\AssetsController;
use MailPoet\Automation\Engine\Storage\WorkflowTemplateStorage;
use MailPoet\WP\Functions as WPFunctions;
class Automation {
@ -24,18 +26,23 @@ class Automation {
/** @var WorkflowStorage */
private $workflowStorage;
/** @var WorkflowTemplateStorage */
private $templateStorage;
public function __construct(
AssetsController $assetsController,
Migrator $migrator,
PageRenderer $pageRenderer,
WPFunctions $wp,
WorkflowStorage $workflowStorage
WorkflowStorage $workflowStorage,
WorkflowTemplateStorage $templateStorage
) {
$this->assetsController = $assetsController;
$this->migrator = $migrator;
$this->pageRenderer = $pageRenderer;
$this->wp = $wp;
$this->workflowStorage = $workflowStorage;
$this->templateStorage = $templateStorage;
}
public function render() {
@ -50,6 +57,12 @@ class Automation {
'nonce' => $this->wp->wpCreateNonce('wp_rest'),
],
'workflowCount' => $this->workflowStorage->getWorkflowCount(),
'templates' => array_map(
function(WorkflowTemplate $template): array {
return $template->toArray();
},
$this->templateStorage->getTemplates()
),
]);
}
}

View File

@ -10,6 +10,7 @@
<script type="text/javascript">
var mailpoet_automation_api = <%= json_encode(api) %>;
var mailpoet_workflow_count = <%= json_encode(workflowCount) %>;
var mailpoet_automation_templates = <%= json_encode(templates) %>;
</script>
<% endblock %>