diff --git a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/overview/index.tsx b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/overview/index.tsx index b7b2f39efb..49e9959dd7 100644 --- a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/overview/index.tsx +++ b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/overview/index.tsx @@ -8,7 +8,7 @@ import { select, useSelect } from '@wordpress/data'; import { MailPoet } from '../../../../../../mailpoet'; import { OverviewSection, storeName } from '../../store'; import { locale } from '../../../../../config'; -import {formattedPrice} from "../../formatter"; +import { formattedPrice } from '../../formatter'; function getEmailPercentage( type: 'opened' | 'clicked', @@ -120,7 +120,9 @@ export function Overview(): JSX.Element | null { key="overview-revenue" label={__('Revenue', 'mailpoet')} delta={getWooCommerceDelta('revenue').toFixed(2) as unknown as number} - value={formattedPrice(overview.data !== undefined ? overview.data.revenue.current : 0)} + value={formattedPrice( + overview.data !== undefined ? overview.data.revenue.current : 0, + )} />, ); } diff --git a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/cell.tsx b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/cell.tsx index 8208d9efbe..bf8f74594e 100644 --- a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/cell.tsx +++ b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/cell.tsx @@ -1,23 +1,37 @@ type CellProps = { - value: number | string | JSX.Element + value: number | string | JSX.Element; subValue?: number | string; badge?: string; badgeType?: string; className?: string; -} -export function Cell({value, subValue, badge, badgeType, className}: CellProps): JSX.Element { - - const badgeElement = badge ? {badge} : null - const mainElement =
+}; +export function Cell({ + value, + subValue, + badge, + badgeType, + className, +}: CellProps): JSX.Element { + const badgeElement = badge ? ( + {badge} + ) : null; + const mainElement = ( +
{badgeElement} {value}
- + ); return (
{mainElement} -

{subValue} 

+

+ {subValue}  +

- ) + ); } diff --git a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/index.tsx b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/index.tsx index e739913b9a..f9d21b4185 100644 --- a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/index.tsx +++ b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/index.tsx @@ -1,10 +1,10 @@ -import {TableCard} from "@woocommerce/components/build"; -import {useSelect} from "@wordpress/data"; -import {EmailStats, OverviewSection, storeName} from "../../../store"; -import {__} from "@wordpress/i18n"; -import {useEffect, useState} from "react"; -import {calculateSummary} from "./summary"; -import {transformEmailsToRows} from "./rows"; +import { useEffect, useState } from 'react'; +import { TableCard } from '@woocommerce/components/build'; +import { useSelect } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { calculateSummary } from './summary'; +import { transformEmailsToRows } from './rows'; +import { EmailStats, OverviewSection, storeName } from '../../../store'; const headers = [ { @@ -14,42 +14,42 @@ const headers = [ { key: 'sent', label: __('Sent', 'mailpoet'), - isLeftAligned:false, - isNumeric: true + isLeftAligned: false, + isNumeric: true, }, { key: 'opened', label: __('Opened', 'mailpoet'), - isLeftAligned:false, - isNumeric: true + isLeftAligned: false, + isNumeric: true, }, { key: 'clicked', label: __('Clicked', 'mailpoet'), - isLeftAligned:false, - isNumeric: true + isLeftAligned: false, + isNumeric: true, }, { key: 'orders', label: __('Orders', 'mailpoet'), - isLeftAligned:false, - isNumeric: true + isLeftAligned: false, + isNumeric: true, }, { key: 'revenue', label: __('Revenue', 'mailpoet'), - isLeftAligned:false, - isNumeric: true + isLeftAligned: false, + isNumeric: true, }, { key: 'unsubscribed', label: __('Unsubscribed', 'mailpoet'), - isLeftAligned:false, - isNumeric: true + isLeftAligned: false, + isNumeric: true, }, { key: 'actions', - label: '' + label: '', }, ]; @@ -58,41 +58,64 @@ export function Emails(): JSX.Element { overview: s(storeName).getSection('overview'), })) as { overview: OverviewSection }; - const [visibleEmails, setVisibleEmails] = useState(undefined); + const [visibleEmails, setVisibleEmails] = useState( + undefined, + ); const [currentPage, setCurrentPage] = useState(1); - const [rowsPerPage, setRowsPerPage] = useState(5); - //const [rowsPerPage, setRowsPerPage] = useState(25); - useEffect( - () => { - setVisibleEmails(overview.data !== undefined ? Object.values(overview.data.emails).splice((currentPage-1)*rowsPerPage, rowsPerPage): undefined) - }, [overview.data] - ) + const [rowsPerPage, setRowsPerPage] = useState(25); + useEffect(() => { + setVisibleEmails( + overview.data !== undefined + ? Object.values(overview.data.emails).splice( + (currentPage - 1) * rowsPerPage, + rowsPerPage, + ) + : undefined, + ); + }, [overview.data, currentPage, rowsPerPage]); - const rows = visibleEmails !== undefined ? transformEmailsToRows(visibleEmails) : []; + const rows = + visibleEmails !== undefined ? transformEmailsToRows(visibleEmails) : []; - const summary = calculateSummary(visibleEmails??[]); - return (param) => { - if (type === 'paged') { - setCurrentPage(param); - setVisibleEmails(overview.data !== undefined ? Object.values(overview.data.emails).splice((param-1)*rowsPerPage, rowsPerPage): undefined) - } else if(type==='per_page') { - setCurrentPage(1); - setRowsPerPage(param); - setVisibleEmails(overview.data !== undefined ? Object.values(overview.data.emails).splice(0, param): undefined) + const summary = calculateSummary(visibleEmails ?? []); + return ( + (param: number) => { + if (type === 'paged') { + setCurrentPage(param); + setVisibleEmails( + overview.data !== undefined + ? Object.values(overview.data.emails).splice( + (param - 1) * rowsPerPage, + rowsPerPage, + ) + : undefined, + ); + } else if (type === 'per_page') { + setCurrentPage(1); + setRowsPerPage(param); + setVisibleEmails( + overview.data !== undefined + ? Object.values(overview.data.emails).splice(0, param) + : undefined, + ); + } + }} + query={{ paged: currentPage, sort: { key: 'email', direction: 'asc' } }} + rows={rows} + headers={headers} + showMenu={false} + rowsPerPage={rowsPerPage} + onRowClick={() => {}} + totalRows={ + overview.data !== undefined + ? Object.values(overview.data.emails).length + : 0 } - } - } - query={ {paged: currentPage, sort: {key: 'email', direction: 'asc'}} } - rows={ rows } - headers={ headers } - showMenu={ false } - rowsPerPage={ rowsPerPage } - onRowClick={ () => {} } - totalRows={ overview.data !== undefined ? Object.values(overview.data.emails).length : 0 } - summary={ summary } - isLoading={ overview.data === undefined } - /> + summary={summary} + isLoading={overview.data === undefined} + /> + ); } diff --git a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/rows.tsx b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/rows.tsx index e019b27244..c3eb04b52c 100644 --- a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/rows.tsx +++ b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/rows.tsx @@ -1,118 +1,170 @@ -import {Tooltip} from "@wordpress/components"; -import {__, sprintf} from "@wordpress/i18n"; -import {EmailStats} from "../../../store"; -import {Actions} from "./actions"; -import {locale} from "../../../../../../config"; -import {Cell} from "./cell"; -import {formattedPrice} from "../../../formatter"; +import { Tooltip } from '@wordpress/components'; +import { __, sprintf } from '@wordpress/i18n'; +import { EmailStats } from '../../../store'; +import { Actions } from './actions'; +import { locale } from '../../../../../../config'; +import { Cell } from './cell'; +import { formattedPrice } from '../../../formatter'; -const percentageFormatter = Intl.NumberFormat(locale.toString(), { style: 'percent', maximumFractionDigits: 2 }); +const percentageFormatter = Intl.NumberFormat(locale.toString(), { + style: 'percent', + maximumFractionDigits: 2, +}); -function calculatePercentage(value: number, base: number, canBeNegative = false) : number { +function calculatePercentage( + value: number, + base: number, + canBeNegative = false, +): number { if (base === 0) { return 0; } const percentage = (value * 100) / base; - return (canBeNegative) ? percentage - 100 : percentage; + return canBeNegative ? percentage - 100 : percentage; } -function percentageBadgeCalculation(percentage:number) : {badge: string, badgeType: string} { +function percentageBadgeCalculation(percentage: number): { + badge: string; + badgeType: string; +} { if (percentage > 3) { - return {badge: __('Excellent', 'mailpoet'), badgeType: 'mailpoet-analytics-badge-success'} + return { + badge: __('Excellent', 'mailpoet'), + badgeType: 'mailpoet-analytics-badge-success', + }; } if (percentage > 1) { - return {badge: __('Good', 'mailpoet'), badgeType: 'mailpoet-analytics-badge-success'} + return { + badge: __('Good', 'mailpoet'), + badgeType: 'mailpoet-analytics-badge-success', + }; } - return {badge: __('Average', 'mailpoet'), badgeType: 'mailpoet-analytics-badge-warning'} + return { + badge: __('Average', 'mailpoet'), + badgeType: 'mailpoet-analytics-badge-warning', + }; } export function transformEmailsToRows(emails: EmailStats[]) { - const openOrders = () => { - const tab: HTMLButtonElement | null = document.querySelector('.mailpoet-analytics-tab-orders'); + const tab: HTMLButtonElement | null = document.querySelector( + '.mailpoet-analytics-tab-orders', + ); tab?.click(); - } + }; return emails.map((email) => { - // Shows the percentage of clicked emails compared to the number of sent emails - const clickedPercentage = calculatePercentage(email.clicked.current, email.sent.current); + const clickedPercentage = calculatePercentage( + email.clicked.current, + email.sent.current, + ); const clickedBadge = percentageBadgeCalculation(clickedPercentage); return [ { - display: , - value: email.name + display: ( + + ), + value: email.name, }, { - display: {email.sent.current}} - subValue={ - // Shows the percentage of sent emails compared to the previous email - percentageFormatter.format(calculatePercentage(email.sent.current, email.sent.previous, true)/100) - } - />, - value: email.sent.current - }, - { - display: , - value: email.opened.current - }, - { - display: 0 ? 'mailpoet-automation-analytics-email-clicked' : '' } - subValue={percentageFormatter.format(clickedPercentage/100)} - badge={email.sent.current > 0 ? clickedBadge.badge : undefined} - badgeType={email.sent.current > 0 ? clickedBadge.badgeType : undefined} - />, - value: email.clicked.current - }, - { - display: - { - e.preventDefault(); - openOrders() - } - }>{ - email.orders.current + display: ( + + + {email.sent.current} + + } - - } - />, - value: email.orders.current + subValue={ + // Shows the percentage of sent emails compared to the previous email + percentageFormatter.format( + calculatePercentage( + email.sent.current, + email.sent.previous, + true, + ) / 100, + ) + } + /> + ), + value: email.sent.current, }, { - display: , - value: email.revenue.current + display: ( + + ), + value: email.opened.current, }, { - display: , - value: email.unsubscribed.current + display: ( + 0 + ? 'mailpoet-automation-analytics-email-clicked' + : '' + } + subValue={percentageFormatter.format(clickedPercentage / 100)} + badge={email.sent.current > 0 ? clickedBadge.badge : undefined} + badgeType={ + email.sent.current > 0 ? clickedBadge.badgeType : undefined + } + /> + ), + value: email.clicked.current, + }, + { + display: ( + + { + e.preventDefault(); + openOrders(); + }} + > + {email.orders.current} + + + } + /> + ), + value: email.orders.current, + }, + { + display: , + value: email.revenue.current, + }, + { + display: , + value: email.unsubscribed.current, }, { display: , - value: null + value: null, }, - ] - }) + ]; + }); } diff --git a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/summary.tsx b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/summary.tsx index 86be4f3393..9e9376e9cb 100644 --- a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/summary.tsx +++ b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/components/tabs/emails/summary.tsx @@ -1,36 +1,64 @@ -import {__} from "@wordpress/i18n"; -import {locale} from "../../../../../../config"; -import {EmailStats} from "../../../store"; -import {formattedPrice} from "../../../formatter"; +import { __ } from '@wordpress/i18n'; +import { locale } from '../../../../../../config'; +import { EmailStats } from '../../../store'; +import { formattedPrice } from '../../../formatter'; -export function calculateSummary(rows:EmailStats[]) { +export function calculateSummary(rows: EmailStats[]) { if (rows.length === 0) { return []; } - const data = rows.reduce((acc, row) => { - acc.sent += row.sent.current; - acc.opened += row.opened.current; - acc.clicked += row.clicked.current; - acc.orders += row.orders.current; - acc.unsubscribed += row.unsubscribed.current; - acc.revenue += row.revenue.current; - return acc; - }, { - sent: 0, - opened: 0, - clicked: 0, - orders: 0, - unsubscribed: 0, - revenue: 0, - }); + const data = rows.reduce( + (acc, row) => { + acc.sent += row.sent.current; + acc.opened += row.opened.current; + acc.clicked += row.clicked.current; + acc.orders += row.orders.current; + acc.unsubscribed += row.unsubscribed.current; + acc.revenue += row.revenue.current; + return acc; + }, + { + sent: 0, + opened: 0, + clicked: 0, + orders: 0, + unsubscribed: 0, + revenue: 0, + }, + ); - const summary = [ - { label: __('sent', 'mailpoet'), value: Intl.NumberFormat(locale.toString(), { notation: 'compact' }).format(data.sent) }, - { label: __('opened', 'mailpoet'), value: Intl.NumberFormat(locale.toString(), { notation: 'compact' }).format(data.opened) }, - { label: __('clicked', 'mailpoet'), value: Intl.NumberFormat(locale.toString(), { notation: 'compact' }).format(data.clicked) }, - { label: __('orders', 'mailpoet'), value: Intl.NumberFormat(locale.toString(), { notation: 'compact' }).format(data.orders) }, + const summary = [ + { + label: __('sent', 'mailpoet'), + value: Intl.NumberFormat(locale.toString(), { + notation: 'compact', + }).format(data.sent), + }, + { + label: __('opened', 'mailpoet'), + value: Intl.NumberFormat(locale.toString(), { + notation: 'compact', + }).format(data.opened), + }, + { + label: __('clicked', 'mailpoet'), + value: Intl.NumberFormat(locale.toString(), { + notation: 'compact', + }).format(data.clicked), + }, + { + label: __('orders', 'mailpoet'), + value: Intl.NumberFormat(locale.toString(), { + notation: 'compact', + }).format(data.orders), + }, { label: __('revenue', 'mailpoet'), value: formattedPrice(data.revenue) }, - { label: __('unsubscribed', 'mailpoet'), value: Intl.NumberFormat(locale.toString(), { notation: 'compact' }).format(data.unsubscribed) }, + { + label: __('unsubscribed', 'mailpoet'), + value: Intl.NumberFormat(locale.toString(), { + notation: 'compact', + }).format(data.unsubscribed), + }, ]; return summary; diff --git a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/formatter/index.tsx b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/formatter/index.tsx index 24df413f08..f759b7ff26 100644 --- a/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/formatter/index.tsx +++ b/mailpoet/assets/js/src/automation/integrations/mailpoet/analytics/formatter/index.tsx @@ -1,7 +1,7 @@ -import CurrencyFactory from "@woocommerce/currency/build"; -import {MailPoet} from "../../../../../mailpoet"; +import CurrencyFactory from '@woocommerce/currency/build'; +import { MailPoet } from '../../../../../mailpoet'; -export function formattedPrice(price: number) : string { +export function formattedPrice(price: number): string { const storeCurrency = CurrencyFactory(MailPoet.WooCommerceStoreConfig); return storeCurrency.formatAmount(price); } diff --git a/mailpoet/assets/js/src/global.d.ts b/mailpoet/assets/js/src/global.d.ts index 5ef1d2166e..3ed9c4862b 100644 --- a/mailpoet/assets/js/src/global.d.ts +++ b/mailpoet/assets/js/src/global.d.ts @@ -82,15 +82,17 @@ declare module '@woocommerce/blocks-checkout' { function registerCheckoutBlock(options: CheckoutBlockOptions): void; } -type WooCommerceStoreConfig = { - precision: number | string | null; - decimalSeparator: string; - thousandSeparator: string; - code: string; - symbol: string; - symbolPosition: 'left' | 'right' | 'left_space' | 'right_space'; - priceFormat?: string; -} | undefined +type WooCommerceStoreConfig = + | { + precision: number | string | null; + decimalSeparator: string; + thousandSeparator: string; + code: string; + symbol: string; + symbolPosition: 'left' | 'right' | 'left_space' | 'right_space'; + priceFormat?: string; + } + | undefined; interface Window { ajaxurl: string;