Merge trunk

This commit is contained in:
Emili Castells Guasch 2025-01-15 12:16:44 +01:00
commit 663e07ea9a
62 changed files with 887 additions and 764 deletions

View file

@ -1,8 +0,0 @@
<svg width="110" height="38" viewBox="0 0 110 38" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_4177_18052" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="110" height="38">
<path d="M0.416626 0.68335H109.583V37.3167H0.416626V0.68335Z" fill="white"/>
</mask>
<g mask="url(#mask0_4177_18052)">
<path d="M109.583 0.68335V28.0417H103.358V0.68335H109.583ZM101.067 9.91668V28.0917H95.5333V26.525C94.8333 27.2083 94.0333 27.725 93.15 28.0917C92.2583 28.475 91.2916 28.675 90.2583 28.675C88.9583 28.675 87.75 28.4333 86.6416 27.95C85.5333 27.4417 84.5666 26.75 83.75 25.8833C82.925 25.0083 82.275 23.9917 81.7916 22.8333C81.3333 21.65 81.1083 20.375 81.1083 19.0167C81.1083 17.6583 81.3333 16.4 81.7916 15.2417C82.275 14.0583 82.925 13.025 83.75 12.15C84.5647 11.2817 85.5489 10.5896 86.6416 10.1167C87.75 9.60835 88.9583 9.35002 90.2583 9.35002C91.2916 9.35002 92.2583 9.54168 93.15 9.93335C94.0416 10.3 94.8416 10.8167 95.5333 11.5V9.93335H101.067V9.91668ZM91.2583 23.1417C92.3916 23.1417 93.3166 22.7583 94.0416 21.975C94.7916 21.2 95.1666 20.2083 95.1666 19C95.1666 17.7917 94.7916 16.7917 94.0416 16.025C93.3166 15.25 92.3833 14.8583 91.2583 14.8583C90.1333 14.8583 89.1833 15.2417 88.4333 16.025C87.7083 16.8 87.35 17.7917 87.35 19C87.35 20.2083 87.7166 21.2083 88.4333 21.975C89.1833 22.75 90.125 23.1417 91.2583 23.1417ZM72.225 0.68335C73.8666 0.68335 75.2666 0.916683 76.425 1.37502C77.5833 1.83335 78.5583 2.47502 79.3583 3.30002C80.175 4.15002 80.8166 5.11668 81.275 6.20835C81.7333 7.30002 81.9583 8.47502 81.9583 9.73335C81.9583 10.9917 81.7333 12.1667 81.275 13.2583C80.8251 14.3399 80.1748 15.3267 79.3583 16.1667C78.5666 16.9917 77.5833 17.6333 76.425 18.0917C75.2666 18.55 73.8666 18.7833 72.225 18.7833H69.225V28.0833H62.8916V0.68335H72.225ZM71.3166 13.15C72.1666 13.15 72.8083 13.0667 73.275 12.8917C73.7583 12.7 74.1583 12.45 74.4666 12.1667C75.1166 11.5583 75.4416 10.75 75.4416 9.73335C75.4416 8.71668 75.1166 7.90835 74.4666 7.30002C74.15 7.00835 73.7583 6.77502 73.275 6.60835C72.8166 6.41668 72.1666 6.31668 71.3166 6.31668H69.2166V13.15H71.3166ZM39.5583 9.91668H46.4333L51.1 18.6333H51.175L55.3333 9.91668H61.7L48.0583 37.3167H41.725L47.95 24.7833L39.5583 9.91668ZM38.3333 9.91668V28.0917H32.8V26.525C32.1 27.2083 31.3 27.725 30.4166 28.0917C29.525 28.475 28.5583 28.675 27.525 28.675C26.225 28.675 25.0166 28.4333 23.9083 27.95C22.8 27.4417 21.8333 26.75 21.0166 25.8833C20.2 25.0083 19.5416 23.9917 19.0583 22.8333C18.6 21.65 18.375 20.375 18.375 19.0167C18.375 17.6583 18.6 16.4 19.0583 15.2417C19.5416 14.0583 20.1916 13.025 21.0166 12.15C21.8298 11.2799 22.8144 10.5875 23.9083 10.1167C25.0166 9.60835 26.225 9.35002 27.525 9.35002C28.5583 9.35002 29.525 9.54168 30.4166 9.93335C31.3083 10.3 32.1083 10.8167 32.8 11.5V9.93335H38.3333V9.91668ZM28.525 23.1417C29.6583 23.1417 30.5833 22.7583 31.3166 21.975C32.0666 21.2 32.4416 20.2083 32.4416 19C32.4416 17.7917 32.0666 16.7917 31.3166 16.025C30.5916 15.25 29.6583 14.8583 28.525 14.8583C27.3916 14.8583 26.45 15.2417 25.7 16.025C24.975 16.8 24.6166 17.7917 24.6166 19C24.6166 20.2083 24.9833 21.2083 25.7 21.975C26.45 22.75 27.3916 23.1417 28.525 23.1417ZM9.74996 0.68335C11.3916 0.68335 12.7916 0.916683 13.95 1.37502C15.1083 1.83335 16.0833 2.47502 16.8833 3.30002C17.7 4.15002 18.3416 5.11668 18.8 6.20835C19.2583 7.30002 19.4833 8.47502 19.4833 9.73335C19.4833 10.9917 19.2583 12.1667 18.8 13.2583C18.3501 14.3399 17.6998 15.3267 16.8833 16.1667C16.0916 16.9917 15.1083 17.6333 13.95 18.0917C12.7916 18.55 11.3916 18.7833 9.74996 18.7833H6.74996V28.0833H0.416626V0.68335H9.74996ZM8.84996 13.15C9.69996 13.15 10.3416 13.0667 10.8083 12.8917C11.2916 12.7 11.6916 12.45 12 12.1667C12.65 11.5583 12.975 10.75 12.975 9.73335C12.975 8.71668 12.65 7.90835 12 7.30002C11.6833 7.00835 11.2916 6.77502 10.8083 6.60835C10.35 6.41668 9.69996 6.31668 8.84996 6.31668H6.74996V13.15H8.84996Z" fill="black"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -54,4 +54,9 @@ $card-vertical-gap: 48px;
--color-gray-200: #{$color-gray-200};
--color-gray-100: #{$color-gray-100};
--color-gradient-dark: #{$color-gradient-dark};
--color-text-title: #{$color-gray-900};
--color-text-main: #{$color-text-text};
--color-text-teriary: #{$color-text-tertiary};
--color-text-description: #{$color-gray-700};
}

View file

@ -0,0 +1,19 @@
@import "./reusable-components/payment-method-item";
@import './reusable-components/accordion-section';
@import './reusable-components/badge-box';
@import './reusable-components/busy-state';
@import './reusable-components/button';
@import './reusable-components/fields';
@import './reusable-components/navigation';
@import './reusable-components/onboarding-header';
@import './reusable-components/payment-method-icons';
@import './reusable-components/select-box';
@import './reusable-components/separator';
@import './reusable-components/settings-block';
@import './reusable-components/settings-card';
@import './reusable-components/settings-toggle-block';
@import './reusable-components/settings-wrapper';
@import './reusable-components/spinner-overlay';
@import './reusable-components/tab-navigation';
@import './reusable-components/title-badge';
@import './reusable-components/welcome-docs';

View file

@ -0,0 +1,176 @@
/*
Styles the `SettingsBlock` and all its derived components.
*/
.ppcp-r-settings-block {
display: flex;
flex-direction: column;
gap: 16px 0;
&.ppcp-r-settings-block__input,
&.ppcp-r-settings-block__select {
gap: 6px 0;
}
.ppcp-r-settings-block__header {
display: flex;
flex-direction: column;
gap: 6px;
&:not(:last-child):not(.ppcp-r-settings-block--accordion__header) {
padding-bottom: 6px;
}
}
.ppcp-r-settings-block__title {
@include font(11, 22, 600);
color: var(--color-text-title);
display: block;
text-transform: uppercase;
.ppcp-r-title-badge {
text-transform: none;
margin-left: 6px;
}
}
.ppcp-r-settings-block__title-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
}
&.ppcp-r-settings-block__feature {
.ppcp-r-settings-block__title {
@include font(13, 20, 600);
color: var(--color-text-main);
text-transform: none;
}
.ppcp-r-settings-block__feature__description {
@include font(13, 20, 400);
color: var(--color-text-description);
}
}
&.ppcp-r-settings-block__toggle {
display: flex;
flex-direction: row;
.ppcp-r-settings-block__title {
@include font(13, 20, 400);
color: var(--color-text-main);
text-transform: none;
}
}
.ppcp-r-settings-block__description {
@include font(13, 20, 400);
margin: 0;
color: var(--color-text-description);
&:not(:last-child) {
padding-bottom: 1em;
}
a {
color: var(--color-blueberry);
}
strong {
color: var(--color-gray-800);
}
}
.ppcp-r-settings-block__supplementary-title-label {
@include font(13, 20, 400);
color: var(--color-text-teriary);
text-transform: none;
margin-left: 5px;
}
+ .ppcp-r-settings-block:not(.no-gap) {
margin-top: 32px;
padding-top: 32px;
border-top: 1px solid var(--color-gray-200);
}
// Types
&--toggle-content {
&.ppcp-r-settings-block--content-visible {
.ppcp-r-settings-block__toggle-content {
transform: rotate(180deg);
}
}
.ppcp-r-settings-block__header {
user-select: none;
&:hover {
cursor: pointer;
}
}
}
&--sandbox-connected {
.ppcp-r-settings-block__content {
margin-top: 24px;
}
.ppcp-r-connection-status__data {
margin-bottom: 20px;
}
}
&--connect-sandbox {
button.components-button {
@include small-button;
}
.ppcp-r__radio-content-additional {
@include vertical-layout-event-gap(24px);
align-items: flex-start;
.ppcp-r-vertical-text-control,
input[type='text'] {
width: 100%;
}
}
}
}
.ppcp-r-settings-block {
&--order-intent,
&--save-payment-methods {
@include vertical-layout-event-gap(24px);
> .ppcp-r-settings-block__content {
@include vertical-layout-event-gap(24px);
}
}
}
.ppcp-r-settings-block--toggle-content {
.ppcp-r-settings-block__content {
margin-top: 32px;
}
}
.ppcp-r-settings-block__button {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 50px;
}
.ppcp-r-settings-block__accordion {
> .ppcp-r-accordion {
width: 100%;
.ppcp-r-accordion__toggler {
width: 100%;
margin: 0;
text-align: unset;
}
}
}

View file

@ -0,0 +1,63 @@
/*
Styles the `SettingsCard` layout component.
This is a 2-column row that displays a title + description on the
left side, and a "card" with settings content on the right side.
*/
.ppcp-r-settings-card {
// -- Theming
--card-width-header: 100%;
--card-width-content: 100%;
--card-gap: 0;
--card-layout: block;
@media screen and (min-width: 960px) {
--card-width-header: 280px;
--card-width-content: 610px;
--card-gap: 48px;
--card-layout: flex;
}
// -- Styling
display: var(--card-layout);
gap: var(--card-gap);
margin: 0 0 var(--card-gap) 0;
.ppcp-r-settings-card__header {
display: var(--card-layout);
width: var(--card-width-header);
flex: 0 0 var(--card-width-header);
gap: 18px;
padding-bottom: 18px;
}
.ppcp-r-settings-card__content-wrapper {
display: flex;
flex-direction: column;
gap: 24px;
}
.ppcp-r-settings-card__content {
flex: 1;
max-width: var(--card-width-content);
border: 1px solid var(--color-gray-200);
border-radius: 4px;
padding: 24px;
}
.ppcp-r-settings-card__title {
@include font(13, 24, 600);
color: var(--color-text-main);
margin: 0 0 4px 0;
display: block;
}
.ppcp-r-settings-card__description {
@include font(13, 20, 400);
color: var(--color-text-teriary);
margin: 0;
}
}

View file

@ -26,60 +26,4 @@
border-bottom: 1px solid $color-gray-200;
}
}
&-settings-card {
@media screen and (min-width: 960px) {
display: flex;
gap: 48px;
}
@media screen and (max-width: 480px) {
padding: 24px;
}
&__content-wrapper {
display: flex;
flex-direction: column;
gap: 24px;
}
&__header {
display: flex;
gap: 18px;
padding-bottom: 18px;
border-bottom: 2px solid $color-gray-700;
margin-bottom: 32px;
@media screen and (min-width: 960px) {
width: 280px;
flex-shrink: 0;
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
}
&__content {
border: 1px solid $color-gray-200;
border-radius: 4px;
padding: 24px;
@media screen and (min-width: 960px) {
flex: 1;
}
}
&__title {
@include font(13, 24, 600);
color: $color-text-text;
margin: 0 0 4px 0;
display: block;
}
&__description {
@include font(13, 20, 400);
color: $color-text-tertiary;
margin: 0;
}
}
}

View file

@ -1,4 +1,6 @@
@import "./settings/block-accordion";
@import './settings/input';
@import './settings/tab-styling';
@import './settings/tab-paylater-configurator';
// Container and Tab Settings
.ppcp-r-tabs.settings,
@ -245,310 +247,3 @@
gap: 48px;
}
// Settings Card and Block Styles
.ppcp-r-settings-card {
margin: 0 0 48px 0;
}
.ppcp-r-settings-card__content {
> .ppcp-r-settings-block {
&:not(:last-child) {
border-bottom: 1px solid $color-divider;
}
}
}
.ppcp-r-settings-block {
display: flex;
flex-direction: column;
gap: 16px 0;
&.ppcp-r-settings-block__input,
&.ppcp-r-settings-block__select {
gap: 6px 0;
}
.ppcp-r-settings-block__header {
display: flex;
flex-direction: column;
gap: 6px;
&:not(:last-child):not(.ppcp-r-settings-block--accordion__header) {
padding-bottom: 6px;
}
}
.ppcp-r-settings-block__title {
@include font(11, 22, 600);
color: $color-gray-900;
display: block;
text-transform: uppercase;
.ppcp-r-title-badge {
text-transform: none;
margin-left: 6px;
}
}
.ppcp-r-settings-block__title-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
}
&.ppcp-r-settings-block__feature {
.ppcp-r-settings-block__title {
@include font(13, 20, 600);
color: $color-text-text;
text-transform: none;
}
.ppcp-r-settings-block__feature__description {
color: $color-gray-700;
@include font(13, 20, 400);
}
}
&.ppcp-r-settings-block__toggle {
display: flex;
flex-direction: row;
.ppcp-r-settings-block__title {
color: $color-text-text;
@include font(13, 20, 400);
text-transform: none;
}
}
.ppcp-r-settings-block__description {
margin: 0;
@include font(13, 20, 400);
color: $color-gray-800;
&:not(:last-child) {
padding-bottom: 1em;
}
a {
color: $color-blueberry;
}
strong {
color: $color-gray-800;
}
}
.ppcp-r-settings-block__supplementary-title-label {
@include font(13, 20, 400);
color: $color-text-tertiary;
text-transform: none;
margin-left: 5px;
}
// Types
&--toggle-content {
&.ppcp-r-settings-block--content-visible {
.ppcp-r-settings-block__toggle-content {
transform: rotate(180deg);
}
}
.ppcp-r-settings-block__header {
user-select: none;
&:hover {
cursor: pointer;
}
}
}
&--sandbox-connected {
.ppcp-r-settings-block__content {
margin-top: 24px;
}
.ppcp-r-connection-status__data {
margin-bottom: 20px;
}
}
&--connect-sandbox {
button.components-button {
@include small-button;
}
.ppcp-r__radio-content-additional {
.ppcp-r-vertical-text-control {
width: 100%;
}
@include vertical-layout-event-gap(24px);
align-items: flex-start;
input[type='text'] {
width: 100%;
}
}
}
&--troubleshooting,
&--settings {
> .ppcp-r-settings-block__content > *:not(:last-child) {
padding-bottom: 32px;
margin-bottom: 32px;
border-bottom: 1px solid $color-gray-500;
}
}
// Fields
input[type='text'] {
border-color: $color-gray-700;
width: 100%;
max-width: 100%;
color: $color-gray-800;
&::placeholder {
color: $color-gray-700;
}
}
// MultiSelect control
.ppcp-r {
&__radio-wrapper {
align-items: flex-start;
gap: 12px;
}
&__radio-content {
display: flex;
flex-direction: column;
gap: 4px;
label {
font-weight: 600;
}
}
&__radio-content-additional {
padding-left: 32px;
}
// Select control styles
&__control {
border-radius: 2px;
border-color: $color-gray-700;
min-height: auto;
padding: 0;
}
&__input-container {
padding: 0;
margin: 0;
}
&__value-container {
padding: 0 0 0 7px;
}
&__indicator {
padding: 5px;
}
&__indicator-separator {
display: none;
}
&__value-container--has-value {
.ppcp-r__single-value {
color: $color-gray-800;
}
}
&__placeholder,
&__single-value {
@include font(13, 20, 400);
}
&__option {
&--is-selected {
background-color: $color-gray-200;
}
}
}
}
// Hooks table
.ppcp-r-table {
&__hooks-url {
width: 70%;
padding-right: 20%;
text-align: left;
vertical-align: top;
}
&__hooks-events {
vertical-align: top;
text-align: left;
width: 40%;
span {
display: block;
}
}
td.ppcp-r-table__hooks-url,
td.ppcp-r-table__hooks-events {
padding-top: 12px;
color: $color-gray-800;
@include font(14, 20, 400);
span {
color: inherit;
@include font(14, 20, 400);
}
}
th.ppcp-r-table__hooks-url,
th.ppcp-r-table__hooks-events {
@include font(14, 20, 700);
color: $color-gray-800;
border-bottom: 1px solid $color-gray-600;
padding-bottom: 4px;
}
}
// Settings specific styles
.ppcp-r-settings-card--common-settings .ppcp-r-settings-card__content,
.ppcp-r-settings-card--expert-settings .ppcp-r-settings-card__content {
> .ppcp-r-settings-block {
&:not(:last-child) {
padding-bottom: 32px;
margin-bottom: 32px;
}
}
}
.ppcp-r-settings-block {
&--order-intent,
&--save-payment-methods {
@include vertical-layout-event-gap(24px);
> .ppcp-r-settings-block__content {
@include vertical-layout-event-gap(24px);
}
}
}
.ppcp-r-settings-block--toggle-content {
.ppcp-r-settings-block__content {
margin-top: 32px;
}
}
.ppcp-r-settings-block__button {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 50px;
}

View file

@ -1,38 +0,0 @@
.ppcp-r-settings-block__accordion {
> .ppcp-r-accordion {
width: 100%;
.ppcp-r-accordion__toggler {
width: 100%;
margin: 0;
text-align: unset;
}
}
&.ppcp-r-settings-block {
gap: 0;
.ppcp-r-settings-block__title {
@include font(13, 20, 600);
color: $color-text-text;
text-transform: none;
}
.ppcp-r-settings-block--accordion__title {
@include font(14, 20, 600);
}
.ppcp-r-settings-block--accordion__description {
color: $color-gray-700;
@include font(13, 20, 400);
}
.ppcp-r-settings-block:not(:last-child) {
&:not(.ppcp-r__radio-content-additional .ppcp-r-settings-block) {
padding-bottom: 32px;
margin-bottom: 32px;
border-bottom: 1px solid $color-divider;
}
}
}
}

View file

@ -0,0 +1,77 @@
// Fields
.ppcp-r {
input[type='text'] {
border-color: $color-gray-700;
width: 100%;
max-width: 100%;
color: $color-gray-800;
&::placeholder {
color: $color-gray-700;
}
}
}
// MultiSelect control
.ppcp-r {
&__radio-wrapper {
align-items: flex-start;
gap: 12px;
}
&__radio-content {
display: flex;
flex-direction: column;
gap: 4px;
label {
font-weight: 600;
}
}
&__radio-content-additional {
padding-left: 32px;
}
// Select control styles
&__control {
border-radius: 2px;
border-color: $color-gray-700;
min-height: auto;
padding: 0;
}
&__input-container {
padding: 0;
margin: 0;
}
&__value-container {
padding: 0 0 0 7px;
}
&__indicator {
padding: 5px;
}
&__indicator-separator {
display: none;
}
&__value-container--has-value {
.ppcp-r__single-value {
color: $color-gray-800;
}
}
&__placeholder,
&__single-value {
@include font(13, 20, 400);
}
&__option {
&--is-selected {
background-color: $color-gray-200;
}
}
}

View file

@ -3,27 +3,9 @@
#ppcp-settings-container {
@import './global';
@import './components/reusable-components/busy-state';
@import './components/reusable-components/button';
@import './components/reusable-components/separator';
@import './components/reusable-components/onboarding-header';
@import './components/reusable-components/settings-toggle-block';
@import './components/reusable-components/payment-method-icons';
@import "./components/reusable-components/payment-method-item";
@import './components/reusable-components/settings-wrapper';
@import './components/reusable-components/select-box';
@import './components/reusable-components/tab-navigation';
@import './components/reusable-components/navigation';
@import './components/reusable-components/fields';
@import './components/reusable-components/title-badge';
@import './components/reusable-components/accordion-section';
@import './components/reusable-components/badge-box';
@import './components/reusable-components/spinner-overlay';
@import './components/reusable-components/welcome-docs';
@import './components/reusable';
@import './components/screens/onboarding';
@import './components/screens/settings';
@import './components/screens/overview/tab-styling';
@import './components/screens/overview/tab-paylater-configurator';
@import './components/app';
}

View file

@ -1,8 +0,0 @@
import Settings from './Components/Screens/Settings';
export function App() {
return (
<div>
<Settings />
</div>
);
}

View file

@ -2,20 +2,18 @@ import { useEffect, useMemo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import classNames from 'classnames';
import { OnboardingHooks } from '../../data';
import SpinnerOverlay from '../ReusableComponents/SpinnerOverlay';
import { OnboardingHooks, CommonHooks } from '../data';
import SpinnerOverlay from './ReusableComponents/SpinnerOverlay';
import SendOnlyMessage from './Screens/SendOnlyMessage';
import OnboardingScreen from './Screens/Onboarding';
import SettingsScreen from './Screens/Settings';
import Onboarding from './Onboarding/Onboarding';
import SettingsScreen from './SettingsScreen';
import { useMerchantInfo } from '../../data/common/hooks';
import SendOnlyMessage from './SendOnlyMessage';
const Settings = () => {
const SettingsApp = () => {
const onboardingProgress = OnboardingHooks.useSteps();
const {
isReady: merchantIsReady,
merchant: { isSendOnlyCountry },
} = useMerchantInfo();
} = CommonHooks.useMerchantInfo();
// Disable the "Changes you made might not be saved" browser warning.
useEffect( () => {
@ -49,7 +47,7 @@ const Settings = () => {
}
if ( ! onboardingProgress.completed ) {
return <Onboarding />;
return <OnboardingScreen />;
}
return <SettingsScreen />;
@ -63,4 +61,4 @@ const Settings = () => {
return <div className={ wrapperClass }>{ Content }</div>;
};
export default Settings;
export default SettingsApp;

View file

@ -1,40 +1,62 @@
import data from '../../utils/data';
const BadgeBox = ( props ) => {
const titleSize =
props.titleType && props.titleType === BADGE_BOX_TITLE_BIG
? BADGE_BOX_TITLE_BIG
: BADGE_BOX_TITLE_SMALL;
const ImageBadge = ( { images } ) => {
if ( ! images || ! images.length ) {
return null;
}
return (
<BadgeContent>
<span className="ppcp-r-badge-box__title-image-badge">
{ images.map( ( badge ) => data().getImage( badge ) ) }
</span>
</BadgeContent>
);
};
// If `children` is not empty, it's output and wrapped in spaces.
const BadgeContent = ( { children } ) => {
if ( ! children ) {
return null;
}
return <> { children } </>;
};
const BadgeBox = ( {
title,
textBadge,
imageBadge = [],
titleType = BADGE_BOX_TITLE_BIG,
description = '',
} ) => {
let titleSize = BADGE_BOX_TITLE_SMALL;
if ( BADGE_BOX_TITLE_BIG === titleType ) {
titleSize = BADGE_BOX_TITLE_BIG;
}
const titleTextClassName =
'ppcp-r-badge-box__title-text ' +
`ppcp-r-badge-box__title-text--${ titleSize }`;
const titleBaseClassName = 'ppcp-r-badge-box__title';
const titleClassName = props.imageBadge
const titleClassName = imageBadge.length
? `${ titleBaseClassName } ppcp-r-badge-box__title--has-image-badge`
: titleBaseClassName;
return (
<div className="ppcp-r-badge-box">
<span className={ titleClassName }>
<span className={ titleTextClassName }>{ props.title }</span>
<span className={ titleTextClassName }>{ title }</span>
{ props.imageBadge && (
<span className="ppcp-r-badge-box__title-image-badge">
{ props.imageBadge.map( ( badge ) =>
data().getImage( badge )
) }
</span>
) }
{ props.textBadge }
<ImageBadge images={ imageBadge } />
<BadgeContent>{ textBadge }</BadgeContent>
</span>
<div className="ppcp-r-badge-box__description">
{ props?.description && (
{ description && (
<p
className="ppcp-r-badge-box__description"
dangerouslySetInnerHTML={ {
__html: props.description,
__html: description,
} }
></p>
) }

View file

@ -1,3 +0,0 @@
export { default as openSignup } from './Icons/open-signup';
export const NOTIFICATION_SUCCESS = '✔️';
export const NOTIFICATION_ERROR = '❌';

View file

@ -0,0 +1,5 @@
export { default as openSignup } from './open-signup';
export { default as logoPayPal } from './logo-paypal';
export const NOTIFICATION_SUCCESS = '✔️';
export const NOTIFICATION_ERROR = '❌';

View file

@ -0,0 +1,12 @@
import { SVG, Path } from '@wordpress/primitives';
const logoPayPal = (
<SVG fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 110 38">
<Path
d="M109.583.683v27.359h-6.225V.683h6.225Zm-8.516 9.234v18.175h-5.534v-1.567c-.7.683-1.5 1.2-2.383 1.567a7.259 7.259 0 0 1-2.892.583c-1.3 0-2.508-.242-3.616-.725a9.216 9.216 0 0 1-2.892-2.067 10.021 10.021 0 0 1-1.958-3.05c-.459-1.183-.684-2.458-.684-3.816 0-1.359.225-2.617.684-3.775.483-1.184 1.133-2.217 1.958-3.092a8.708 8.708 0 0 1 2.892-2.033c1.108-.509 2.316-.767 3.616-.767 1.034 0 2 .192 2.892.583a7.312 7.312 0 0 1 2.383 1.567V9.933h5.534v-.016Zm-9.809 13.225c1.134 0 2.059-.384 2.784-1.167.75-.775 1.125-1.767 1.125-2.975 0-1.208-.375-2.208-1.125-2.975-.725-.775-1.659-1.167-2.784-1.167-1.125 0-2.075.384-2.825 1.167-.725.775-1.083 1.767-1.083 2.975 0 1.208.367 2.208 1.083 2.975.75.775 1.692 1.167 2.825 1.167ZM72.225.683c1.642 0 3.042.234 4.2.692 1.158.458 2.133 1.1 2.933 1.925a9.439 9.439 0 0 1 1.917 2.908c.458 1.092.683 2.267.683 3.525 0 1.259-.225 2.434-.683 3.525a9.293 9.293 0 0 1-1.917 2.909c-.791.825-1.775 1.466-2.933 1.925-1.158.458-2.558.691-4.2.691h-3v9.3h-6.333V.683h9.333Zm-.908 12.467c.85 0 1.491-.083 1.958-.258a3.853 3.853 0 0 0 1.192-.725c.65-.609.975-1.417.975-2.434 0-1.016-.325-1.825-.975-2.433a3.329 3.329 0 0 0-1.192-.692c-.458-.191-1.108-.291-1.958-.291h-2.1v6.833h2.1ZM39.558 9.917h6.875l4.667 8.716h.075l4.158-8.716H61.7l-13.642 27.4h-6.333l6.225-12.534-8.392-14.866Zm-1.225 0v18.175H32.8v-1.567c-.7.683-1.5 1.2-2.383 1.567a7.258 7.258 0 0 1-2.892.583c-1.3 0-2.508-.242-3.617-.725a9.218 9.218 0 0 1-2.891-2.067 10.18 10.18 0 0 1-1.959-3.05c-.458-1.183-.683-2.458-.683-3.816 0-1.359.225-2.617.683-3.775.484-1.184 1.134-2.217 1.959-3.092a8.626 8.626 0 0 1 2.891-2.033c1.109-.509 2.317-.767 3.617-.767 1.033 0 2 .192 2.892.583A7.312 7.312 0 0 1 32.8 11.5V9.933h5.533v-.016Zm-9.808 13.225c1.133 0 2.058-.384 2.792-1.167.75-.775 1.125-1.767 1.125-2.975 0-1.208-.375-2.208-1.125-2.975-.725-.775-1.659-1.167-2.792-1.167-1.133 0-2.075.384-2.825 1.167-.725.775-1.083 1.767-1.083 2.975 0 1.208.366 2.208 1.083 2.975.75.775 1.692 1.167 2.825 1.167ZM9.75.683c1.642 0 3.042.234 4.2.692 1.158.458 2.133 1.1 2.933 1.925A9.439 9.439 0 0 1 18.8 6.208c.458 1.092.683 2.267.683 3.525 0 1.259-.225 2.434-.683 3.525a9.293 9.293 0 0 1-1.917 2.909c-.791.825-1.775 1.466-2.933 1.925-1.158.458-2.558.691-4.2.691h-3v9.3H.417V.683H9.75Zm-.9 12.467c.85 0 1.492-.083 1.958-.258A3.855 3.855 0 0 0 12 12.167c.65-.609.975-1.417.975-2.434 0-1.016-.325-1.825-.975-2.433a3.33 3.33 0 0 0-1.192-.692c-.458-.191-1.108-.291-1.958-.291h-2.1v6.833h2.1Z"
fill="#000"
/>
</SVG>
);
export default logoPayPal;

View file

@ -1,6 +1,3 @@
/**
* WordPress dependencies
*/
import { SVG, Path } from '@wordpress/primitives';
const openSignup = (

View file

@ -1,9 +1,11 @@
const SettingsBlock = ( { className, children } ) => {
const blockClassName = [ 'ppcp-r-settings-block', className ].filter(
Boolean
);
import classNames from 'classnames';
return <div className={ blockClassName.join( ' ' ) }>{ children }</div>;
const SettingsBlock = ( { className, children, separatorAndGap = true } ) => {
const blockClassName = classNames( 'ppcp-r-settings-block', className, {
'no-gap': ! separatorAndGap,
} );
return <div className={ blockClassName }>{ children }</div>;
};
export default SettingsBlock;

View file

@ -1,3 +1,5 @@
import classNames from 'classnames';
import { Content, ContentWrapper } from './SettingsBlocks';
const SettingsCard = ( {
@ -9,9 +11,7 @@ const SettingsCard = ( {
contentItems,
contentContainer = true,
} ) => {
const className = [ 'ppcp-r-settings-card', extraClassName ]
.filter( Boolean )
.join( ' ' );
const className = classNames( 'ppcp-r-settings-card', extraClassName );
const renderContent = () => {
// If contentItems array is provided, wrap each item in Content component

View file

@ -43,9 +43,7 @@ const TabNavigation = ( { tabs } ) => {
onSelect={ updateActivePanel }
tabs={ tabs }
>
{ ( tab ) => {
return tab.component || <>{ tab.title ?? tab.name }</>;
} }
{ ( { Component } ) => Component }
</TabPanel>
);
};

View file

@ -0,0 +1,86 @@
import { useCallback, useLayoutEffect } from '@wordpress/element';
import { Button, Icon } from '@wordpress/components';
import { chevronLeft } from '@wordpress/icons';
import classNames from 'classnames';
import useIsScrolled from '../../hooks/useIsScrolled';
import { useNavigation } from '../../hooks/useNavigation';
import BusyStateWrapper from './BusyStateWrapper';
const TopNavigation = ( {
title,
children,
isMainTitle = true,
exitOnTitleClick = false,
onTitleClick = null,
showProgressBar = false,
progressBarPercent = 0,
} ) => {
const { goToWooCommercePaymentsTab } = useNavigation();
const { isScrolled } = useIsScrolled();
const className = classNames( 'ppcp-r-navigation-container', {
'is-scrolled': isScrolled,
} );
const titleClassName = classNames( 'title', {
big: isMainTitle,
} );
const handleTitleClick = useCallback( () => {
if ( exitOnTitleClick ) {
goToWooCommercePaymentsTab();
} else if ( 'function' === typeof onTitleClick ) {
onTitleClick();
}
}, [ exitOnTitleClick, goToWooCommercePaymentsTab, onTitleClick ] );
// Removes the excess padding at the top of the navigation bar.
useLayoutEffect( () => {
window.dispatchEvent( new Event( 'resize' ) );
}, [] );
return (
<div className={ className }>
<div className="ppcp-r-navigation">
<BusyStateWrapper
className="ppcp-r-navigation--left"
busySpinner={ false }
enabled={ ! exitOnTitleClick }
>
<Button
variant="link"
onClick={ handleTitleClick }
className="is-title"
>
<Icon icon={ chevronLeft } />
<span className={ titleClassName }>{ title }</span>
</Button>
</BusyStateWrapper>
<BusyStateWrapper
className="ppcp-r-navigation--right"
busySpinner={ false }
>
{ children }
</BusyStateWrapper>
{ showProgressBar && (
<ProgressBar percent={ progressBarPercent } />
) }
</div>
</div>
);
};
const ProgressBar = ( { percent } ) => {
percent = Math.min( Math.max( percent, 0 ), 100 );
return (
<div
className="ppcp-r-navigation--progress-bar"
style={ { width: `${ percent }%` } }
/>
);
};
export default TopNavigation;

View file

@ -1,9 +1,11 @@
import { __, sprintf } from '@wordpress/i18n';
import BadgeBox, { BADGE_BOX_TITLE_BIG } from '../BadgeBox';
import Separator from '../Separator';
import OptionalPaymentMethods from '../OptionalPaymentMethods/OptionalPaymentMethods';
import PricingTitleBadge from '../PricingTitleBadge';
import BadgeBox, {
BADGE_BOX_TITLE_BIG,
} from '../../../ReusableComponents/BadgeBox';
import Separator from '../../../ReusableComponents/Separator';
import PricingTitleBadge from '../../../ReusableComponents/PricingTitleBadge';
import OptionalPaymentMethods from './OptionalPaymentMethods';
const AcdcFlow = ( { isFastlane, isPayLater, storeCountry } ) => {
if ( isFastlane && isPayLater && storeCountry === 'US' ) {
@ -53,9 +55,7 @@ const AcdcFlow = ( { isFastlane, isPayLater, storeCountry } ) => {
imageBadge={ [
'icon-payment-method-paypal-small.svg',
] }
textBadge={
<PricingTitleBadge item="plater" />
}
textBadge={ <PricingTitleBadge item="plater" /> }
description={ sprintf(
// translators: %s: Link to PayPal business fees guide
__(
@ -100,8 +100,7 @@ const AcdcFlow = ( { isFastlane, isPayLater, storeCountry } ) => {
) }
titleType={ BADGE_BOX_TITLE_BIG }
description={ __(
'Accept debit/credit cards, PayPal, Apple Pay, Google Pay, and more.\n' +
'Note: Additional application required for more methods',
'Accept debit/credit cards, PayPal, Apple Pay, Google Pay, and more. Note: Additional application required for more methods',
'woocommerce-paypal-payments'
) }
/>
@ -176,13 +175,12 @@ const AcdcFlow = ( { isFastlane, isPayLater, storeCountry } ) => {
<div className="ppcp-r-welcome-docs__col">
<BadgeBox
title={ __(
'Expanded Checkout',
'Optional payment methods',
'woocommerce-paypal-payments'
) }
titleType={ BADGE_BOX_TITLE_BIG }
description={ __(
'Accept debit/credit cards, PayPal, Apple Pay, Google Pay, and more.\n' +
'Note: Additional application required for more methods',
'with additional application',
'woocommerce-paypal-payments'
) }
/>
@ -251,13 +249,12 @@ const AcdcFlow = ( { isFastlane, isPayLater, storeCountry } ) => {
<div className="ppcp-r-welcome-docs__col">
<BadgeBox
title={ __(
'Expanded Checkout',
'Optional payment methods',
'woocommerce-paypal-payments'
) }
titleType={ BADGE_BOX_TITLE_BIG }
description={ __(
'Accept debit/credit cards, PayPal, Apple Pay, Google Pay, and more.\n' +
'Note: Additional application required for more methods',
'with additional application',
'woocommerce-paypal-payments'
) }
/>

View file

@ -1,8 +1,8 @@
import { __, sprintf } from '@wordpress/i18n';
import BadgeBox from '../BadgeBox';
import Separator from '../Separator';
import PricingTitleBadge from '../PricingTitleBadge';
import BadgeBox from '../../../ReusableComponents/BadgeBox';
import Separator from '../../../ReusableComponents/Separator';
import PricingTitleBadge from '../../../ReusableComponents/PricingTitleBadge';
const AcdcOptionalPaymentMethods = ( {
isFastlane,

View file

@ -1,9 +1,11 @@
import { __, sprintf } from '@wordpress/i18n';
import BadgeBox, { BADGE_BOX_TITLE_BIG } from '../BadgeBox';
import Separator from '../Separator';
import OptionalPaymentMethods from '../OptionalPaymentMethods/OptionalPaymentMethods';
import PricingTitleBadge from '../PricingTitleBadge';
import BadgeBox, {
BADGE_BOX_TITLE_BIG,
} from '../../../ReusableComponents/BadgeBox';
import Separator from '../../../ReusableComponents/Separator';
import PricingTitleBadge from '../../../ReusableComponents/PricingTitleBadge';
import OptionalPaymentMethods from './OptionalPaymentMethods';
const BcdcFlow = ( { isPayLater, storeCountry } ) => {
if ( isPayLater && storeCountry === 'US' ) {
@ -97,8 +99,7 @@ const BcdcFlow = ( { isPayLater, storeCountry } ) => {
) }
titleType={ BADGE_BOX_TITLE_BIG }
description={ __(
'Accept debit/credit cards, PayPal, Apple Pay, Google Pay, and more.\n' +
'Note: Additional application required for more methods',
'Accept debit/credit cards, PayPal, Apple Pay, Google Pay, and more. Note: Additional application required for more methods',
'woocommerce-paypal-payments'
) }
/>
@ -159,13 +160,12 @@ const BcdcFlow = ( { isPayLater, storeCountry } ) => {
<Separator className="ppcp-r-page-welcome-mode-separator" />
<BadgeBox
title={ __(
'Expanded Checkout',
'Optional payment methods',
'woocommerce-paypal-payments'
) }
titleType={ BADGE_BOX_TITLE_BIG }
description={ __(
'Accept debit/credit cards, PayPal, Apple Pay, Google Pay, and more.\n' +
'Note: Additional application required for more methods',
'with additional application',
'woocommerce-paypal-payments'
) }
/>

View file

@ -1,7 +1,7 @@
import { __, sprintf } from '@wordpress/i18n';
import BadgeBox from '../BadgeBox';
import PricingTitleBadge from '../PricingTitleBadge';
import BadgeBox from '../../../ReusableComponents/BadgeBox';
import PricingTitleBadge from '../../../ReusableComponents/PricingTitleBadge';
const BcdcOptionalPaymentMethods = ( { isPayLater, storeCountry } ) => {
if ( isPayLater && storeCountry === 'us' ) {

View file

@ -1,56 +1,27 @@
import { Button, Icon } from '@wordpress/components';
import { chevronLeft } from '@wordpress/icons';
import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import classNames from 'classnames';
import { OnboardingHooks } from '../../../../data';
import useIsScrolled from '../../../../hooks/useIsScrolled';
import BusyStateWrapper from '../../../ReusableComponents/BusyStateWrapper';
import { useNavigation } from '../../../../hooks/useNavigation';
import TopNavigation from '../../../ReusableComponents/TopNavigation';
const Navigation = ( { stepDetails, onNext, onPrev, onExit } ) => {
const OnboardingNavigation = ( { stepDetails, onNext, onPrev } ) => {
const { goToWooCommercePaymentsTab } = useNavigation();
const { title, isFirst, percentage, showNext, canProceed } = stepDetails;
const { isScrolled } = useIsScrolled();
const state = OnboardingHooks.useNavigationState();
const isDisabled = ! canProceed( state );
const className = classNames( 'ppcp-r-navigation-container', {
'is-scrolled': isScrolled,
} );
return (
<div className={ className }>
<div className="ppcp-r-navigation">
<BusyStateWrapper
className="ppcp-r-navigation--left"
busySpinner={ false }
enabled={ ! isFirst }
>
<Button
variant="link"
onClick={ isFirst ? onExit : onPrev }
className="is-title"
>
<Icon icon={ chevronLeft } />
<span className={ 'title ' + ( isFirst ? 'big' : '' ) }>
{ title }
</span>
</Button>
</BusyStateWrapper>
{ ! isFirst &&
NextButton( { showNext, isDisabled, onNext, onExit } ) }
<ProgressBar percent={ percentage } />
</div>
</div>
);
};
const NextButton = ( { showNext, isDisabled, onNext, onExit } ) => {
return (
<BusyStateWrapper
className="ppcp-r-navigation--right"
busySpinner={ false }
<TopNavigation
title={ title }
isMainTitle={ isFirst }
exitOnTitleClick={ isFirst }
onTitleClick={ onPrev }
showProgressBar={ true }
progressBarPercent={ percentage * 0.9 }
>
<Button variant="link" onClick={ onExit }>
<Button variant="link" onClick={ goToWooCommercePaymentsTab }>
{ __( 'Save and exit', 'woocommerce-paypal-payments' ) }
</Button>
{ showNext && (
@ -62,19 +33,8 @@ const NextButton = ( { showNext, isDisabled, onNext, onExit } ) => {
{ __( 'Continue', 'woocommerce-paypal-payments' ) }
</Button>
) }
</BusyStateWrapper>
</TopNavigation>
);
};
const ProgressBar = ( { percent } ) => {
percent = Math.min( Math.max( percent, 0 ), 100 );
return (
<div
className="ppcp-r-navigation--progress-bar"
style={ { width: `${ percent * 0.9 }%` } }
/>
);
};
export default Navigation;
export default OnboardingNavigation;

View file

@ -1,11 +1,13 @@
import data from '../../utils/data';
import { Icon } from '@wordpress/components';
import { logoPayPal } from '../../../ReusableComponents/Icons';
const OnboardingHeader = ( props ) => {
return (
<section className="ppcp-r-onboarding-header">
<div className="ppcp-r-onboarding-header__logo">
<div className="ppcp-r-onboarding-header__logo-wrapper">
{ data().getImage( 'logo-paypal.svg' ) }
<Icon icon={ logoPayPal } width="auto" height={ 38 } />
</div>
</div>
<div className="ppcp-r-onboarding-header__content">
@ -14,8 +16,10 @@ const OnboardingHeader = ( props ) => {
</h1>
{ props.description && (
<p
className="ppcp-r-onboarding-header__description"
dangerouslySetInnerHTML={ { __html: props.description, } }
className="ppcp-r-onboarding-header__description"
dangerouslySetInnerHTML={ {
__html: props.description,
} }
></p>
) }
</div>

View file

@ -1,6 +1,6 @@
import { __ } from '@wordpress/i18n';
import PricingDescription from '../PricingDescription';
import PricingDescription from '../../../ReusableComponents/PricingDescription';
import AcdcFlow from './AcdcFlow';
import BcdcFlow from './BcdcFlow';

View file

@ -1,9 +1,9 @@
import { __ } from '@wordpress/i18n';
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
import SelectBox from '../../ReusableComponents/SelectBox';
import { OnboardingHooks, BUSINESS_TYPES } from '../../../data';
import SelectBoxWrapper from '../../../ReusableComponents/SelectBoxWrapper';
import SelectBox from '../../../ReusableComponents/SelectBox';
import { OnboardingHooks, BUSINESS_TYPES } from '../../../../data';
import OnboardingHeader from '../Components/OnboardingHeader';
const BUSINESS_RADIO_GROUP_NAME = 'business';

View file

@ -1,7 +1,7 @@
import { __ } from '@wordpress/i18n';
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
import ConnectionButton from './Components/ConnectionButton';
import OnboardingHeader from '../Components/OnboardingHeader';
import ConnectionButton from '../Components/ConnectionButton';
const StepCompleteSetup = () => {
return (

View file

@ -1,11 +1,11 @@
import { __ } from '@wordpress/i18n';
import { CommonHooks, OnboardingHooks } from '../../../data';
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
import SelectBox from '../../ReusableComponents/SelectBox';
import OptionalPaymentMethods from '../../ReusableComponents/OptionalPaymentMethods/OptionalPaymentMethods';
import PricingDescription from '../../ReusableComponents/PricingDescription';
import { CommonHooks, OnboardingHooks } from '../../../../data';
import SelectBoxWrapper from '../../../ReusableComponents/SelectBoxWrapper';
import SelectBox from '../../../ReusableComponents/SelectBox';
import PricingDescription from '../../../ReusableComponents/PricingDescription';
import OnboardingHeader from '../Components/OnboardingHeader';
import OptionalPaymentMethods from '../Components/OptionalPaymentMethods';
const OPM_RADIO_GROUP_NAME = 'optional-payment-methods';
@ -17,14 +17,21 @@ const StepPaymentMethods = ( {} ) => {
const { storeCountry, storeCurrency } = CommonHooks.useWooSettings();
let screenTitle = __(
'Add optional payment methods to your Checkout',
'woocommerce-paypal-payments'
);
if ( 'US' === storeCountry ) {
screenTitle = __(
'Add Expanded Checkout for More Ways to Pay',
'woocommerce-paypal-payments'
);
}
return (
<div className="ppcp-r-page-optional-payment-methods">
<OnboardingHeader
title={ __(
'Add Expanded Checkout for more ways to pay',
'woocommerce-paypal-payments'
) }
/>
<OnboardingHeader title={ screenTitle } />
<div className="ppcp-r-inner-container">
<SelectBoxWrapper>
<SelectBox

View file

@ -1,9 +1,9 @@
import { __ } from '@wordpress/i18n';
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
import SelectBox from '../../ReusableComponents/SelectBox';
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
import { OnboardingHooks, PRODUCT_TYPES } from '../../../data';
import SelectBox from '../../../ReusableComponents/SelectBox';
import SelectBoxWrapper from '../../../ReusableComponents/SelectBoxWrapper';
import { OnboardingHooks, PRODUCT_TYPES } from '../../../../data';
import OnboardingHeader from '../Components/OnboardingHeader';
const PRODUCTS_CHECKBOX_GROUP_NAME = 'products';

View file

@ -1,15 +1,14 @@
import { __ } from '@wordpress/i18n';
import { Button } from '@wordpress/components';
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
import Separator from '../../ReusableComponents/Separator';
import WelcomeDocs from '../../ReusableComponents/WelcomeDocs/WelcomeDocs';
import AccordionSection from '../../ReusableComponents/AccordionSection';
import AdvancedOptionsForm from './Components/AdvancedOptionsForm';
import { CommonHooks } from '../../../data';
import BusyStateWrapper from '../../ReusableComponents/BusyStateWrapper';
import PaymentMethodIcons from '../../../ReusableComponents/PaymentMethodIcons';
import Separator from '../../../ReusableComponents/Separator';
import AccordionSection from '../../../ReusableComponents/AccordionSection';
import { CommonHooks } from '../../../../data';
import BusyStateWrapper from '../../../ReusableComponents/BusyStateWrapper';
import OnboardingHeader from '../Components/OnboardingHeader';
import WelcomeDocs from '../Components/WelcomeDocs';
import AdvancedOptionsForm from '../Components/AdvancedOptionsForm';
const StepWelcome = ( { setStep, currentStep } ) => {
const { storeCountry } = CommonHooks.useWooSettings();

View file

@ -1,27 +1,23 @@
import Container from '../../ReusableComponents/Container';
import { OnboardingHooks } from '../../../data';
import { getSteps, getCurrentStep } from './availableSteps';
import Navigation from './Components/Navigation';
import { getSteps, getCurrentStep } from './Steps';
import OnboardingNavigation from './Components/Navigation';
const Onboarding = () => {
const OnboardingScreen = () => {
const { step, setStep, flags } = OnboardingHooks.useSteps();
const Steps = getSteps( flags );
const currentStep = getCurrentStep( step, Steps );
const handleNext = () => setStep( currentStep.nextStep );
const handlePrev = () => setStep( currentStep.prevStep );
const handleExit = () => {
window.location.href = window.ppcpSettings.wcPaymentsTabUrl;
};
return (
<>
<Navigation
<OnboardingNavigation
stepDetails={ currentStep }
onNext={ handleNext }
onPrev={ handlePrev }
onExit={ handleExit }
/>
<Container page="onboarding">
@ -37,4 +33,4 @@ const Onboarding = () => {
);
};
export default Onboarding;
export default OnboardingScreen;

View file

@ -1,6 +1,9 @@
import { __ } from '@wordpress/i18n';
import { CommonHooks } from '../../../../../../data';
import { Title } from '../../../../../ReusableComponents/SettingsBlocks';
import {
SettingsBlock,
Title,
} from '../../../../../ReusableComponents/SettingsBlocks';
const HooksTableBlock = () => {
const { webhooks } = CommonHooks.useWebhooks();
@ -11,10 +14,10 @@ const HooksTableBlock = () => {
}
return (
<>
<SettingsBlock separatorAndGap={ false }>
<WebhookUrl url={ url } />
<WebhookEvents events={ events } />
</>
</SettingsBlock>
);
};

View file

@ -56,6 +56,7 @@ const ResubscribeBlock = () => {
'Click to remove the current webhook subscription and subscribe again, for example, if the website domain or URL structure changed.',
'woocommerce-paypal-payments'
) }
separatorAndGap={ false }
actionProps={ {
buttonType: 'secondary',
isBusy: resubscribing,

View file

@ -107,23 +107,20 @@ const SimulationBlock = () => {
};
return (
<>
<ButtonSettingsBlock
title={ __(
'Simulate webhooks',
'woocommerce-paypal-payments'
) }
actionProps={ {
buttonType: 'secondary',
isBusy: simulating,
callback: () => startSimulation( 30 ),
value: __(
'Simulate webhooks',
'woocommerce-paypal-payments'
),
} }
/>
</>
<ButtonSettingsBlock
title={ __( 'Test webhooks', 'woocommerce-paypal-payments' ) }
description={ __(
'Send a test-webhook from PayPal to confirm that webhooks are being received and processed correctly.',
'woocommerce-paypal-payments'
) }
separatorAndGap={ false }
actionProps={ {
buttonType: 'secondary',
isBusy: simulating,
callback: () => startSimulation( 30 ),
value: __( 'Simulate webhooks', 'woocommerce-paypal-payments' ),
} }
/>
);
};
export default SimulationBlock;

View file

@ -2,7 +2,7 @@ import { __, sprintf } from '@wordpress/i18n';
import Container from '../ReusableComponents/Container';
import SettingsCard from '../ReusableComponents/SettingsCard';
import SettingsNavigation from './SettingsNavigation';
import SettingsNavigation from './Settings/Components/Navigation';
const SendOnlyMessage = () => {
const settingsPageUrl = '/wp-admin/admin.php?page=wc-settings';
@ -38,7 +38,7 @@ const SendOnlyMessage = () => {
__html: sprintf(
/* translators: 1: URL to the WooCommerce store location settings */
__(
'To activate PayPal, please update your <a href="%1$s">WooCommerce store location</a> to a supported region and connect a PayPal account eligible for receiving payments.',
'To activate PayPal, please <a href="%1$s">update your WooCommerce store location</a> to a supported region and connect a PayPal account eligible for receiving payments.',
'woocommerce-paypal-payments'
),
settingsPageUrl

View file

@ -0,0 +1,18 @@
import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import TopNavigation from '../../../ReusableComponents/TopNavigation';
const SettingsNavigation = () => {
const title = __( 'PayPal Payments', 'woocommerce-paypal-payments' );
return (
<TopNavigation title={ title } exitOnTitleClick={ true }>
<Button variant="primary" disabled={ false }>
{ __( 'Save', 'woocommerce-paypal-payments' ) }
</Button>
</TopNavigation>
);
};
export default SettingsNavigation;

View file

@ -0,0 +1,49 @@
import { __ } from '@wordpress/i18n';
import TabOverview from '../../Overview/TabOverview';
import TabPaymentMethods from '../../Overview/TabPaymentMethods';
import TabSettings from '../../Overview/TabSettings';
import TabStyling from '../../Overview/TabStyling';
import TabPayLaterMessaging from '../../Overview/TabPayLaterMessaging';
/**
* List of all default settings tabs.
*
* The tabs are displayed in the order in which they appear in this array
*
* @type {[{name, title, Component}]}
*/
const DEFAULT_TABS = [
{
name: 'overview',
title: __( 'Overview', 'woocommerce-paypal-payments' ),
Component: <TabOverview />,
},
{
name: 'payment-methods',
title: __( 'Payment Methods', 'woocommerce-paypal-payments' ),
Component: <TabPaymentMethods />,
},
{
name: 'settings',
title: __( 'Settings', 'woocommerce-paypal-payments' ),
Component: <TabSettings />,
},
{
name: 'styling',
title: __( 'Styling', 'woocommerce-paypal-payments' ),
Component: <TabStyling />,
},
{
name: 'pay-later-messaging',
title: __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ),
Component: <TabPayLaterMessaging />,
showIf: () => !! window.ppcpSettings?.isPayLaterConfiguratorAvailable,
},
];
export const getSettingsTabs = () => {
return DEFAULT_TABS.filter( ( tab ) => {
return ! tab.showIf || tab.showIf();
} );
};

View file

@ -1,7 +1,7 @@
import { getSettingsTabs } from './tabs';
import SettingsNavigation from './SettingsNavigation';
import Container from '../ReusableComponents/Container';
import TabNavigation from '../ReusableComponents/TabNavigation';
import Container from '../../ReusableComponents/Container';
import TabNavigation from '../../ReusableComponents/TabNavigation';
import { getSettingsTabs } from './Tabs';
import SettingsNavigation from './Components/Navigation';
const SettingsScreen = () => {
const tabs = getSettingsTabs();

View file

@ -1,37 +0,0 @@
import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import data from '../../utils/data';
const SettingsNavigation = ( {} ) => {
return (
<div className="ppcp-r-navigation-container">
<div className="ppcp-r-navigation">
<div className="ppcp-r-navigation--left">
<span>{ data().getImage( 'icon-arrow-left.svg' ) }</span>
<a
className="ppcp-r-navigation--left__link"
href={ global.ppcpSettings.wcPaymentsTabUrl }
aria-label={ __(
'PayPal Payments',
'woocommerce-paypal-payments'
) }
>
{ __(
'PayPal Payments',
'woocommerce-paypal-payments'
) }
</a>
</div>
{
<div className="ppcp-r-navigation--right">
<Button variant="primary" disabled={ false }>
{ __( 'Save', 'woocommerce-paypal-payments' ) }
</Button>
</div>
}
</div>
</div>
);
};
export default SettingsNavigation;

View file

@ -1,44 +0,0 @@
import { __ } from '@wordpress/i18n';
import TabOverview from './Overview/TabOverview';
import TabPaymentMethods from './Overview/TabPaymentMethods';
import TabSettings from './Overview/TabSettings';
import TabStyling from './Overview/TabStyling';
import TabPayLaterMessaging from './Overview/TabPayLaterMessaging';
export const getSettingsTabs = () => {
const tabs = [];
tabs.push( {
name: 'overview',
title: __( 'Overview', 'woocommerce-paypal-payments' ),
component: <TabOverview />,
} );
tabs.push( {
name: 'payment-methods',
title: __( 'Payment Methods', 'woocommerce-paypal-payments' ),
component: <TabPaymentMethods />,
} );
tabs.push( {
name: 'settings',
title: __( 'Settings', 'woocommerce-paypal-payments' ),
component: <TabSettings />,
} );
tabs.push( {
name: 'styling',
title: __( 'Styling', 'woocommerce-paypal-payments' ),
component: <TabStyling />,
} );
if ( window.ppcpSettings.isPayLaterConfiguratorAvailable ) {
tabs.push( {
name: 'pay-later-messaging',
title: __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ),
component: <TabPayLaterMessaging />,
} );
}
return tabs;
};

View file

@ -21,11 +21,11 @@ export default {
DO_PERSIST_DATA: 'COMMON:DO_PERSIST_DATA',
DO_DIRECT_API_AUTHENTICATION: 'COMMON:DO_DIRECT_API_AUTHENTICATION',
DO_OAUTH_AUTHENTICATION: 'COMMON:DO_OAUTH_AUTHENTICATION',
DO_DISCONNECT_MERCHANT: 'COMMON:DO_DISCONNECT_MERCHANT',
DO_GENERATE_ONBOARDING_URL: 'COMMON:DO_GENERATE_ONBOARDING_URL',
DO_REFRESH_MERCHANT: 'COMMON:DO_REFRESH_MERCHANT',
DO_REFRESH_FEATURES: 'COMMON:DO_REFRESH_FEATURES',
DO_RESUBSCRIBE_WEBHOOKS: 'COMMON:DO_RESUBSCRIBE_WEBHOOKS',
DO_START_WEBHOOK_SIMULATION: 'COMMON:DO_START_WEBHOOK_SIMULATION',
DO_CHECK_WEBHOOK_SIMULATION_STATE:
'COMMON:DO_CHECK_WEBHOOK_SIMULATION_STATE',
DO_CHECK_WEBHOOK_SIMULATION: 'COMMON:DO_CHECK_WEBHOOK_SIMULATION',
};

View file

@ -212,6 +212,15 @@ export const authenticateWithOAuth = function* (
};
};
/**
* Side effect. Checks webhook simulation.
*
* @return {Action} The action.
*/
export const disconnectMerchant = function* () {
return yield { type: ACTION_TYPES.DO_DISCONNECT_MERCHANT };
};
/**
* Side effect. Clears and refreshes the merchant data via a REST request.
*
@ -288,5 +297,5 @@ export const startWebhookSimulation = function* () {
* @return {Action} The action.
*/
export const checkWebhookSimulationState = function* () {
return yield { type: ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION_STATE };
return yield { type: ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION };
};

View file

@ -46,14 +46,26 @@ export const REST_DIRECT_AUTHENTICATION_PATH =
'/wc/v3/wc_paypal/authenticate/direct';
/**
* REST path to perform the ISU authentication check, using shared ID and authCode.
* REST path to perform the OAuth authentication check, using shared ID and authCode.
*
* Used by: Controls
* See: AuthenticateRestEndpoint.php
*
* @type {string}
*/
export const REST_ISU_AUTHENTICATION_PATH = '/wc/v3/wc_paypal/authenticate/isu';
export const REST_OAUTH_AUTHENTICATION_PATH =
'/wc/v3/wc_paypal/authenticate/oauth';
/**
* REST path to disconnect the current merchant from PayPal.
*
* Used by: Controls
* See: AuthenticateRestEndpoint.php
*
* @type {string}
*/
export const REST_DISCONNECT_MERCHANT_PATH =
'/wc/v3/wc_paypal/authenticate/disconnect';
/**
* REST path to generate an ISU URL for the PayPal-login.
@ -66,24 +78,24 @@ export const REST_ISU_AUTHENTICATION_PATH = '/wc/v3/wc_paypal/authenticate/isu';
export const REST_CONNECTION_URL_PATH = '/wc/v3/wc_paypal/login_link';
/**
* REST path to fetch webhooks data or resubscribe webhooks,
* REST path to fetch webhooks data or resubscribe webhooks.
*
* Used by: Controls
* See: WebhookSettingsEndpoint.php
*
* @type {string}
*/
export const REST_WEBHOOKS = '/wc/v3/wc_paypal/webhook_settings';
export const REST_WEBHOOKS = '/wc/v3/wc_paypal/webhooks';
/**
* REST path to start webhook simulation and observe the state,
* REST path to start webhook simulation and observe the state.
*
* Used by: Controls
* See: WebhookSettingsEndpoint.php
*
* @type {string}
*/
export const REST_WEBHOOKS_SIMULATE = '/wc/v3/wc_paypal/webhook_simulate';
export const REST_WEBHOOKS_SIMULATE = '/wc/v3/wc_paypal/webhooks/simulate';
/**
* REST path to refresh the feature status.
@ -93,5 +105,4 @@ export const REST_WEBHOOKS_SIMULATE = '/wc/v3/wc_paypal/webhook_simulate';
*
* @type {string}
*/
export const REST_REFRESH_FEATURES_PATH =
'/wc/v3/wc_paypal/refresh-feature-status';
export const REST_REFRESH_FEATURES_PATH = '/wc/v3/wc_paypal/refresh-features';

View file

@ -11,11 +11,12 @@ import apiFetch from '@wordpress/api-fetch';
import {
REST_PERSIST_PATH,
REST_DIRECT_AUTHENTICATION_PATH,
REST_CONNECTION_URL_PATH,
REST_HYDRATE_MERCHANT_PATH,
REST_REFRESH_FEATURES_PATH,
REST_ISU_AUTHENTICATION_PATH,
REST_DIRECT_AUTHENTICATION_PATH,
REST_OAUTH_AUTHENTICATION_PATH,
REST_DISCONNECT_MERCHANT_PATH,
REST_WEBHOOKS,
REST_WEBHOOKS_SIMULATE,
} from './constants';
@ -82,7 +83,7 @@ export const controls = {
} ) {
try {
return await apiFetch( {
path: REST_ISU_AUTHENTICATION_PATH,
path: REST_OAUTH_AUTHENTICATION_PATH,
method: 'POST',
data: {
sharedId,
@ -98,6 +99,13 @@ export const controls = {
}
},
async [ ACTION_TYPES.DO_DISCONNECT_MERCHANT ]() {
return await apiFetch( {
path: REST_DISCONNECT_MERCHANT_PATH,
method: 'POST',
} );
},
async [ ACTION_TYPES.DO_REFRESH_MERCHANT ]() {
try {
return await apiFetch( { path: REST_HYDRATE_MERCHANT_PATH } );
@ -138,7 +146,7 @@ export const controls = {
} );
},
async [ ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION_STATE ]() {
async [ ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION ]() {
return await apiFetch( {
path: REST_WEBHOOKS_SIMULATE,
} );

View file

@ -77,6 +77,8 @@ const commonReducer = createReducer( defaultTransient, defaultPersistent, {
// Keep "read-only" details and initialization flags.
cleanState.wooSettings = { ...state.wooSettings };
cleanState.merchant = { ...state.merchant };
cleanState.features = { ...state.features };
cleanState.isReady = true;
return cleanState;

View file

@ -9,6 +9,7 @@ export const addDebugTools = ( context, modules ) => {
return;
}
// Dump the current state of all our Redux stores.
context.dumpStore = async () => {
/* eslint-disable no-console */
if ( ! console?.groupCollapsed ) {
@ -36,25 +37,47 @@ export const addDebugTools = ( context, modules ) => {
/* eslint-enable no-console */
};
// Reset all Redux stores to their initial state.
context.resetStore = () => {
const stores = [
OnboardingStoreName,
CommonStoreName,
PaymentStoreName,
];
const stores = [];
const { isConnected } = wp.data.select( CommonStoreName ).merchant();
if ( isConnected ) {
// Make sure the Onboarding wizard is "completed".
const onboarding = wp.data.dispatch( OnboardingStoreName );
onboarding.setCompleted( true );
onboarding.persist();
// Reset all stores, except for the onboarding store.
stores.push( CommonStoreName );
// TODO: Add other stores here once they are available.
stores.push( PaymentStoreName );
} else {
// Only reset the common & onboarding stores to restart the onboarding wizard.
stores.push( CommonStoreName );
stores.push( OnboardingStoreName );
}
stores.forEach( ( storeName ) => {
const store = wp.data.dispatch( storeName );
// eslint-disable-next-line no-console
console.log( `Reset store: ${ storeName }...` );
store.reset();
store.persist();
} );
};
context.startOnboarding = () => {
const onboarding = wp.data.dispatch( OnboardingStoreName );
onboarding.setCompleted( false );
onboarding.setStep( 0 );
onboarding.persist();
// Disconnect the merchant and display the onboarding wizard.
context.disconnect = () => {
const common = wp.data.dispatch( CommonStoreName );
common.disconnectMerchant();
// eslint-disable-next-line no-console
console.log( 'Disconnected from PayPal. Reloading the page...' );
window.location.reload();
};
};

View file

@ -0,0 +1,10 @@
/**
* Navigate to the WooCommerce "Payments" settings tab, i.e. exit the settings app.
*/
const goToWooCommercePaymentsTab = () => {
window.location.href = window.ppcpSettings.wcPaymentsTabUrl;
};
export const useNavigation = () => {
return { goToWooCommercePaymentsTab };
};

View file

@ -1,6 +1,6 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './App';
import App from './Components/App';
createRoot( document.getElementById( 'ppcp-settings-container' ) ).render(
<App />

View file

@ -67,6 +67,14 @@ class AuthenticationRestEndpoint extends RestEndpoint {
* Configure REST API routes.
*/
public function register_routes() : void {
/**
* POST /wp-json/wc/v3/wc_paypal/authenticate/direct
* {
* clientId
* clientSecret
* useSandbox
* }
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/direct',
@ -97,12 +105,20 @@ class AuthenticationRestEndpoint extends RestEndpoint {
)
);
/**
* POST /wp-json/wc/v3/wc_paypal/authenticate/oauth
* {
* sharedId
* authCode
* useSandbox
* }
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/isu',
'/' . $this->rest_base . '/oauth',
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array( $this, 'connect_isu' ),
'callback' => array( $this, 'connect_oauth' ),
'permission_callback' => array( $this, 'check_permission' ),
'args' => array(
'sharedId' => array(
@ -123,6 +139,19 @@ class AuthenticationRestEndpoint extends RestEndpoint {
),
)
);
/**
* POST /wp-json/wc/v3/wc_paypal/authenticate/disconnect
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/disconnect',
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array( $this, 'disconnect' ),
'permission_callback' => array( $this, 'check_permission' ),
)
);
}
/**
@ -152,14 +181,14 @@ class AuthenticationRestEndpoint extends RestEndpoint {
}
/**
* ISU login: Retrieves clientId and clientSecret using a sharedId and authCode.
* OAuth login: Retrieves clientId and clientSecret using a sharedId and authCode.
*
* This is the final step in the UI-driven login via the ISU popup, which
* This is the final step in the UI-driven login via the OAuth popup, which
* is triggered by the LoginLinkRestEndpoint URL.
*
* @param WP_REST_Request $request Full data about the request.
*/
public function connect_isu( WP_REST_Request $request ) : WP_REST_Response {
public function connect_oauth( WP_REST_Request $request ) : WP_REST_Response {
$shared_id = $request->get_param( 'sharedId' );
$auth_code = $request->get_param( 'authCode' );
$use_sandbox = $request->get_param( 'useSandbox' );
@ -176,4 +205,15 @@ class AuthenticationRestEndpoint extends RestEndpoint {
return $this->return_success( $response );
}
/**
* Disconnect the merchant and clear the authentication details.
*
* @return WP_REST_Response
*/
public function disconnect() : WP_REST_Response {
$this->authentication_manager->disconnect();
return $this->return_success( 'OK' );
}
}

View file

@ -110,7 +110,10 @@ class CommonRestEndpoint extends RestEndpoint {
/**
* Configure REST API routes.
*/
public function register_routes() {
public function register_routes() : void {
/**
* GET /wp-json/wc/v3/wc_paypal/common
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
@ -121,6 +124,12 @@ class CommonRestEndpoint extends RestEndpoint {
)
);
/**
* POST /wp-json/wc/v3/wc_paypal/common
* {
* // Fields mentioned in $field_map[]['js_name']
* }
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
@ -131,6 +140,9 @@ class CommonRestEndpoint extends RestEndpoint {
)
);
/**
* GET /wp-json/wc/v3/wc_paypal/common/merchant
*/
register_rest_route(
$this->namespace,
"/$this->rest_base/merchant",

View file

@ -52,6 +52,13 @@ class LoginLinkRestEndpoint extends RestEndpoint {
* Configure REST API routes.
*/
public function register_routes() : void {
/**
* POST /wp-json/wc/v3/wc_paypal/login_link
* {
* useSandbox
* products
* }
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base,

View file

@ -96,7 +96,10 @@ class OnboardingRestEndpoint extends RestEndpoint {
/**
* Configure REST API routes.
*/
public function register_routes() {
public function register_routes() : void {
/**
* GET /wp-json/wc/v3/wc_paypal/onboarding
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
@ -107,6 +110,12 @@ class OnboardingRestEndpoint extends RestEndpoint {
)
);
/**
* POST /wp-json/wc/v3/wc_paypal/onboarding
* {
* // Fields mentioned in $field_map[]['js_name']
* }
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base,

View file

@ -25,7 +25,7 @@ class RefreshFeatureStatusEndpoint extends RestEndpoint {
*
* @var string
*/
protected $rest_base = 'refresh-feature-status';
protected $rest_base = 'refresh-features';
/**
* Cache timeout in seconds.
@ -82,7 +82,10 @@ class RefreshFeatureStatusEndpoint extends RestEndpoint {
/**
* Configure REST API routes.
*/
public function register_routes() {
public function register_routes() : void {
/**
* POST /wp-json/wc/v3/wc_paypal/refresh-features
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base,

View file

@ -29,14 +29,7 @@ class WebhookSettingsEndpoint extends RestEndpoint {
*
* @var string
*/
protected $rest_base = 'webhook_settings';
/**
* Endpoint base to start webhook simulation and check the state
*
* @var string
*/
protected string $rest_simulate_base = 'webhook_simulate';
protected $rest_base = 'webhooks';
/**
* Application webhook endpoint
@ -67,7 +60,11 @@ class WebhookSettingsEndpoint extends RestEndpoint {
* @param WebhookRegistrar $webhook_registrar A service that allows resubscribing webhooks.
* @param WebhookSimulation $webhook_simulation A service that allows webhook simulations.
*/
public function __construct( WebhookEndpoint $webhook_endpoint, WebhookRegistrar $webhook_registrar, WebhookSimulation $webhook_simulation ) {
public function __construct(
WebhookEndpoint $webhook_endpoint,
WebhookRegistrar $webhook_registrar,
WebhookSimulation $webhook_simulation
) {
$this->webhook_endpoint = $webhook_endpoint;
$this->webhook_registrar = $webhook_registrar;
$this->webhook_simulation = $webhook_simulation;
@ -77,6 +74,10 @@ class WebhookSettingsEndpoint extends RestEndpoint {
* Configure REST API routes.
*/
public function register_routes() : void {
/**
* GET /wp-json/wc/v3/wc_paypal/webhooks
* POST /wp-json/wc/v3/wc_paypal/webhooks
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
@ -94,9 +95,13 @@ class WebhookSettingsEndpoint extends RestEndpoint {
)
);
/**
* GET /wp-json/wc/v3/wc_paypal/webhooks/simulate
* POST /wp-json/wc/v3/wc_paypal/webhooks/simulate
*/
register_rest_route(
$this->namespace,
'/' . $this->rest_simulate_base,
'/' . $this->rest_base . '/simulate',
array(
array(
'methods' => WP_REST_Server::READABLE,

View file

@ -122,6 +122,11 @@ class AuthenticationManager {
* is no need for it here, it's good house-keeping practice to clean up.
*/
do_action( 'woocommerce_paypal_payments_flush_api_cache' );
/**
* Clear the APM eligibility flags from the default settings object.
*/
do_action( 'woocommerce_paypal_payments_clear_apm_product_status', null );
}
/**
@ -420,6 +425,11 @@ class AuthenticationManager {
*/
do_action( 'woocommerce_paypal_payments_authenticated_merchant' );
/**
* Clear the APM eligibility flags from the default settings object.
*/
do_action( 'woocommerce_paypal_payments_clear_apm_product_status', null );
/**
* Subscribe the new merchant to relevant PayPal webhooks.
*/