mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 14:57:26 +08:00
🔀 Merge branch 'trunk'
# Conflicts: # modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
This commit is contained in:
commit
6aecfdad31
70 changed files with 1178 additions and 821 deletions
|
@ -44,7 +44,13 @@ return array(
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( wc_terms_and_conditions_page_id() > 0 ) {
|
/**
|
||||||
|
* Replace wc_terms_and_conditions_page_id() function to avoid errors when to avoid errors because of early loading.
|
||||||
|
*/
|
||||||
|
$wc_terms_and_conditions_page_id = apply_filters( 'woocommerce_get_terms_page_id', get_option( 'woocommerce_terms_page_id' ) );
|
||||||
|
$wc_terms_and_conditions_page_id = apply_filters( 'woocommerce_terms_and_conditions_page_id', 0 < $wc_terms_and_conditions_page_id ? absint( $wc_terms_and_conditions_page_id ) : 0 );
|
||||||
|
|
||||||
|
if ( $wc_terms_and_conditions_page_id > 0 ) {
|
||||||
$label .= __(
|
$label .= __(
|
||||||
'<div class="ppcp-notice ppcp-notice-warning"><p><span class="highlight">Important:</span> Your store has a <a href="/wp-admin/admin.php?page=wc-settings&tab=advanced" target="_blank">Terms and Conditions</a> page configured. Buyers who use a PayPal express payment method will not be able to consent to the terms on the <code>Classic Checkout</code>, as the final checkout confirmation will be skipped.</p></div>',
|
'<div class="ppcp-notice ppcp-notice-warning"><p><span class="highlight">Important:</span> Your store has a <a href="/wp-admin/admin.php?page=wc-settings&tab=advanced" target="_blank">Terms and Conditions</a> page configured. Buyers who use a PayPal express payment method will not be able to consent to the terms on the <code>Classic Checkout</code>, as the final checkout confirmation will be skipped.</p></div>',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin hide-input-field() {
|
@mixin hide-input-field() {
|
||||||
width: 100%;
|
width: auto;
|
||||||
height: 100%;
|
height: auto;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
|
@ -19,7 +19,6 @@ $color-divider: #F0F0F0;
|
||||||
$color-error-red: #cc1818;
|
$color-error-red: #cc1818;
|
||||||
|
|
||||||
$shadow-card: 0 3px 6px 0 rgba(0, 0, 0, 0.15);
|
$shadow-card: 0 3px 6px 0 rgba(0, 0, 0, 0.15);
|
||||||
$shadow-selection-box: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
$color-gradient-dark: #001435;
|
$color-gradient-dark: #001435;
|
||||||
$gradient-header: linear-gradient(87.03deg, #003087 -0.49%, #001E51 29.22%, $color-gradient-dark 100%);
|
$gradient-header: linear-gradient(87.03deg, #003087 -0.49%, #001E51 29.22%, $color-gradient-dark 100%);
|
||||||
|
|
||||||
|
@ -71,4 +70,15 @@ $card-vertical-gap: 48px;
|
||||||
--block-separator-size: 1px;
|
--block-separator-size: 1px;
|
||||||
--block-separator-color: var(--color-gray-200);
|
--block-separator-color: var(--color-gray-200);
|
||||||
--block-action-gap: 16px; // Space between two consecutive action blocks.
|
--block-action-gap: 16px; // Space between two consecutive action blocks.
|
||||||
|
|
||||||
|
// Default visual effects.
|
||||||
|
--box-shadow-active-item: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
--container-border-radius: 8px;
|
||||||
|
|
||||||
|
// Spinner/loader.
|
||||||
|
--spinner-size: 20px;
|
||||||
|
--spinner-overlay-width: 320px;
|
||||||
|
--spinner-overlay-height: 320px;
|
||||||
|
--spinner-overlay-color: #fafafa;
|
||||||
|
--spinner-overlay-box-shadow: var(--box-shadow-active-item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
@import './reusable-components/button';
|
@import './reusable-components/button';
|
||||||
@import './reusable-components/elements';
|
@import './reusable-components/elements';
|
||||||
@import './reusable-components/fields';
|
@import './reusable-components/fields';
|
||||||
@import './reusable-components/hstack';
|
|
||||||
@import './reusable-components/navigation';
|
@import './reusable-components/navigation';
|
||||||
@import './reusable-components/onboarding-header';
|
@import './reusable-components/onboarding-header';
|
||||||
@import './reusable-components/payment-method-icons';
|
@import './reusable-components/payment-method-icons';
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
@import './reusable-components/settings-toggle-block';
|
@import './reusable-components/settings-toggle-block';
|
||||||
@import './reusable-components/settings-wrapper';
|
@import './reusable-components/settings-wrapper';
|
||||||
@import './reusable-components/spinner-overlay';
|
@import './reusable-components/spinner-overlay';
|
||||||
|
@import './reusable-components/stack';
|
||||||
@import './reusable-components/tab-navigation';
|
@import './reusable-components/tab-navigation';
|
||||||
@import './reusable-components/title-badge';
|
@import './reusable-components/title-badge';
|
||||||
@import './reusable-components/welcome-docs';
|
@import './reusable-components/welcome-docs';
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
&--has-image-badge .ppcp-r-title-badge--info {
|
&--has-image-badge .ppcp-r-title-badge--info {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 6px 0px 0px 0px;
|
margin: 6px 0 0 0;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,9 +42,9 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.ppcp-r-badge-box__title-text:not(:empty) + .ppcp-r-badge-box__title-image-badge {
|
.ppcp-r-badge-box__title-text:not(:empty) + .ppcp-r-badge-box__title-image-badge {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
img:first-of-type {
|
img:first-of-type {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,8 @@ button.components-button, a.components-button {
|
||||||
|
|
||||||
/* style the button template */
|
/* style the button template */
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
&:not(:disabled) {
|
&:not(:disabled) {
|
||||||
@extend %button-style-default;
|
@extend %button-style-default;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
.ppcp-r-title-badge {
|
.ppcp-r-title-badge {
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
margin-left: 6px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
.ppcp-r-app {
|
|
||||||
.components-flex {
|
|
||||||
display: flex;
|
|
||||||
-webkit-box-align: stretch;
|
|
||||||
align-items: stretch;
|
|
||||||
-webkit-box-pack: center;
|
|
||||||
|
|
||||||
.components-h-stack {
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-v-stack {
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix layout for checkboxes inside a flex-stack.
|
|
||||||
.components-checkbox-control > .components-base-control__field > .components-flex {
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ppcp--horizontal {
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,6 +3,7 @@
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
> img{
|
> img{
|
||||||
width: 38px;
|
width: 38px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
|
@ -1,74 +1,80 @@
|
||||||
.ppcp-r-settings-block__payment-methods {
|
// Grid layout.
|
||||||
&.ppcp-r-settings-block {
|
.ppcp-r-settings-block.ppcp--grid > .ppcp--content {
|
||||||
display: flex;
|
--block-separator-gap: 0;
|
||||||
flex-wrap: wrap;
|
|
||||||
flex-direction: row;
|
display: grid;
|
||||||
gap: 16px;
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__item {
|
@media screen and (max-width: 480px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Theming & visual styles.
|
||||||
|
.ppcp-r-settings-block__payment-methods {
|
||||||
|
.ppcp-r-settings-block {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
width: calc(100% / 3 - 32px / 3);
|
|
||||||
border: 1px solid $color-gray-300;
|
border: 1px solid $color-gray-300;
|
||||||
|
border-radius: var(--container-border-radius);
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 8px;
|
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
|
|
||||||
@media screen and (max-width: 767px) {
|
.ppcp--method-inner {
|
||||||
width: calc(50% - 8px);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 480px) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__inner {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title-wrapper {
|
.ppcp--method-title-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0 0 8px 0;
|
margin: 0 0 8px 0;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__description {
|
.ppcp--method-description {
|
||||||
p {
|
p {
|
||||||
|
@include font(13, 20, 400);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: $color-text-tertiary;
|
color: $color-text-tertiary;
|
||||||
@include font(13, 20, 400);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
margin: 0 0 12px 0;
|
margin: 0 0 12px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title {
|
.ppcp--method-title {
|
||||||
@include font(13, 20, 500);
|
@include font(13, 20, 500);
|
||||||
color: $color-black;
|
color: $color-black;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__settings {
|
.ppcp--method-settings {
|
||||||
line-height: 0;
|
padding: 0;
|
||||||
transition: 0.2s ease-out transform;
|
transition: 0.2s ease-out transform;
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
zoom: 1.005;
|
zoom: 1.005;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ppcp--method-icon {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
button.is-secondary {
|
button.is-secondary {
|
||||||
@include small-button;
|
@include small-button;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__footer {
|
.ppcp--method-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
.ppcp-r-select-box-wrapper {
|
.ppcp-r-select-box-wrapper {
|
||||||
|
--box-border-color: var(--color-gray-200);
|
||||||
|
--box-outline-color: transparent;
|
||||||
|
--box-shadow: 0;
|
||||||
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 32px;
|
gap: 32px;
|
||||||
|
@ -6,92 +10,62 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.ppcp-r-select-box {
|
.ppcp-r-select-box {
|
||||||
|
border: 1px solid var(--box-border-color);
|
||||||
|
outline: 1px solid var(--box-outline-color);
|
||||||
|
box-shadow: var(--box-shadow);
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid $color-gray-200;
|
|
||||||
outline: 1px solid transparent;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 24px 16px 24px 16px;
|
padding: 24px 16px 24px 16px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
--box-border-color: var(--color-gray-500);
|
||||||
|
--box-shadow: var(--box-shadow-active-item);
|
||||||
|
}
|
||||||
|
|
||||||
&.ppcp--selected {
|
&.ppcp--selected {
|
||||||
border-color: $color-blueberry;
|
--box-border-color: var(--color-blueberry);
|
||||||
outline-color: $color-blueberry;
|
--box-outline-color: var(--color-blueberry);
|
||||||
box-shadow: $shadow-selection-box;
|
--box-shadow: var(--box-shadow-active-item);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__radio-value {
|
.ppcp--box-content {
|
||||||
@include hide-input-field;
|
|
||||||
|
|
||||||
&:checked {
|
|
||||||
+ .ppcp-r-select-box__radio-presentation {
|
|
||||||
background: $color-white;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
border: 6px solid $color-blueberry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__checkbox-value {
|
|
||||||
@include hide-input-field;
|
|
||||||
|
|
||||||
&:not(:checked) + .ppcp-r-select-box__checkbox-presentation img {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:checked {
|
|
||||||
+ .ppcp-r-select-box__checkbox-presentation {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
img {
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
*:not(a){
|
|
||||||
|
*:not(a) {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title {
|
.ppcp--box-title {
|
||||||
@include font(14, 20, 700);
|
@include font(14, 20, 700);
|
||||||
color: $color-black;
|
color: $color-black;
|
||||||
margin: 0 0 4px 0;
|
margin: 0 0 4px 0;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__description {
|
.ppcp--box-description {
|
||||||
@include font(13, 20, 400);
|
@include font(13, 20, 400);
|
||||||
color: $color-gray-700;
|
color: $color-gray-700;
|
||||||
margin:0;
|
margin: 0;
|
||||||
|
|
||||||
&:not(:last-child){
|
&:not(:last-child) {
|
||||||
margin-block-end:18px;
|
margin-block-end: 18px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__radio-presentation {
|
.ppcp--box-details {
|
||||||
@include fake-input-field(20px);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__checkbox-presentation {
|
|
||||||
@include fake-input-field(2px);
|
|
||||||
}
|
|
||||||
&__additional-content{
|
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
@ -99,15 +73,18 @@
|
||||||
@media screen and (max-width: 480px) {
|
@media screen and (max-width: 480px) {
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 18px 16px;
|
padding: 18px 16px;
|
||||||
&__description {
|
|
||||||
|
.ppcp--box-description {
|
||||||
margin: 0 0 8px 0;
|
margin: 0 0 8px 0;
|
||||||
}
|
}
|
||||||
&__content {
|
|
||||||
|
.ppcp--box-content {
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 380px) {
|
@media screen and (max-width: 380px) {
|
||||||
&__content > img {
|
.ppcp--box-content > img {
|
||||||
max-width: 32px;
|
max-width: 32px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
// Configuration for this module.
|
||||||
|
$width_container: 938px;
|
||||||
|
$width_header: 280px;
|
||||||
|
$width_gap: 24px;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Styles the `SettingsCard` layout component.
|
Styles the `SettingsCard` layout component.
|
||||||
|
|
||||||
|
@ -14,9 +19,9 @@
|
||||||
--card-layout: block;
|
--card-layout: block;
|
||||||
|
|
||||||
@media screen and (min-width: 960px) {
|
@media screen and (min-width: 960px) {
|
||||||
--card-width-header: 280px;
|
--card-width-header: #{$width_header};
|
||||||
--card-width-content: 610px;
|
--card-width-content: #{$width_container - $width_header - $width_gap};
|
||||||
--card-gap: 48px;
|
--card-gap: #{$width_gap};
|
||||||
--card-layout: flex;
|
--card-layout: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +51,7 @@
|
||||||
&.ppcp--is-card {
|
&.ppcp--is-card {
|
||||||
max-width: var(--card-width-content);
|
max-width: var(--card-width-content);
|
||||||
border: 1px solid var(--color-gray-200);
|
border: 1px solid var(--color-gray-200);
|
||||||
|
width: 100%;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,26 @@
|
||||||
.ppcp-r {
|
.ppcp-r-container {
|
||||||
&-container {
|
max-width: var(--max-container-width, none);
|
||||||
max-width: var(--max-container-width, none);
|
margin: 0 auto 0 35px;
|
||||||
margin-left: auto;
|
}
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-inner-container {
|
.ppcp-r-inner-container {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
padding: 0 16px 48px;
|
padding: 0 16px 48px;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
|
|
||||||
@media screen and (max-width: 480px) {
|
@media screen and (max-width: 480px) {
|
||||||
padding-bottom: 36px;
|
padding-bottom: 36px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-settings {
|
.ppcp-r-settings {
|
||||||
> * {
|
> * {
|
||||||
margin-bottom: $card-vertical-gap;
|
margin-bottom: $card-vertical-gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
> *:not(:last-child) {
|
> *:not(:last-child) {
|
||||||
padding-bottom: $card-vertical-gap;
|
padding-bottom: $card-vertical-gap;
|
||||||
border-bottom: 1px solid $color-gray-200;
|
border-bottom: 1px solid $color-gray-200;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
.ppcp-r-spinner-overlay {
|
.ppcp-r-spinner-overlay {
|
||||||
position: absolute;
|
width: var(--spinner-overlay-width);
|
||||||
left: 0;
|
height: var(--spinner-overlay-height);
|
||||||
top: 0;
|
box-shadow: var(--spinner-overlay-box-shadow);
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 10;
|
|
||||||
background: var(--spinner-overlay-color);
|
background: var(--spinner-overlay-color);
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
.components-spinner {
|
.components-spinner {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -13,5 +15,15 @@
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
width: var(--spinner-size);
|
||||||
|
height: var(--spinner-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp--spinner-message {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
top: calc(50% + 20px + var(--spinner-size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
.ppcp-r-app {
|
||||||
|
.components-flex {
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-align: stretch;
|
||||||
|
align-items: stretch;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-flex.components-h-stack,
|
||||||
|
.ppcp--horizontal {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp--horizontal {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-flex.components-v-stack {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,6 @@
|
||||||
--wp-admin-border-width-focus: 3px;
|
--wp-admin-border-width-focus: 3px;
|
||||||
|
|
||||||
max-width: var(--max-container-width);
|
max-width: var(--max-container-width);
|
||||||
margin: 0 auto;
|
|
||||||
transition: max-width 0.2s;
|
transition: max-width 0.2s;
|
||||||
|
|
||||||
.components-tab-panel__tabs {
|
.components-tab-panel__tabs {
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
.ppcp-r-title-badge{
|
.ppcp-r-title-badge {
|
||||||
|
--badge-bg-color: #F5F5F5;
|
||||||
|
--badge-text-color: #2F2F2F;
|
||||||
|
|
||||||
|
color: var(--badge-text-color);
|
||||||
|
background-color: var(--badge-bg-color);
|
||||||
|
|
||||||
@include font(12, 16, 400);
|
@include font(12, 16, 400);
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
&--positive{
|
|
||||||
color: #144722;
|
&.ppcp-r-title-badge--positive {
|
||||||
background-color: #DAFFE0;
|
--badge-bg-color: #DAFFE0;
|
||||||
|
--badge-text-color: #144722;
|
||||||
}
|
}
|
||||||
&--negative{
|
|
||||||
color:#5c0000;
|
&.ppcp-r-title-badge--negative {
|
||||||
background-color: #faeded;
|
--badge-bg-color: #faeded;
|
||||||
}
|
--badge-text-color: #5c0000;
|
||||||
&--info{
|
|
||||||
color: #2F2F2F;
|
|
||||||
background-color: #F5F5F5;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ body:has(.ppcp-r-container--onboarding) {
|
||||||
.nav-tab-wrapper.woo-nav-tab-wrapper,
|
.nav-tab-wrapper.woo-nav-tab-wrapper,
|
||||||
.woocommerce-layout__header,
|
.woocommerce-layout__header,
|
||||||
.wrap.woocommerce form > h2,
|
.wrap.woocommerce form > h2,
|
||||||
|
#mainform .subsubsub,
|
||||||
#screen-meta-links {
|
#screen-meta-links {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
.ppcp-r-container--onboarding {
|
.ppcp-r-container--onboarding {
|
||||||
--max-container-width: var(--max-width-onboarding);
|
--max-container-width: var(--max-width-onboarding);
|
||||||
|
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
.ppcp-r-inner-container {
|
.ppcp-r-inner-container {
|
||||||
max-width: var(--max-width-onboarding-content);
|
max-width: var(--max-width-onboarding-content);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,33 +107,26 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ppcp-r-feature-item {
|
.ppcp-r-tab-overview-features {
|
||||||
padding-top: 32px;
|
--block-header-gap: 12px;
|
||||||
border-top: 1px solid $color-gray-400;
|
}
|
||||||
|
|
||||||
&__title {
|
.ppcp-r-tab-overview-help {
|
||||||
@include font(16, 20, 600);
|
--block-header-gap: 8px;
|
||||||
color: $color-black;
|
}
|
||||||
display: block;
|
|
||||||
margin: 0 0 8px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__description {
|
.ppcp-r-settings-block__feature {
|
||||||
@include font(14, 20, 400);
|
.ppcp--action-buttons {
|
||||||
color: $color-gray-800;
|
|
||||||
margin: 0 0 18px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:last-child) {
|
|
||||||
padding-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__buttons {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 18px;
|
gap: 18px;
|
||||||
|
|
||||||
|
.components-button.is-tertiary {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__notes {
|
.ppcp--item-notes {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,20 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix the checkbox layout (add gap between checkbox and label).
|
||||||
|
.components-checkbox-control > .components-base-control__field > .components-flex {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix layout for radio groups inside a horizontal flex-stack.
|
||||||
|
.components-flex.components-h-stack > .components-radio-control {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.components-radio-control__group-wrapper {
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.ppcp-r-paylater-configurator {
|
.ppcp-r-paylater-configurator {
|
||||||
display: flex;
|
display: flex;
|
||||||
border: 1px solid var(--color-separators);
|
border: 1px solid var(--color-separators);
|
||||||
border-radius: 8px;
|
border-radius: var(--container-border-radius);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: "PayPalPro", sans-serif;
|
font-family: "PayPalPro", sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|
|
@ -7,3 +7,25 @@
|
||||||
--block-header-gap: 0;
|
--block-header-gap: 0;
|
||||||
--block-separator-size: 0;
|
--block-separator-size: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ppcp--webhooks {
|
||||||
|
.ppcp--webhook-list li {
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '✔︎';
|
||||||
|
opacity: 0.35;
|
||||||
|
font-size: 0.75em;
|
||||||
|
line-height: 1.35;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ppcp--webhook-resubscribe,
|
||||||
|
.ppcp--webhook-simulation {
|
||||||
|
.ppcp--action .components-button {
|
||||||
|
min-width: 160px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
border: 1px solid var(--color-separators);
|
border: 1px solid var(--color-separators);
|
||||||
border-radius: 8px;
|
border-radius: var(--container-border-radius);
|
||||||
|
|
||||||
.ppcp-r-settings-block {
|
.ppcp-r-settings-block {
|
||||||
&.header-section {
|
&.header-section {
|
||||||
|
|
|
@ -9,7 +9,12 @@ const ControlButton = ( {
|
||||||
buttonLabel,
|
buttonLabel,
|
||||||
} ) => (
|
} ) => (
|
||||||
<Action>
|
<Action>
|
||||||
<Button isBusy={ isBusy } variant={ type } onClick={ onClick }>
|
<Button
|
||||||
|
className="small-button"
|
||||||
|
isBusy={ isBusy }
|
||||||
|
variant={ type }
|
||||||
|
onClick={ onClick }
|
||||||
|
>
|
||||||
{ buttonLabel }
|
{ buttonLabel }
|
||||||
</Button>
|
</Button>
|
||||||
</Action>
|
</Action>
|
||||||
|
|
|
@ -10,6 +10,7 @@ const ControlTextInput = ( {
|
||||||
} ) => (
|
} ) => (
|
||||||
<Action>
|
<Action>
|
||||||
<TextControl
|
<TextControl
|
||||||
|
__nextHasNoMarginBottom={ true }
|
||||||
className="ppcp-r-vertical-text-control"
|
className="ppcp-r-vertical-text-control"
|
||||||
placeholder={ placeholder }
|
placeholder={ placeholder }
|
||||||
value={ value }
|
value={ value }
|
||||||
|
|
|
@ -24,6 +24,7 @@ const Checkbox = ( {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CheckboxControl
|
<CheckboxControl
|
||||||
|
__nextHasNoMarginBottom={ true }
|
||||||
label={ label }
|
label={ label }
|
||||||
value={ value }
|
value={ value }
|
||||||
checked={ checked }
|
checked={ checked }
|
||||||
|
|
|
@ -1,15 +1,39 @@
|
||||||
import { PayPalCheckbox } from './index';
|
import { PayPalCheckbox } from './index';
|
||||||
|
import { useCallback } from '@wordpress/element';
|
||||||
|
|
||||||
const CheckboxGroup = ( { options, value, onChange } ) => {
|
const CheckboxGroup = ( { name, options, value, onChange } ) => {
|
||||||
const handleChange = ( key, checked ) => {
|
const handleChange = useCallback(
|
||||||
const getNewValue = () => {
|
( key, checked ) => {
|
||||||
if ( checked ) {
|
const getNewValue = () => {
|
||||||
return [ ...value, key ];
|
if ( 'boolean' === typeof value ) {
|
||||||
}
|
return checked;
|
||||||
return value.filter( ( val ) => val !== key );
|
}
|
||||||
};
|
|
||||||
|
|
||||||
onChange( getNewValue() );
|
if ( checked ) {
|
||||||
|
return [ ...value, key ];
|
||||||
|
}
|
||||||
|
return value.filter( ( val ) => val !== key );
|
||||||
|
};
|
||||||
|
|
||||||
|
onChange( getNewValue() );
|
||||||
|
},
|
||||||
|
[ onChange, value ]
|
||||||
|
);
|
||||||
|
|
||||||
|
const isItemChecked = ( checked, itemValue ) => {
|
||||||
|
if ( typeof checked === 'boolean' ) {
|
||||||
|
return checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Array.isArray( value ) ) {
|
||||||
|
return value.includes( itemValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( typeof value === 'boolean' ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value === itemValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -21,16 +45,14 @@ const CheckboxGroup = ( { options, value, onChange } ) => {
|
||||||
checked,
|
checked,
|
||||||
disabled,
|
disabled,
|
||||||
description,
|
description,
|
||||||
tooltip,
|
|
||||||
} ) => (
|
} ) => (
|
||||||
<PayPalCheckbox
|
<PayPalCheckbox
|
||||||
key={ itemValue }
|
key={ name + itemValue }
|
||||||
value={ itemValue }
|
value={ itemValue }
|
||||||
label={ label }
|
label={ label }
|
||||||
checked={ checked }
|
checked={ isItemChecked( checked, itemValue ) }
|
||||||
disabled={ disabled }
|
disabled={ disabled }
|
||||||
description={ description }
|
description={ description }
|
||||||
tooltip={ tooltip }
|
|
||||||
changeCallback={ handleChange }
|
changeCallback={ handleChange }
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,10 +49,12 @@ const OptionItem = ( {
|
||||||
} ) => {
|
} ) => {
|
||||||
const boxClassName = classNames( 'ppcp-r-select-box', {
|
const boxClassName = classNames( 'ppcp-r-select-box', {
|
||||||
'ppcp--selected': isSelected,
|
'ppcp--selected': isSelected,
|
||||||
|
'ppcp--multiselect': isMulti,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ boxClassName }>
|
// eslint-disable-next-line jsx-a11y/label-has-associated-control -- label has a nested input control.
|
||||||
|
<label className={ boxClassName }>
|
||||||
<InputField
|
<InputField
|
||||||
value={ itemValue }
|
value={ itemValue }
|
||||||
isRadio={ ! isMulti }
|
isRadio={ ! isMulti }
|
||||||
|
@ -60,22 +62,16 @@ const OptionItem = ( {
|
||||||
isSelected={ isSelected }
|
isSelected={ isSelected }
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="ppcp-r-select-box__content">
|
<div className="ppcp--box-content">
|
||||||
<div className="ppcp-r-select-box__content-inner">
|
<div className="ppcp--box-content-inner">
|
||||||
<span className="ppcp-r-select-box__title">
|
<span className="ppcp--box-title">{ itemTitle }</span>
|
||||||
{ itemTitle }
|
<p className="ppcp--box-description">{ itemDescription }</p>
|
||||||
</span>
|
|
||||||
<p className="ppcp-r-select-box__description">
|
|
||||||
{ itemDescription }
|
|
||||||
</p>
|
|
||||||
{ children && (
|
{ children && (
|
||||||
<div className="ppcp-r-select-box__additional-content">
|
<div className="ppcp--box-details">{ children }</div>
|
||||||
{ children }
|
|
||||||
</div>
|
|
||||||
) }
|
) }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</label>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/**
|
|
||||||
* Temporary component, until the experimental HStack block editor component is stable.
|
|
||||||
*
|
|
||||||
* @see https://wordpress.github.io/gutenberg/?path=/docs/components-experimental-hstack--docs
|
|
||||||
* @file
|
|
||||||
*/
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
const HStack = ( { className, spacing = 3, children } ) => {
|
|
||||||
const wrapperClass = classNames(
|
|
||||||
'components-flex components-h-stack',
|
|
||||||
className
|
|
||||||
);
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
gap: `calc(${ 4 * spacing }px)`,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ wrapperClass } style={ styles }>
|
|
||||||
{ children }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HStack;
|
|
|
@ -1,15 +1,20 @@
|
||||||
|
import { Icon } from '@wordpress/components';
|
||||||
|
|
||||||
import data from '../../utils/data';
|
import data from '../../utils/data';
|
||||||
|
|
||||||
const PaymentMethodIcon = ( props ) => {
|
const PaymentMethodIcon = ( { icons, type } ) => {
|
||||||
if (
|
const validIcon = Array.isArray( icons ) && icons.includes( type );
|
||||||
( Array.isArray( props.icons ) &&
|
|
||||||
props.icons.includes( props.type ) ) ||
|
if ( validIcon || icons === 'all' ) {
|
||||||
props.icons === 'all'
|
return (
|
||||||
) {
|
<Icon
|
||||||
return data().getImage( 'icon-button-' + props.type + '.svg' );
|
icon={ data().getImage( 'icon-button-' + type + '.svg' ) }
|
||||||
|
className="ppcp--method-icon"
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <></>;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PaymentMethodIcon;
|
export default PaymentMethodIcon;
|
||||||
|
|
|
@ -15,22 +15,6 @@ const SettingsBlock = ( {
|
||||||
'ppcp--horizontal': horizontalLayout,
|
'ppcp--horizontal': horizontalLayout,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
const BlockTitle = ( { blockTitle, blockSuffix, blockDescription } ) => {
|
|
||||||
if ( ! blockTitle && ! blockDescription ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Header>
|
|
||||||
<Title>
|
|
||||||
{ blockTitle }
|
|
||||||
<TitleExtra>{ blockSuffix }</TitleExtra>
|
|
||||||
</Title>
|
|
||||||
<Description>{ blockDescription }</Description>
|
|
||||||
</Header>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ blockClassName }>
|
<div className={ blockClassName }>
|
||||||
<BlockTitle
|
<BlockTitle
|
||||||
|
@ -45,3 +29,19 @@ const SettingsBlock = ( {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SettingsBlock;
|
export default SettingsBlock;
|
||||||
|
|
||||||
|
const BlockTitle = ( { blockTitle, blockSuffix, blockDescription } ) => {
|
||||||
|
if ( ! blockTitle && ! blockDescription ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Header>
|
||||||
|
<Title>
|
||||||
|
{ blockTitle }
|
||||||
|
<TitleExtra>{ blockSuffix }</TitleExtra>
|
||||||
|
</Title>
|
||||||
|
<Description>{ blockDescription }</Description>
|
||||||
|
</Header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="ppcp-r-feature-item__notes">
|
<span className="ppcp--item-notes">
|
||||||
{ notes.map( ( note, index ) => (
|
{ notes.map( ( note, index ) => (
|
||||||
<span key={ index }>{ note }</span>
|
<span key={ index }>{ note }</span>
|
||||||
) ) }
|
) ) }
|
||||||
|
@ -20,30 +20,39 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderButton = ( button ) => {
|
const FeatureButton = ( {
|
||||||
const buttonElement = (
|
className,
|
||||||
<Button
|
variant,
|
||||||
className={ button.class ? button.class : '' }
|
text,
|
||||||
key={ button.text }
|
isBusy,
|
||||||
isBusy={ props.actionProps?.isBusy }
|
url,
|
||||||
variant={ button.type }
|
urls,
|
||||||
onClick={ button.onClick }
|
onClick,
|
||||||
>
|
} ) => {
|
||||||
{ button.text }
|
const buttonProps = {
|
||||||
</Button>
|
className,
|
||||||
);
|
isBusy,
|
||||||
|
variant,
|
||||||
|
};
|
||||||
|
|
||||||
// If there's a URL (either direct or in urls object), wrap in anchor tag
|
if ( url || urls ) {
|
||||||
if ( button.url || button.urls ) {
|
buttonProps.href = urls ? urls.live : url;
|
||||||
const href = button.urls ? button.urls.live : button.url;
|
buttonProps.target = '_blank';
|
||||||
return (
|
}
|
||||||
<a href={ href } key={ button.text }>
|
if ( ! buttonProps.href ) {
|
||||||
{ buttonElement }
|
buttonProps.onClick = onClick;
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buttonElement;
|
return <Button { ...buttonProps }>{ text }</Button>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderDescription = () => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className="ppcp-r-feature-item__description ppcp-r-settings-block__feature__description"
|
||||||
|
dangerouslySetInnerHTML={ { __html: description } }
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -56,13 +65,33 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
|
||||||
) }
|
) }
|
||||||
</Title>
|
</Title>
|
||||||
<Description className="ppcp-r-settings-block__feature__description">
|
<Description className="ppcp-r-settings-block__feature__description">
|
||||||
{ description }
|
{ renderDescription() }
|
||||||
{ printNotes() }
|
{ printNotes() }
|
||||||
</Description>
|
</Description>
|
||||||
</Header>
|
</Header>
|
||||||
<Action>
|
<Action>
|
||||||
<div className="ppcp-r-feature-item__buttons">
|
<div className="ppcp--action-buttons">
|
||||||
{ props.actionProps?.buttons.map( renderButton ) }
|
{ props.actionProps?.buttons.map(
|
||||||
|
( {
|
||||||
|
class: className,
|
||||||
|
type,
|
||||||
|
text,
|
||||||
|
url,
|
||||||
|
urls,
|
||||||
|
onClick,
|
||||||
|
} ) => (
|
||||||
|
<FeatureButton
|
||||||
|
key={ text }
|
||||||
|
className={ className }
|
||||||
|
variant={ type }
|
||||||
|
text={ text }
|
||||||
|
isBusy={ props.actionProps.isBusy }
|
||||||
|
url={ url }
|
||||||
|
urls={ urls }
|
||||||
|
onClick={ onClick }
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
) }
|
||||||
</div>
|
</div>
|
||||||
</Action>
|
</Action>
|
||||||
</SettingsBlock>
|
</SettingsBlock>
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { ToggleControl } from '@wordpress/components';
|
||||||
|
|
||||||
import SettingsBlock from '../SettingsBlock';
|
import SettingsBlock from '../SettingsBlock';
|
||||||
import PaymentMethodIcon from '../PaymentMethodIcon';
|
import PaymentMethodIcon from '../PaymentMethodIcon';
|
||||||
import data from '../../../utils/data';
|
|
||||||
|
|
||||||
const PaymentMethodItemBlock = ( {
|
const PaymentMethodItemBlock = ( {
|
||||||
paymentMethod,
|
paymentMethod,
|
||||||
|
@ -11,33 +10,35 @@ const PaymentMethodItemBlock = ( {
|
||||||
isSelected,
|
isSelected,
|
||||||
} ) => {
|
} ) => {
|
||||||
return (
|
return (
|
||||||
<SettingsBlock className="ppcp-r-settings-block__payment-methods__item">
|
<SettingsBlock className="ppcp--method-item" separatorAndGap={ false }>
|
||||||
<div className="ppcp-r-settings-block__payment-methods__item__inner">
|
<div className="ppcp--method-inner">
|
||||||
<div className="ppcp-r-settings-block__payment-methods__item__title-wrapper">
|
<div className="ppcp--method-title-wrapper">
|
||||||
<PaymentMethodIcon
|
{ paymentMethod?.icon && (
|
||||||
icons={ [ paymentMethod.icon ] }
|
<PaymentMethodIcon
|
||||||
type={ paymentMethod.icon }
|
icons={ [ paymentMethod.icon ] }
|
||||||
/>
|
type={ paymentMethod.icon }
|
||||||
<span className="ppcp-r-settings-block__payment-methods__item__title">
|
/>
|
||||||
|
) }
|
||||||
|
<span className="ppcp--method-title">
|
||||||
{ paymentMethod.itemTitle }
|
{ paymentMethod.itemTitle }
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="ppcp-r-settings-block__payment-methods__item__description">
|
<p className="ppcp--method-description">
|
||||||
{ paymentMethod.itemDescription }
|
{ paymentMethod.itemDescription }
|
||||||
</p>
|
</p>
|
||||||
<div className="ppcp-r-settings-block__payment-methods__item__footer">
|
<div className="ppcp--method-footer">
|
||||||
<ToggleControl
|
<ToggleControl
|
||||||
__nextHasNoMarginBottom={ true }
|
__nextHasNoMarginBottom={ true }
|
||||||
checked={ isSelected }
|
checked={ isSelected }
|
||||||
onChange={ onSelect }
|
onChange={ onSelect }
|
||||||
/>
|
/>
|
||||||
{ paymentMethod?.fields && onTriggerModal && (
|
{ paymentMethod?.fields && onTriggerModal && (
|
||||||
<div
|
<Button
|
||||||
className="ppcp-r-settings-block__payment-methods__item__settings"
|
className="ppcp--method-settings"
|
||||||
onClick={ onTriggerModal }
|
onClick={ onTriggerModal }
|
||||||
>
|
>
|
||||||
{ data().getImage( 'icon-settings.svg' ) }
|
<Icon icon={ cog } />
|
||||||
</div>
|
</Button>
|
||||||
) }
|
) }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,42 +1,38 @@
|
||||||
import SettingsBlock from '../SettingsBlock';
|
import SettingsBlock from '../SettingsBlock';
|
||||||
import PaymentMethodItemBlock from './PaymentMethodItemBlock';
|
import PaymentMethodItemBlock from './PaymentMethodItemBlock';
|
||||||
import { usePaymentMethods } from '../../../data/payment/hooks';
|
import { PaymentHooks } from '../../../data';
|
||||||
|
|
||||||
const PaymentMethodsBlock = ( {
|
// TODO: This is not a reusable component, as it's connected to the Redux store.
|
||||||
paymentMethods,
|
const PaymentMethodsBlock = ( { paymentMethods = [], onTriggerModal } ) => {
|
||||||
className = '',
|
const { changePaymentSettings } = PaymentHooks.useStore();
|
||||||
onTriggerModal,
|
|
||||||
} ) => {
|
|
||||||
const { setPersistent } = usePaymentMethods();
|
|
||||||
|
|
||||||
if ( ! paymentMethods?.length ) {
|
const handleSelect = ( methodId, isSelected ) =>
|
||||||
|
changePaymentSettings( methodId, {
|
||||||
|
enabled: isSelected,
|
||||||
|
} );
|
||||||
|
|
||||||
|
if ( ! paymentMethods.length ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSelect = ( paymentMethod, isSelected ) => {
|
|
||||||
setPersistent( paymentMethod.id, {
|
|
||||||
...paymentMethod,
|
|
||||||
enabled: isSelected,
|
|
||||||
} );
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsBlock
|
<SettingsBlock className="ppcp--grid ppcp-r-settings-block__payment-methods">
|
||||||
className={ `ppcp-r-settings-block__payment-methods ${ className }` }
|
{ paymentMethods
|
||||||
>
|
// Remove empty/invalid payment method entries.
|
||||||
{ paymentMethods.map( ( paymentMethod ) => (
|
.filter( ( m ) => m.id )
|
||||||
<PaymentMethodItemBlock
|
.map( ( paymentMethod ) => (
|
||||||
key={ paymentMethod.id }
|
<PaymentMethodItemBlock
|
||||||
paymentMethod={ paymentMethod }
|
key={ paymentMethod.id }
|
||||||
isSelected={ paymentMethod.enabled }
|
paymentMethod={ paymentMethod }
|
||||||
onSelect={ ( checked ) =>
|
isSelected={ paymentMethod.enabled }
|
||||||
handleSelect( paymentMethod, checked )
|
onSelect={ ( checked ) =>
|
||||||
}
|
handleSelect( paymentMethod.id, checked )
|
||||||
onTriggerModal={ () =>
|
}
|
||||||
onTriggerModal?.( paymentMethod.id )
|
onTriggerModal={ () =>
|
||||||
}
|
onTriggerModal?.( paymentMethod.id )
|
||||||
/>
|
}
|
||||||
) ) }
|
/>
|
||||||
|
) ) }
|
||||||
</SettingsBlock>
|
</SettingsBlock>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,55 +1,47 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { Content, ContentWrapper } from './Elements';
|
import { Content } from './Elements';
|
||||||
|
|
||||||
const SettingsCard = ( {
|
const SettingsCard = ( {
|
||||||
id,
|
id,
|
||||||
className: extraClassName,
|
className,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
children,
|
children,
|
||||||
contentItems,
|
|
||||||
contentContainer = true,
|
contentContainer = true,
|
||||||
} ) => {
|
} ) => {
|
||||||
const className = classNames( 'ppcp-r-settings-card', extraClassName );
|
const cardClassNames = classNames( 'ppcp-r-settings-card', className );
|
||||||
|
const cardProps = {
|
||||||
const renderContent = () => {
|
className: cardClassNames,
|
||||||
// If contentItems array is provided, wrap each item in Content component
|
id,
|
||||||
if ( contentItems ) {
|
|
||||||
return (
|
|
||||||
<ContentWrapper>
|
|
||||||
{ contentItems.map( ( item ) => (
|
|
||||||
<Content key={ item.key } id={ item.key }>
|
|
||||||
{ item }
|
|
||||||
</Content>
|
|
||||||
) ) }
|
|
||||||
</ContentWrapper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise handle regular children with contentContainer prop
|
|
||||||
if ( contentContainer ) {
|
|
||||||
return <Content>{ children }</Content>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return children;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id={ id } className={ className }>
|
<div { ...cardProps }>
|
||||||
<div className="ppcp-r-settings-card__header">
|
<div className="ppcp-r-settings-card__header">
|
||||||
<div className="ppcp-r-settings-card__content-inner">
|
<div className="ppcp-r-settings-card__content-inner">
|
||||||
<span className="ppcp-r-settings-card__title">
|
<span className="ppcp-r-settings-card__title">
|
||||||
{ title }
|
{ title }
|
||||||
</span>
|
</span>
|
||||||
<p className="ppcp-r-settings-card__description">
|
<div className="ppcp-r-settings-card__description">
|
||||||
{ description }
|
{ description }
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{ renderContent() }
|
|
||||||
|
<InnerContent showCards={ contentContainer }>
|
||||||
|
{ children }
|
||||||
|
</InnerContent>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SettingsCard;
|
export default SettingsCard;
|
||||||
|
|
||||||
|
const InnerContent = ( { showCards, children } ) => {
|
||||||
|
if ( showCards ) {
|
||||||
|
return <Content>{ children }</Content>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
};
|
||||||
|
|
|
@ -9,9 +9,7 @@ const SpinnerOverlay = ( { message = null } ) => {
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-spinner-overlay">
|
<div className="ppcp-r-spinner-overlay">
|
||||||
{ message && (
|
{ message && (
|
||||||
<span className="ppcp-r-spinner-overlay__message">
|
<span className="ppcp--spinner-message">{ message }</span>
|
||||||
{ message }
|
|
||||||
</span>
|
|
||||||
) }
|
) }
|
||||||
<Spinner />
|
<Spinner />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* Temporary component, until the experimental VStack/HStack block editor component is stable.
|
||||||
|
*
|
||||||
|
* @see https://wordpress.github.io/gutenberg/?path=/docs/components-experimental-hstack--docs
|
||||||
|
* @see https://wordpress.github.io/gutenberg/?path=/docs/components-experimental-vstack--docs
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
const Stack = ( { type, className, spacing, children } ) => {
|
||||||
|
const wrapperClass = classNames(
|
||||||
|
'components-flex',
|
||||||
|
`components-${ type }-stack`,
|
||||||
|
className
|
||||||
|
);
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
gap: `calc(${ 4 * spacing }px)`,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ wrapperClass } style={ styles }>
|
||||||
|
{ children }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HStack = ( { className, spacing = 3, children } ) => {
|
||||||
|
return (
|
||||||
|
<Stack type="h" className={ className } spacing={ spacing }>
|
||||||
|
{ children }
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const VStack = ( { className, spacing = 3, children } ) => {
|
||||||
|
return (
|
||||||
|
<Stack type="v" className={ className } spacing={ spacing }>
|
||||||
|
{ children }
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,134 +0,0 @@
|
||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
|
|
||||||
import SettingsCard from '../../ReusableComponents/SettingsCard';
|
|
||||||
import { PaymentMethodsBlock } from '../../ReusableComponents/SettingsBlocks';
|
|
||||||
import { PaymentHooks } from '../../../data';
|
|
||||||
import { useActiveModal } from '../../../data/common/hooks';
|
|
||||||
import Modal from './TabSettingsElements/Blocks/Modal';
|
|
||||||
import { usePaymentMethods } from '../../../data/payment/hooks';
|
|
||||||
|
|
||||||
const TabPaymentMethods = () => {
|
|
||||||
const { paymentMethodsPayPalCheckout } =
|
|
||||||
PaymentHooks.usePaymentMethodsPayPalCheckout();
|
|
||||||
const { paymentMethodsOnlineCardPayments } =
|
|
||||||
PaymentHooks.usePaymentMethodsOnlineCardPayments();
|
|
||||||
const { paymentMethodsAlternative } =
|
|
||||||
PaymentHooks.usePaymentMethodsAlternative();
|
|
||||||
|
|
||||||
const { setPersistent } = usePaymentMethods();
|
|
||||||
|
|
||||||
const { activeModal, setActiveModal } = useActiveModal();
|
|
||||||
|
|
||||||
const getActiveMethod = () => {
|
|
||||||
if ( ! activeModal ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const allMethods = [
|
|
||||||
...paymentMethodsPayPalCheckout,
|
|
||||||
...paymentMethodsOnlineCardPayments,
|
|
||||||
...paymentMethodsAlternative,
|
|
||||||
];
|
|
||||||
|
|
||||||
return allMethods.find( ( method ) => method.id === activeModal );
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="ppcp-r-payment-methods">
|
|
||||||
<SettingsCard
|
|
||||||
id="ppcp-paypal-checkout-card"
|
|
||||||
title={ __( 'PayPal Checkout', 'woocommerce-paypal-payments' ) }
|
|
||||||
description={ __(
|
|
||||||
'Select your preferred checkout option with PayPal for easy payment processing.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
icon="icon-checkout-standard.svg"
|
|
||||||
contentContainer={ false }
|
|
||||||
>
|
|
||||||
<PaymentMethodsBlock
|
|
||||||
paymentMethods={ paymentMethodsPayPalCheckout }
|
|
||||||
onTriggerModal={ setActiveModal }
|
|
||||||
/>
|
|
||||||
</SettingsCard>
|
|
||||||
<SettingsCard
|
|
||||||
id="ppcp-card-payments-card"
|
|
||||||
title={ __(
|
|
||||||
'Online Card Payments',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
description={ __(
|
|
||||||
'Select your preferred card payment options for efficient payment processing.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
icon="icon-checkout-online-methods.svg"
|
|
||||||
contentContainer={ false }
|
|
||||||
>
|
|
||||||
<PaymentMethodsBlock
|
|
||||||
paymentMethods={ paymentMethodsOnlineCardPayments }
|
|
||||||
onTriggerModal={ setActiveModal }
|
|
||||||
/>
|
|
||||||
</SettingsCard>
|
|
||||||
<SettingsCard
|
|
||||||
id="ppcp-alternative-payments-card"
|
|
||||||
title={ __(
|
|
||||||
'Alternative Payment Methods',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
description={ __(
|
|
||||||
'With alternative payment methods, customers across the globe can pay with their bank accounts and other local payment methods.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
icon="icon-checkout-alternative-methods.svg"
|
|
||||||
contentContainer={ false }
|
|
||||||
>
|
|
||||||
<PaymentMethodsBlock
|
|
||||||
paymentMethods={ paymentMethodsAlternative }
|
|
||||||
onTriggerModal={ setActiveModal }
|
|
||||||
/>
|
|
||||||
</SettingsCard>
|
|
||||||
|
|
||||||
{ activeModal && (
|
|
||||||
<Modal
|
|
||||||
method={ getActiveMethod() }
|
|
||||||
setModalIsVisible={ () => setActiveModal( null ) }
|
|
||||||
onSave={ ( methodId, settings ) => {
|
|
||||||
setPersistent( methodId, {
|
|
||||||
...getActiveMethod(),
|
|
||||||
title: settings.checkoutPageTitle,
|
|
||||||
description: settings.checkoutPageDescription,
|
|
||||||
} );
|
|
||||||
|
|
||||||
if ( 'paypalShowLogo' in settings ) {
|
|
||||||
setPersistent(
|
|
||||||
'paypalShowLogo',
|
|
||||||
settings.paypalShowLogo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ( 'threeDSecure' in settings ) {
|
|
||||||
setPersistent(
|
|
||||||
'threeDSecure',
|
|
||||||
settings.threeDSecure
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ( 'fastlaneCardholderName' in settings ) {
|
|
||||||
setPersistent(
|
|
||||||
'fastlaneCardholderName',
|
|
||||||
settings.fastlaneCardholderName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ( 'fastlaneDisplayWatermark' in settings ) {
|
|
||||||
setPersistent(
|
|
||||||
'fastlaneDisplayWatermark',
|
|
||||||
settings.fastlaneDisplayWatermark
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
setActiveModal( null );
|
|
||||||
} }
|
|
||||||
/>
|
|
||||||
) }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TabPaymentMethods;
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
import { Button } from '@wordpress/components';
|
||||||
|
|
||||||
import Container from '../ReusableComponents/Container';
|
import Container from '../ReusableComponents/Container';
|
||||||
import SettingsCard from '../ReusableComponents/SettingsCard';
|
import SettingsCard from '../ReusableComponents/SettingsCard';
|
||||||
|
@ -9,7 +10,7 @@ const SendOnlyMessage = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingsNavigation />
|
<SettingsNavigation canSave={ false } />
|
||||||
<Container page="settings">
|
<Container page="settings">
|
||||||
<SettingsCard
|
<SettingsCard
|
||||||
title={ __(
|
title={ __(
|
||||||
|
@ -45,6 +46,19 @@ const SendOnlyMessage = () => {
|
||||||
),
|
),
|
||||||
} }
|
} }
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
href={ settingsPageUrl }
|
||||||
|
variant="primary"
|
||||||
|
className="small-button"
|
||||||
|
>
|
||||||
|
{ __(
|
||||||
|
'Go to WooCommerce settings',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</SettingsCard>
|
</SettingsCard>
|
||||||
</Container>
|
</Container>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -2,21 +2,20 @@ import { Button } from '@wordpress/components';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
import TopNavigation from '../../../ReusableComponents/TopNavigation';
|
import TopNavigation from '../../../ReusableComponents/TopNavigation';
|
||||||
import BusyStateWrapper from '../../../ReusableComponents/BusyStateWrapper';
|
|
||||||
import { useSaveSettings } from '../../../../hooks/useSaveSettings';
|
import { useSaveSettings } from '../../../../hooks/useSaveSettings';
|
||||||
|
|
||||||
const SettingsNavigation = () => {
|
const SettingsNavigation = ( { canSave = true } ) => {
|
||||||
const { persistAll } = useSaveSettings();
|
const { persistAll } = useSaveSettings();
|
||||||
|
|
||||||
const title = __( 'PayPal Payments', 'woocommerce-paypal-payments' );
|
const title = __( 'PayPal Payments', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TopNavigation title={ title } exitOnTitleClick={ true }>
|
<TopNavigation title={ title } exitOnTitleClick={ true }>
|
||||||
<BusyStateWrapper>
|
{ canSave && (
|
||||||
<Button variant="primary" onClick={ persistAll }>
|
<Button variant="primary" onClick={ persistAll }>
|
||||||
{ __( 'Save', 'woocommerce-paypal-payments' ) }
|
{ __( 'Save', 'woocommerce-paypal-payments' ) }
|
||||||
</Button>
|
</Button>
|
||||||
</BusyStateWrapper>
|
) }
|
||||||
</TopNavigation>
|
</TopNavigation>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { TAB_IDS, selectTab } from '../../../../../utils/tabSelector';
|
import { TAB_IDS, selectTab } from '../../../../../utils/tabSelector';
|
||||||
|
import { payLaterMessaging } from './pay-later-messaging';
|
||||||
|
|
||||||
const Features = {
|
export const getFeatures = ( setActiveModal ) => {
|
||||||
getFeatures: ( setActiveModal ) => [
|
const storeCountry = ppcpSettings?.storeCountry;
|
||||||
|
const features = [
|
||||||
{
|
{
|
||||||
id: 'save_paypal_and_venmo',
|
id: 'save_paypal_and_venmo',
|
||||||
title: __( 'Save PayPal and Venmo', 'woocommerce-paypal-payments' ),
|
title: __( 'Save PayPal and Venmo', 'woocommerce-paypal-payments' ),
|
||||||
|
@ -39,7 +41,10 @@ const Features = {
|
||||||
{
|
{
|
||||||
type: 'tertiary',
|
type: 'tertiary',
|
||||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||||
url: 'https://developer.paypal.com/studio/checkout/standard',
|
urls: {
|
||||||
|
sandbox: '#',
|
||||||
|
live: '#',
|
||||||
|
},
|
||||||
class: 'small-button',
|
class: 'small-button',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -230,7 +235,16 @@ const Features = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
];
|
||||||
|
|
||||||
|
const countryData = payLaterMessaging[ storeCountry ] || {};
|
||||||
|
|
||||||
|
// Add "Pay Later Messaging" to the feature list, if it's available.
|
||||||
|
if (
|
||||||
|
!! window.ppcpSettings?.isPayLaterConfiguratorAvailable &&
|
||||||
|
countryData
|
||||||
|
) {
|
||||||
|
features.push( {
|
||||||
id: 'pay_later_messaging',
|
id: 'pay_later_messaging',
|
||||||
title: __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ),
|
title: __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ),
|
||||||
description: __(
|
description: __(
|
||||||
|
@ -269,8 +283,8 @@ const Features = {
|
||||||
class: 'small-button',
|
class: 'small-button',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
} );
|
||||||
],
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export default Features;
|
return features;
|
||||||
|
};
|
|
@ -0,0 +1,106 @@
|
||||||
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
|
||||||
|
export const payLaterMessaging = {
|
||||||
|
US: {
|
||||||
|
description: sprintf(
|
||||||
|
__(
|
||||||
|
'Your customers can already buy now and pay later with PayPal — add messaging to your site to let them know. PayPal’s Pay Later helps boost merchants\' conversion rates and increases cart sizes by 39%%.¹ You get paid in full up front. <a target="_blank" href="%s">More about Pay Later</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/accept-payments/checkout/installments'
|
||||||
|
),
|
||||||
|
notes: [
|
||||||
|
__( '¹PayPal Q2 Earnings-2021.', 'woocommerce-paypal-payments' ),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
GB: {
|
||||||
|
description: sprintf(
|
||||||
|
__(
|
||||||
|
'Your customers can already buy now and pay later with PayPal — add messaging to your site to let them know. Pay in 3 gets a 216%% higher Average Order Value than a standard PayPal transaction.¹ There’s <strong>no extra cost</strong> and you get paid up front. <a target="_blank" href="%s">More about Pay in 3</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/uk/business/accept-payments/checkout/installments'
|
||||||
|
),
|
||||||
|
notes: [
|
||||||
|
__(
|
||||||
|
'Based on PayPal internal data from Q1 2022, results include Pay in 3 (UK).',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
FR: {
|
||||||
|
description: sprintf(
|
||||||
|
__(
|
||||||
|
'Your customers can already buy now and pay later with PayPal — add messaging to your site to let them know. Pay in 4x gets a 65%% higher Average Order Value than a standard PayPal transaction.¹ <strong>There\'s no extra cost on top of your PayPal Checkout rate</strong>, and you get paid up front. <a target="_blank" href="%s">More about Pay in 4x</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/fr/business/accept-payments/checkout/installments'
|
||||||
|
),
|
||||||
|
notes: [
|
||||||
|
__(
|
||||||
|
'Internal Data Analysis of 1124 SMB across integrated partners and non-integrated partners, November 2022. SMB internally defined as up to 100,000€ in annual estimated ecommerce online payment volume.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
AU: {
|
||||||
|
description: sprintf(
|
||||||
|
__(
|
||||||
|
'Your customers can already buy now and pay later with PayPal — add messaging to your site to let them know. Pay in 4 gets more than a 100%% higher Average Order Value than a standard PayPal transaction.¹ There’s <strong>no extra cost</strong> and you get paid up front. <a target="_blank" href="%s">More about Pay in 4</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/au/business/accept-payments/checkout/installments'
|
||||||
|
),
|
||||||
|
notes: [
|
||||||
|
__(
|
||||||
|
'Based on PayPal internal data from Q1 2022, results include Pay in 4 (AU). Consumer eligibility applies.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
IT: {
|
||||||
|
description: sprintf(
|
||||||
|
__(
|
||||||
|
'Your customers can already buy now and pay later with PayPal — add messaging to your site to let them know. Pay in 3 installments gets about a 275%% higher Average Order Value than a standard PayPal transaction.¹ <strong>There\'s no extra cost on top of your PayPal Checkout rate</strong>, and you get paid up front. <a target="_blank" href="%s">More about Pay in 3 installments</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/it/business/accept-payments/checkout/installments'
|
||||||
|
),
|
||||||
|
notes: [
|
||||||
|
__(
|
||||||
|
'Based on PayPal internal data from Q1 2022, results include Pay in 3 installments (IT).',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
ES: {
|
||||||
|
description: sprintf(
|
||||||
|
__(
|
||||||
|
'Your customers can already buy now and pay later with PayPal — add messaging to your site to let them know. Pay in 3 installments gets about a 275%% higher Average Order Value than a standard PayPal transaction.¹ <strong>There\'s no extra cost on top of your PayPal Checkout rate</strong>, and you get paid up front. <a target="_blank" href="%s">More about Pay in 3 installments</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/es/business/accept-payments/checkout/installments'
|
||||||
|
),
|
||||||
|
notes: [
|
||||||
|
__(
|
||||||
|
'Based on PayPal internal data from Q1 2022, results include Pay in 3 installments (ES).',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
DE: {
|
||||||
|
description: sprintf(
|
||||||
|
__(
|
||||||
|
'Your customers can already buy now and pay later with PayPal — add messaging to your site to let them know. When you offer your customers Pay Later options, 57%% will be more likely to buy from you again.¹ <strong>There\'s no extra cost</strong> and you get paid up front. <a target="_blank" href="%s">More about Pay Later</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/de/business/accept-payments/checkout/installments'
|
||||||
|
),
|
||||||
|
notes: [
|
||||||
|
__(
|
||||||
|
'Average order value in 2020 with PayPal installments compared to total PayPal sales.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
|
@ -6,20 +6,18 @@ import {
|
||||||
RadioControl,
|
RadioControl,
|
||||||
} from '@wordpress/components';
|
} from '@wordpress/components';
|
||||||
import { useState } from '@wordpress/element';
|
import { useState } from '@wordpress/element';
|
||||||
|
|
||||||
import PaymentMethodModal from '../../../../ReusableComponents/PaymentMethodModal';
|
import PaymentMethodModal from '../../../../ReusableComponents/PaymentMethodModal';
|
||||||
import {
|
import { PaymentHooks } from '../../../../../data';
|
||||||
usePaymentMethods,
|
|
||||||
usePaymentMethodsModal,
|
|
||||||
} from '../../../../../data/payment/hooks';
|
|
||||||
|
|
||||||
const Modal = ( { method, setModalIsVisible, onSave } ) => {
|
const Modal = ( { method, setModalIsVisible, onSave } ) => {
|
||||||
const { paymentMethods } = usePaymentMethods();
|
const { paymentMethods } = PaymentHooks.usePaymentMethods();
|
||||||
const {
|
const {
|
||||||
paypalShowLogo,
|
paypalShowLogo,
|
||||||
threeDSecure,
|
threeDSecure,
|
||||||
fastlaneCardholderName,
|
fastlaneCardholderName,
|
||||||
fastlaneDisplayWatermark,
|
fastlaneDisplayWatermark,
|
||||||
} = usePaymentMethodsModal();
|
} = PaymentHooks.usePaymentMethodsModal();
|
||||||
|
|
||||||
const [ settings, setSettings ] = useState( () => {
|
const [ settings, setSettings ] = useState( () => {
|
||||||
if ( ! method?.id ) {
|
if ( ! method?.id ) {
|
||||||
|
@ -68,6 +66,7 @@ const Modal = ( { method, setModalIsVisible, onSave } ) => {
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-modal__field-row">
|
<div className="ppcp-r-modal__field-row">
|
||||||
<TextControl
|
<TextControl
|
||||||
|
__nextHasNoMarginBottom={ true }
|
||||||
className="ppcp-r-vertical-text-control"
|
className="ppcp-r-vertical-text-control"
|
||||||
label={ field.label }
|
label={ field.label }
|
||||||
value={ settings[ key ] }
|
value={ settings[ key ] }
|
|
@ -4,9 +4,9 @@ import { Button } from '@wordpress/components';
|
||||||
import {
|
import {
|
||||||
ControlTextInput,
|
ControlTextInput,
|
||||||
ControlRadioGroup,
|
ControlRadioGroup,
|
||||||
} from '../../../../ReusableComponents/Controls';
|
} from '../../../../../ReusableComponents/Controls';
|
||||||
import Accordion from '../../../../ReusableComponents/AccordionSection';
|
import Accordion from '../../../../../ReusableComponents/AccordionSection';
|
||||||
import SettingsBlock from '../../../../ReusableComponents/SettingsBlock';
|
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||||
|
|
||||||
const ConnectionDetails = ( { settings, updateFormValue } ) => {
|
const ConnectionDetails = ( { settings, updateFormValue } ) => {
|
||||||
const isSandbox = settings.sandboxConnected;
|
const isSandbox = settings.sandboxConnected;
|
|
@ -4,7 +4,7 @@ import { CommonHooks } from '../../../../../../data';
|
||||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||||
import { Title } from '../../../../../ReusableComponents/Elements';
|
import { Title } from '../../../../../ReusableComponents/Elements';
|
||||||
|
|
||||||
const HooksTableBlock = () => {
|
const HooksListBlock = () => {
|
||||||
const { webhooks } = CommonHooks.useWebhooks();
|
const { webhooks } = CommonHooks.useWebhooks();
|
||||||
const { url, events } = webhooks;
|
const { url, events } = webhooks;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ const HooksTableBlock = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsBlock separatorAndGap={ false }>
|
<SettingsBlock separatorAndGap={ false } className="ppcp--webhooks">
|
||||||
<WebhookUrl url={ url } />
|
<WebhookUrl url={ url } />
|
||||||
<WebhookEvents events={ events } />
|
<WebhookEvents events={ events } />
|
||||||
</SettingsBlock>
|
</SettingsBlock>
|
||||||
|
@ -37,7 +37,7 @@ const WebhookEvents = ( { events } ) => {
|
||||||
<Title>
|
<Title>
|
||||||
{ __( 'Subscribed Events', 'woocommerce-paypal-payments' ) }
|
{ __( 'Subscribed Events', 'woocommerce-paypal-payments' ) }
|
||||||
</Title>
|
</Title>
|
||||||
<ul>
|
<ul className="ppcp--webhook-list">
|
||||||
{ events.map( ( event, index ) => (
|
{ events.map( ( event, index ) => (
|
||||||
<li key={ index }>{ event }</li>
|
<li key={ index }>{ event }</li>
|
||||||
) ) }
|
) ) }
|
||||||
|
@ -46,4 +46,4 @@ const WebhookEvents = ( { events } ) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HooksTableBlock;
|
export default HooksListBlock;
|
|
@ -1,9 +1,9 @@
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
import Accordion from '../../../../ReusableComponents/AccordionSection';
|
import Accordion from '../../../../../ReusableComponents/AccordionSection';
|
||||||
import SettingsBlock from '../../../../ReusableComponents/SettingsBlock';
|
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||||
import { ControlSelect } from '../../../../ReusableComponents/Controls';
|
import { ControlSelect } from '../../../../../ReusableComponents/Controls';
|
||||||
import { SettingsHooks } from '../../../../../data';
|
import { SettingsHooks } from '../../../../../../data';
|
||||||
|
|
||||||
const OtherSettings = () => {
|
const OtherSettings = () => {
|
||||||
const { disabledCards, setDisabledCards } = SettingsHooks.useSettings();
|
const { disabledCards, setDisabledCards } = SettingsHooks.useSettings();
|
|
@ -5,10 +5,10 @@ import {
|
||||||
ControlToggleButton,
|
ControlToggleButton,
|
||||||
ControlTextInput,
|
ControlTextInput,
|
||||||
ControlSelect,
|
ControlSelect,
|
||||||
} from '../../../../ReusableComponents/Controls';
|
} from '../../../../../ReusableComponents/Controls';
|
||||||
import SettingsBlock from '../../../../ReusableComponents/SettingsBlock';
|
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||||
import Accordion from '../../../../ReusableComponents/AccordionSection';
|
import Accordion from '../../../../../ReusableComponents/AccordionSection';
|
||||||
import { SettingsHooks } from '../../../../../data';
|
import { SettingsHooks } from '../../../../../../data';
|
||||||
|
|
||||||
const PaypalSettings = () => {
|
const PaypalSettings = () => {
|
||||||
const {
|
const {
|
|
@ -59,6 +59,7 @@ const ResubscribeBlock = () => {
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
) }
|
) }
|
||||||
horizontalLayout={ true }
|
horizontalLayout={ true }
|
||||||
|
className="ppcp--webhook-resubscribe"
|
||||||
>
|
>
|
||||||
<ControlButton
|
<ControlButton
|
||||||
type={ 'secondary' }
|
type={ 'secondary' }
|
|
@ -116,6 +116,7 @@ const SimulationBlock = () => {
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
) }
|
) }
|
||||||
horizontalLayout={ true }
|
horizontalLayout={ true }
|
||||||
|
className="ppcp--webhook-simulation"
|
||||||
>
|
>
|
||||||
<ControlButton
|
<ControlButton
|
||||||
type={ 'secondary' }
|
type={ 'secondary' }
|
|
@ -6,7 +6,7 @@ import Accordion from '../../../../../ReusableComponents/AccordionSection';
|
||||||
|
|
||||||
import SimulationBlock from './SimulationBlock';
|
import SimulationBlock from './SimulationBlock';
|
||||||
import ResubscribeBlock from './ResubscribeBlock';
|
import ResubscribeBlock from './ResubscribeBlock';
|
||||||
import HooksTableBlock from './HooksTableBlock';
|
import HooksListBlock from './HooksListBlock';
|
||||||
import { SettingsHooks } from '../../../../../../data';
|
import { SettingsHooks } from '../../../../../../data';
|
||||||
|
|
||||||
const Troubleshooting = () => {
|
const Troubleshooting = () => {
|
||||||
|
@ -43,7 +43,7 @@ const Troubleshooting = () => {
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#webhook-status'
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#webhook-status'
|
||||||
) }
|
) }
|
||||||
>
|
>
|
||||||
<HooksTableBlock />
|
<HooksListBlock />
|
||||||
<ResubscribeBlock />
|
<ResubscribeBlock />
|
||||||
<SimulationBlock />
|
<SimulationBlock />
|
||||||
</SettingsBlock>
|
</SettingsBlock>
|
|
@ -4,10 +4,10 @@ import {
|
||||||
Content,
|
Content,
|
||||||
ContentWrapper,
|
ContentWrapper,
|
||||||
} from '../../../../ReusableComponents/Elements';
|
} from '../../../../ReusableComponents/Elements';
|
||||||
import ConnectionDetails from '../../../Overview/TabSettingsElements/Blocks/ConnectionDetails';
|
import ConnectionDetails from './Blocks/ConnectionDetails';
|
||||||
import Troubleshooting from '../../../Overview/TabSettingsElements/Blocks/Troubleshooting/Troubleshooting';
|
import Troubleshooting from './Blocks/Troubleshooting';
|
||||||
import PaypalSettings from '../../../Overview/TabSettingsElements/Blocks/PaypalSettings';
|
import PaypalSettings from './Blocks/PaypalSettings';
|
||||||
import OtherSettings from '../../../Overview/TabSettingsElements/Blocks/OtherSettings';
|
import OtherSettings from './Blocks/OtherSettings';
|
||||||
|
|
||||||
const ExpertSettings = () => {
|
const ExpertSettings = () => {
|
||||||
const settings = {}; // dummy object
|
const settings = {}; // dummy object
|
||||||
|
|
|
@ -49,7 +49,7 @@ const LocationSelector = ( { location, setLocation } ) => {
|
||||||
) }
|
) }
|
||||||
</SelectStylingSection>
|
</SelectStylingSection>
|
||||||
<CheckboxStylingSection
|
<CheckboxStylingSection
|
||||||
className="location-activation"
|
name="location-activation"
|
||||||
separatorAndGap={ false }
|
separatorAndGap={ false }
|
||||||
options={ [ activateCheckbox ] }
|
options={ [ activateCheckbox ] }
|
||||||
value={ isActive }
|
value={ isActive }
|
||||||
|
|
|
@ -9,8 +9,8 @@ const SectionPaymentMethods = ( { location } ) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CheckboxStylingSection
|
<CheckboxStylingSection
|
||||||
|
name="payment-methods"
|
||||||
title={ __( 'Payment Methods', 'woocommerce-paypal-payments' ) }
|
title={ __( 'Payment Methods', 'woocommerce-paypal-payments' ) }
|
||||||
className="payment-methods"
|
|
||||||
options={ choices }
|
options={ choices }
|
||||||
value={ paymentMethods }
|
value={ paymentMethods }
|
||||||
onChange={ setPaymentMethods }
|
onChange={ setPaymentMethods }
|
||||||
|
|
|
@ -21,7 +21,7 @@ const SectionTagline = ( { location } ) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CheckboxStylingSection
|
<CheckboxStylingSection
|
||||||
className="tagline"
|
name="tagline"
|
||||||
separatorAndGap={ false }
|
separatorAndGap={ false }
|
||||||
options={ [ checkbox ] }
|
options={ [ checkbox ] }
|
||||||
value={ tagline }
|
value={ tagline }
|
||||||
|
|
|
@ -20,7 +20,7 @@ const StylingSection = ( {
|
||||||
separatorAndGap={ separatorAndGap }
|
separatorAndGap={ separatorAndGap }
|
||||||
>
|
>
|
||||||
<Header>
|
<Header>
|
||||||
<Title altStyle={ true } big={ bigTitle }>
|
<Title noCaps={ true } big={ bigTitle }>
|
||||||
{ title }
|
{ title }
|
||||||
</Title>
|
</Title>
|
||||||
<Description>{ description }</Description>
|
<Description>{ description }</Description>
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { CheckboxGroup } from '../../../../../ReusableComponents/Fields';
|
import { CheckboxGroup } from '../../../../../ReusableComponents/Fields';
|
||||||
import HStack from '../../../../../ReusableComponents/HStack';
|
import { VStack } from '../../../../../ReusableComponents/Stack';
|
||||||
import StylingSection from './StylingSection';
|
import StylingSection from './StylingSection';
|
||||||
|
|
||||||
const StylingSectionWithCheckboxes = ( {
|
const StylingSectionWithCheckboxes = ( {
|
||||||
title,
|
title,
|
||||||
|
name,
|
||||||
className = '',
|
className = '',
|
||||||
description = '',
|
description = '',
|
||||||
separatorAndGap = true,
|
separatorAndGap = true,
|
||||||
|
@ -14,7 +15,14 @@ const StylingSectionWithCheckboxes = ( {
|
||||||
onChange,
|
onChange,
|
||||||
children,
|
children,
|
||||||
} ) => {
|
} ) => {
|
||||||
className = classNames( 'ppcp--has-checkboxes', className );
|
className = classNames( 'ppcp--has-checkboxes', name, className );
|
||||||
|
|
||||||
|
if ( ! name ) {
|
||||||
|
console.error(
|
||||||
|
'Checkbox sections need a unique name! No name given to:',
|
||||||
|
title
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StylingSection
|
<StylingSection
|
||||||
|
@ -23,13 +31,14 @@ const StylingSectionWithCheckboxes = ( {
|
||||||
description={ description }
|
description={ description }
|
||||||
separatorAndGap={ separatorAndGap }
|
separatorAndGap={ separatorAndGap }
|
||||||
>
|
>
|
||||||
<HStack spacing={ 6 }>
|
<VStack spacing={ 6 }>
|
||||||
<CheckboxGroup
|
<CheckboxGroup
|
||||||
|
name={ name }
|
||||||
options={ options }
|
options={ options }
|
||||||
value={ value }
|
value={ value }
|
||||||
onChange={ onChange }
|
onChange={ onChange }
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</VStack>
|
||||||
|
|
||||||
{ children }
|
{ children }
|
||||||
</StylingSection>
|
</StylingSection>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { RadioControl } from '@wordpress/components';
|
import { RadioControl } from '@wordpress/components';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import HStack from '../../../../../ReusableComponents/HStack';
|
import { HStack } from '../../../../../ReusableComponents/Stack';
|
||||||
import StylingSection from './StylingSection';
|
import StylingSection from './StylingSection';
|
||||||
|
|
||||||
const StylingSectionWithRadiobuttons = ( {
|
const StylingSectionWithRadiobuttons = ( {
|
||||||
|
|
|
@ -9,21 +9,48 @@ import {
|
||||||
TodoSettingsBlock,
|
TodoSettingsBlock,
|
||||||
FeatureSettingsBlock,
|
FeatureSettingsBlock,
|
||||||
} from '../../../ReusableComponents/SettingsBlocks';
|
} from '../../../ReusableComponents/SettingsBlocks';
|
||||||
|
import { Content, ContentWrapper } from '../../../ReusableComponents/Elements';
|
||||||
import SettingsCard from '../../../ReusableComponents/SettingsCard';
|
import SettingsCard from '../../../ReusableComponents/SettingsCard';
|
||||||
import { TITLE_BADGE_POSITIVE } from '../../../ReusableComponents/TitleBadge';
|
import { TITLE_BADGE_POSITIVE } from '../../../ReusableComponents/TitleBadge';
|
||||||
import { useMerchantInfo } from '../../../../data/common/hooks';
|
import { useMerchantInfo } from '../../../../data/common/hooks';
|
||||||
import { useTodos } from '../../../../data/todos/hooks';
|
|
||||||
import { STORE_NAME } from '../../../../data/common';
|
import { STORE_NAME } from '../../../../data/common';
|
||||||
import Features from '../Components/Overview/Features';
|
import { getFeatures } from '../Components/Overview/features-config';
|
||||||
|
import { todosData } from '../todo-items';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NOTIFICATION_ERROR,
|
NOTIFICATION_ERROR,
|
||||||
NOTIFICATION_SUCCESS,
|
NOTIFICATION_SUCCESS,
|
||||||
} from '../../../ReusableComponents/Icons';
|
} from '../../../ReusableComponents/Icons';
|
||||||
|
|
||||||
const TabOverview = () => {
|
const TabOverview = () => {
|
||||||
const [ isRefreshing, setIsRefreshing ] = useState( false );
|
return (
|
||||||
|
<div className="ppcp-r-tab-overview">
|
||||||
|
{ todosData.length > 0 && (
|
||||||
|
<SettingsCard
|
||||||
|
className="ppcp-r-tab-overview-todo"
|
||||||
|
title={ __(
|
||||||
|
'Things to do next',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
description={ __(
|
||||||
|
'Complete these tasks to keep your store updated with the latest products and services.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
>
|
||||||
|
<TodoSettingsBlock todosData={ todosData } />
|
||||||
|
</SettingsCard>
|
||||||
|
) }
|
||||||
|
|
||||||
const { todos, isReady: areTodosReady } = useTodos();
|
<OverviewFeatures />
|
||||||
|
<OverviewHelp />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TabOverview;
|
||||||
|
|
||||||
|
const OverviewFeatures = () => {
|
||||||
|
const [ isRefreshing, setIsRefreshing ] = useState( false );
|
||||||
const { merchant, features: merchantFeatures } = useMerchantInfo();
|
const { merchant, features: merchantFeatures } = useMerchantInfo();
|
||||||
const { refreshFeatureStatuses, setActiveModal } =
|
const { refreshFeatureStatuses, setActiveModal } =
|
||||||
useDispatch( STORE_NAME );
|
useDispatch( STORE_NAME );
|
||||||
|
@ -32,7 +59,7 @@ const TabOverview = () => {
|
||||||
|
|
||||||
// Get the features data with access to setActiveModal
|
// Get the features data with access to setActiveModal
|
||||||
const featuresData = useMemo(
|
const featuresData = useMemo(
|
||||||
() => Features.getFeatures( setActiveModal ),
|
() => getFeatures( setActiveModal ),
|
||||||
[ setActiveModal ]
|
[ setActiveModal ]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -49,6 +76,7 @@ const TabOverview = () => {
|
||||||
|
|
||||||
const refreshHandler = async () => {
|
const refreshHandler = async () => {
|
||||||
setIsRefreshing( true );
|
setIsRefreshing( true );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await refreshFeatureStatuses();
|
const result = await refreshFeatureStatuses();
|
||||||
if ( result && ! result.success ) {
|
if ( result && ! result.success ) {
|
||||||
|
@ -79,122 +107,139 @@ const TabOverview = () => {
|
||||||
icon: NOTIFICATION_SUCCESS,
|
icon: NOTIFICATION_SUCCESS,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log( 'Features refreshed successfully.' );
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setIsRefreshing( false );
|
setIsRefreshing( false );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Don't render todos section until data is ready
|
return (
|
||||||
const showTodos = areTodosReady && todos.length > 0;
|
<SettingsCard
|
||||||
|
className="ppcp-r-tab-overview-features"
|
||||||
|
title={ __( 'Features', 'woocommerce-paypal-payments' ) }
|
||||||
|
description={
|
||||||
|
<OverviewFeatureDescription
|
||||||
|
refreshHandler={ refreshHandler }
|
||||||
|
isRefreshing={ isRefreshing }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
contentContainer={ false }
|
||||||
|
>
|
||||||
|
<ContentWrapper>
|
||||||
|
{ features.map( ( { id, ...feature } ) => (
|
||||||
|
<OverviewFeatureItem
|
||||||
|
key={ id }
|
||||||
|
isBusy={ isRefreshing }
|
||||||
|
isSandbox={ merchant.isSandbox }
|
||||||
|
title={ feature.title }
|
||||||
|
description={ feature.description }
|
||||||
|
buttons={ feature.buttons }
|
||||||
|
enabled={ feature.enabled }
|
||||||
|
notes={ feature.notes }
|
||||||
|
/>
|
||||||
|
) ) }
|
||||||
|
</ContentWrapper>
|
||||||
|
</SettingsCard>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const OverviewFeatureItem = ( {
|
||||||
|
isBusy,
|
||||||
|
isSandbox,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
buttons,
|
||||||
|
enabled,
|
||||||
|
notes,
|
||||||
|
} ) => {
|
||||||
|
const getButtonUrl = ( button ) => {
|
||||||
|
if ( button.urls ) {
|
||||||
|
return isSandbox ? button.urls.sandbox : button.urls.live;
|
||||||
|
}
|
||||||
|
|
||||||
|
return button.url;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visibleButtons = buttons.filter(
|
||||||
|
( button ) =>
|
||||||
|
! button.showWhen || // Learn more buttons
|
||||||
|
( enabled && button.showWhen === 'enabled' ) ||
|
||||||
|
( ! enabled && button.showWhen === 'disabled' )
|
||||||
|
);
|
||||||
|
|
||||||
|
const actionProps = {
|
||||||
|
isBusy,
|
||||||
|
enabled,
|
||||||
|
notes,
|
||||||
|
buttons: visibleButtons.map( ( button ) => ( {
|
||||||
|
...button,
|
||||||
|
url: getButtonUrl( button ),
|
||||||
|
} ) ),
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( enabled ) {
|
||||||
|
actionProps.badge = {
|
||||||
|
text: __( 'Active', 'woocommerce-paypal-payments' ),
|
||||||
|
type: TITLE_BADGE_POSITIVE,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-tab-overview">
|
<Content>
|
||||||
{ showTodos && (
|
<FeatureSettingsBlock
|
||||||
<SettingsCard
|
title={ title }
|
||||||
className="ppcp-r-tab-overview-todo"
|
description={ description }
|
||||||
title={ __(
|
actionProps={ actionProps }
|
||||||
'Things to do next',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
description={ __(
|
|
||||||
'Complete these tasks to keep your store updated with the latest products and services.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
>
|
|
||||||
<TodoSettingsBlock todosData={ todos } />
|
|
||||||
</SettingsCard>
|
|
||||||
) }
|
|
||||||
|
|
||||||
<SettingsCard
|
|
||||||
className="ppcp-r-tab-overview-features"
|
|
||||||
title={ __( 'Features', 'woocommerce-paypal-payments' ) }
|
|
||||||
description={
|
|
||||||
<>
|
|
||||||
<p>
|
|
||||||
{ __(
|
|
||||||
'Enable additional features and capabilities on your WooCommerce store.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{ __(
|
|
||||||
'Click Refresh to update your current features after making changes.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
</p>
|
|
||||||
<Button
|
|
||||||
variant="tertiary"
|
|
||||||
onClick={ refreshHandler }
|
|
||||||
disabled={ isRefreshing }
|
|
||||||
>
|
|
||||||
<Icon icon={ reusableBlock } size={ 18 } />
|
|
||||||
{ isRefreshing
|
|
||||||
? __(
|
|
||||||
'Refreshing…',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
)
|
|
||||||
: __(
|
|
||||||
'Refresh',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
contentItems={ features.map( ( feature ) => {
|
|
||||||
return (
|
|
||||||
<FeatureSettingsBlock
|
|
||||||
key={ feature.id }
|
|
||||||
title={ feature.title }
|
|
||||||
description={ feature.description }
|
|
||||||
actionProps={ {
|
|
||||||
buttons: feature.buttons
|
|
||||||
.filter(
|
|
||||||
( button ) =>
|
|
||||||
! button.showWhen || // Learn more buttons
|
|
||||||
( feature.enabled &&
|
|
||||||
button.showWhen ===
|
|
||||||
'enabled' ) ||
|
|
||||||
( ! feature.enabled &&
|
|
||||||
button.showWhen === 'disabled' )
|
|
||||||
)
|
|
||||||
.map( ( button ) => ( {
|
|
||||||
...button,
|
|
||||||
url: button.urls
|
|
||||||
? merchant?.isSandbox
|
|
||||||
? button.urls.sandbox
|
|
||||||
: button.urls.live
|
|
||||||
: button.url,
|
|
||||||
} ) ),
|
|
||||||
isBusy: isRefreshing,
|
|
||||||
enabled: feature.enabled,
|
|
||||||
notes: feature.notes,
|
|
||||||
badge: feature.enabled
|
|
||||||
? {
|
|
||||||
text: __(
|
|
||||||
'Active',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
type: TITLE_BADGE_POSITIVE,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
} }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} ) }
|
|
||||||
/>
|
/>
|
||||||
|
</Content>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
<SettingsCard
|
const OverviewFeatureDescription = ( { refreshHandler, isRefreshing } ) => {
|
||||||
className="ppcp-r-tab-overview-help"
|
const buttonLabel = isRefreshing
|
||||||
title={ __( 'Help Center', 'woocommerce-paypal-payments' ) }
|
? __( 'Refreshing…', 'woocommerce-paypal-payments' )
|
||||||
description={ __(
|
: __( 'Refresh', 'woocommerce-paypal-payments' );
|
||||||
'Access detailed guides and responsive support to streamline setup and enhance your experience.',
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>
|
||||||
|
{ __(
|
||||||
|
'Enable additional features and capabilities on your WooCommerce store.',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
) }
|
) }
|
||||||
contentItems={ [
|
</p>
|
||||||
|
<p>
|
||||||
|
{ __(
|
||||||
|
'Click Refresh to update your current features after making changes.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
variant="tertiary"
|
||||||
|
onClick={ refreshHandler }
|
||||||
|
disabled={ isRefreshing }
|
||||||
|
>
|
||||||
|
<Icon icon={ reusableBlock } size={ 18 } />
|
||||||
|
{ buttonLabel }
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const OverviewHelp = () => {
|
||||||
|
return (
|
||||||
|
<SettingsCard
|
||||||
|
className="ppcp-r-tab-overview-help"
|
||||||
|
title={ __( 'Help Center', 'woocommerce-paypal-payments' ) }
|
||||||
|
description={ __(
|
||||||
|
'Access detailed guides and responsive support to streamline setup and enhance your experience.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
contentContainer={ false }
|
||||||
|
>
|
||||||
|
<ContentWrapper>
|
||||||
|
<Content>
|
||||||
<FeatureSettingsBlock
|
<FeatureSettingsBlock
|
||||||
key="documentation"
|
|
||||||
title={ __(
|
title={ __(
|
||||||
'Documentation',
|
'Documentation',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
|
@ -211,13 +256,15 @@ const TabOverview = () => {
|
||||||
'View full documentation',
|
'View full documentation',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
),
|
||||||
url: 'https://woocommerce.com/document/woocommerce-paypal-payments/',
|
url: 'https://woocommerce.com/document/woocommerce-paypal-payments/ ',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} }
|
} }
|
||||||
/>,
|
/>
|
||||||
|
</Content>
|
||||||
|
|
||||||
|
<Content>
|
||||||
<FeatureSettingsBlock
|
<FeatureSettingsBlock
|
||||||
key="support"
|
|
||||||
title={ __( 'Support', 'woocommerce-paypal-payments' ) }
|
title={ __( 'Support', 'woocommerce-paypal-payments' ) }
|
||||||
description={ __(
|
description={ __(
|
||||||
'Need help? Access troubleshooting tips or contact our support team for personalized assistance.',
|
'Need help? Access troubleshooting tips or contact our support team for personalized assistance.',
|
||||||
|
@ -231,15 +278,13 @@ const TabOverview = () => {
|
||||||
'View support options',
|
'View support options',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
),
|
||||||
url: 'https://woocommerce.com/document/woocommerce-paypal-payments/#get-help',
|
url: 'https://woocommerce.com/document/woocommerce-paypal-payments/#get-help ',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} }
|
} }
|
||||||
/>,
|
/>
|
||||||
] }
|
</Content>
|
||||||
/>
|
</ContentWrapper>
|
||||||
</div>
|
</SettingsCard>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TabOverview;
|
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { useCallback } from '@wordpress/element';
|
||||||
|
|
||||||
|
import SettingsCard from '../../../ReusableComponents/SettingsCard';
|
||||||
|
import { PaymentMethodsBlock } from '../../../ReusableComponents/SettingsBlocks';
|
||||||
|
import { PaymentHooks } from '../../../../data';
|
||||||
|
import { useActiveModal } from '../../../../data/common/hooks';
|
||||||
|
import Modal from '../Components/Payment/Modal';
|
||||||
|
|
||||||
|
const TabPaymentMethods = () => {
|
||||||
|
const methods = PaymentHooks.usePaymentMethods();
|
||||||
|
const { setPersistent, changePaymentSettings } = PaymentHooks.useStore();
|
||||||
|
const { activeModal, setActiveModal } = useActiveModal();
|
||||||
|
|
||||||
|
const getActiveMethod = () => {
|
||||||
|
if ( ! activeModal ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return methods.all.find( ( method ) => method.id === activeModal );
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = useCallback(
|
||||||
|
( methodId, settings ) => {
|
||||||
|
changePaymentSettings( methodId, {
|
||||||
|
title: settings.checkoutPageTitle,
|
||||||
|
description: settings.checkoutPageDescription,
|
||||||
|
} );
|
||||||
|
|
||||||
|
const persistentSettings = [
|
||||||
|
'paypalShowLogo',
|
||||||
|
'threeDSecure',
|
||||||
|
'fastlaneCardholderName',
|
||||||
|
'fastlaneDisplayWatermark',
|
||||||
|
];
|
||||||
|
|
||||||
|
persistentSettings.forEach( ( setting ) => {
|
||||||
|
if ( setting in settings ) {
|
||||||
|
// TODO: Create a dedicated setter for those values.
|
||||||
|
setPersistent( setting, settings[ setting ] );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
setActiveModal( null );
|
||||||
|
},
|
||||||
|
[ changePaymentSettings, setActiveModal, setPersistent ]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-payment-methods">
|
||||||
|
<PaymentMethodCard
|
||||||
|
id="ppcp-paypal-checkout-card"
|
||||||
|
title={ __( 'PayPal Checkout', 'woocommerce-paypal-payments' ) }
|
||||||
|
description={ __(
|
||||||
|
'Select your preferred checkout option with PayPal for easy payment processing.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
icon="icon-checkout-standard.svg"
|
||||||
|
methods={ methods.paypal }
|
||||||
|
onTriggerModal={ setActiveModal }
|
||||||
|
/>
|
||||||
|
<PaymentMethodCard
|
||||||
|
id="ppcp-card-payments-card"
|
||||||
|
title={ __(
|
||||||
|
'Online Card Payments',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
description={ __(
|
||||||
|
'Select your preferred card payment options for efficient payment processing.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
icon="icon-checkout-online-methods.svg"
|
||||||
|
methods={ methods.cardPayment }
|
||||||
|
onTriggerModal={ setActiveModal }
|
||||||
|
/>
|
||||||
|
<PaymentMethodCard
|
||||||
|
id="ppcp-alternative-payments-card"
|
||||||
|
title={ __(
|
||||||
|
'Alternative Payment Methods',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
description={ __(
|
||||||
|
'With alternative payment methods, customers across the globe can pay with their bank accounts and other local payment methods.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
icon="icon-checkout-alternative-methods.svg"
|
||||||
|
methods={ methods.apm }
|
||||||
|
onTriggerModal={ setActiveModal }
|
||||||
|
/>
|
||||||
|
|
||||||
|
{ activeModal && (
|
||||||
|
<Modal
|
||||||
|
method={ getActiveMethod() }
|
||||||
|
setModalIsVisible={ () => setActiveModal( null ) }
|
||||||
|
onSave={ handleSave }
|
||||||
|
/>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TabPaymentMethods;
|
||||||
|
|
||||||
|
const PaymentMethodCard = ( {
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
icon,
|
||||||
|
methods,
|
||||||
|
onTriggerModal,
|
||||||
|
} ) => (
|
||||||
|
<SettingsCard
|
||||||
|
id={ id }
|
||||||
|
title={ title }
|
||||||
|
description={ description }
|
||||||
|
icon={ icon }
|
||||||
|
contentContainer={ false }
|
||||||
|
>
|
||||||
|
<PaymentMethodsBlock
|
||||||
|
paymentMethods={ methods }
|
||||||
|
onTriggerModal={ onTriggerModal }
|
||||||
|
/>
|
||||||
|
</SettingsCard>
|
||||||
|
);
|
|
@ -1,7 +1,7 @@
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
import TabOverview from './TabOverview';
|
import TabOverview from './TabOverview';
|
||||||
import TabPaymentMethods from '../../Overview/TabPaymentMethods';
|
import TabPaymentMethods from './TabPaymentMethods';
|
||||||
import TabSettings from './TabSettings';
|
import TabSettings from './TabSettings';
|
||||||
import TabStyling from './TabStyling';
|
import TabStyling from './TabStyling';
|
||||||
import TabPayLaterMessaging from '../../Overview/TabPayLaterMessaging';
|
import TabPayLaterMessaging from '../../Overview/TabPayLaterMessaging';
|
||||||
|
|
|
@ -12,6 +12,7 @@ export default {
|
||||||
SET_PERSISTENT: 'PAYMENT:SET_PERSISTENT',
|
SET_PERSISTENT: 'PAYMENT:SET_PERSISTENT',
|
||||||
RESET: 'PAYMENT:RESET',
|
RESET: 'PAYMENT:RESET',
|
||||||
HYDRATE: 'PAYMENT:HYDRATE',
|
HYDRATE: 'PAYMENT:HYDRATE',
|
||||||
|
CHANGE_PAYMENT_SETTING: 'PAYMENT:CHANGE_PAYMENT_SETTING',
|
||||||
|
|
||||||
// Controls - always start with "DO_".
|
// Controls - always start with "DO_".
|
||||||
DO_PERSIST_DATA: 'PAYMENT:DO_PERSIST_DATA',
|
DO_PERSIST_DATA: 'PAYMENT:DO_PERSIST_DATA',
|
||||||
|
|
|
@ -37,27 +37,17 @@ export const hydrate = ( payload ) => ( {
|
||||||
} );
|
} );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transient. Marks the store as "ready", i.e., fully initialized.
|
* Generic transient-data updater.
|
||||||
*
|
*
|
||||||
* @param {boolean} isReady
|
* @param {string} prop Name of the property to update.
|
||||||
|
* @param {any} value The new value of the property.
|
||||||
* @return {Action} The action.
|
* @return {Action} The action.
|
||||||
*/
|
*/
|
||||||
export const setIsReady = ( isReady ) => ( {
|
export const setTransient = ( prop, value ) => ( {
|
||||||
type: ACTION_TYPES.SET_TRANSIENT,
|
type: ACTION_TYPES.SET_TRANSIENT,
|
||||||
payload: { isReady },
|
payload: { [ prop ]: value },
|
||||||
} );
|
} );
|
||||||
|
|
||||||
/**
|
|
||||||
* Side effect. Triggers the persistence of store data to the server.
|
|
||||||
*
|
|
||||||
* @return {Action} The action.
|
|
||||||
*/
|
|
||||||
export const persist = function* () {
|
|
||||||
const data = yield select( STORE_NAME ).persistentData();
|
|
||||||
|
|
||||||
yield { type: ACTION_TYPES.DO_PERSIST_DATA, data };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic persistent-data updater.
|
* Generic persistent-data updater.
|
||||||
*
|
*
|
||||||
|
@ -69,3 +59,34 @@ export const setPersistent = ( prop, value ) => ( {
|
||||||
type: ACTION_TYPES.SET_PERSISTENT,
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
payload: { [ prop ]: value },
|
payload: { [ prop ]: value },
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transient. Marks the store as "ready", i.e., fully initialized.
|
||||||
|
*
|
||||||
|
* @param {boolean} isReady
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setIsReady = ( isReady ) => setTransient( 'isReady', isReady );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify properties of a specific payment method.
|
||||||
|
*
|
||||||
|
* @param {string} id The payment method ID.
|
||||||
|
* @param {Object} props New props.
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const changePaymentSettings = ( id, props ) => ( {
|
||||||
|
type: ACTION_TYPES.CHANGE_PAYMENT_SETTING,
|
||||||
|
payload: { id, props },
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Side effect. Triggers the persistence of store data to the server.
|
||||||
|
*
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const persist = function* () {
|
||||||
|
const data = yield select( STORE_NAME ).persistentData();
|
||||||
|
|
||||||
|
yield { type: ACTION_TYPES.DO_PERSIST_DATA, data };
|
||||||
|
};
|
||||||
|
|
|
@ -7,60 +7,53 @@
|
||||||
* @file
|
* @file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useSelect, useDispatch } from '@wordpress/data';
|
import { useDispatch } from '@wordpress/data';
|
||||||
|
|
||||||
import { STORE_NAME } from './constants';
|
import { STORE_NAME } from './constants';
|
||||||
|
import { createHooksForStore } from '../utils';
|
||||||
const useTransient = ( key ) =>
|
|
||||||
useSelect(
|
|
||||||
( select ) => select( STORE_NAME ).transientData()?.[ key ],
|
|
||||||
[ key ]
|
|
||||||
);
|
|
||||||
|
|
||||||
const usePersistent = ( key ) =>
|
|
||||||
useSelect(
|
|
||||||
( select ) => select( STORE_NAME ).persistentData()?.[ key ],
|
|
||||||
[ key ]
|
|
||||||
);
|
|
||||||
|
|
||||||
const useHooks = () => {
|
const useHooks = () => {
|
||||||
const { persist, setPersistent } = useDispatch( STORE_NAME );
|
const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
|
||||||
|
const { persist, setPersistent, changePaymentSettings } =
|
||||||
|
useDispatch( STORE_NAME );
|
||||||
|
|
||||||
// Read-only flags and derived state.
|
// Read-only flags and derived state.
|
||||||
// Nothing here yet.
|
// Nothing here yet.
|
||||||
|
|
||||||
// Transient accessors.
|
// Transient accessors.
|
||||||
const isReady = useTransient( 'isReady' );
|
const [ isReady ] = useTransient( 'isReady' );
|
||||||
|
|
||||||
// PayPal checkout.
|
// PayPal checkout.
|
||||||
const paypal = usePersistent( 'ppcp-gateway' );
|
const [ paypal ] = usePersistent( 'ppcp-gateway' );
|
||||||
const venmo = usePersistent( 'venmo' );
|
const [ venmo ] = usePersistent( 'venmo' );
|
||||||
const payLater = usePersistent( 'pay-later' );
|
const [ payLater ] = usePersistent( 'pay-later' );
|
||||||
const creditCard = usePersistent( 'ppcp-card-button-gateway' );
|
const [ creditCard ] = usePersistent( 'ppcp-card-button-gateway' );
|
||||||
|
|
||||||
// Online card Payments.
|
// Online card Payments.
|
||||||
const advancedCreditCard = usePersistent( 'ppcp-credit-card-gateway' );
|
const [ advancedCreditCard ] = usePersistent( 'ppcp-credit-card-gateway' );
|
||||||
const fastlane = usePersistent( 'ppcp-axo-gateway' );
|
const [ fastlane ] = usePersistent( 'ppcp-axo-gateway' );
|
||||||
const applePay = usePersistent( 'ppcp-applepay' );
|
const [ applePay ] = usePersistent( 'ppcp-applepay' );
|
||||||
const googlePay = usePersistent( 'ppcp-googlepay' );
|
const [ googlePay ] = usePersistent( 'ppcp-googlepay' );
|
||||||
|
|
||||||
// Alternative payment methods.
|
// Alternative payment methods.
|
||||||
const bancontact = usePersistent( 'ppcp-bancontact' );
|
const [ bancontact ] = usePersistent( 'ppcp-bancontact' );
|
||||||
const blik = usePersistent( 'ppcp-blik' );
|
const [ blik ] = usePersistent( 'ppcp-blik' );
|
||||||
const eps = usePersistent( 'ppcp-eps' );
|
const [ eps ] = usePersistent( 'ppcp-eps' );
|
||||||
const ideal = usePersistent( 'ppcp-ideal' );
|
const [ ideal ] = usePersistent( 'ppcp-ideal' );
|
||||||
const mybank = usePersistent( 'ppcp-mybank' );
|
const [ mybank ] = usePersistent( 'ppcp-mybank' );
|
||||||
const p24 = usePersistent( 'ppcp-p24' );
|
const [ p24 ] = usePersistent( 'ppcp-p24' );
|
||||||
const trustly = usePersistent( 'ppcp-trustly' );
|
const [ trustly ] = usePersistent( 'ppcp-trustly' );
|
||||||
const multibanco = usePersistent( 'ppcp-multibanco' );
|
const [ multibanco ] = usePersistent( 'ppcp-multibanco' );
|
||||||
const pui = usePersistent( 'ppcp-pay-upon-invoice-gateway' );
|
const [ pui ] = usePersistent( 'ppcp-pay-upon-invoice-gateway' );
|
||||||
const oxxo = usePersistent( 'ppcp-oxxo-gateway' );
|
const [ oxxo ] = usePersistent( 'ppcp-oxxo-gateway' );
|
||||||
|
|
||||||
// Custom modal data.
|
// Custom modal data.
|
||||||
const paypalShowLogo = usePersistent( 'paypalShowLogo' );
|
const [ paypalShowLogo ] = usePersistent( 'paypalShowLogo' );
|
||||||
const threeDSecure = usePersistent( 'threeDSecure' );
|
const [ threeDSecure ] = usePersistent( 'threeDSecure' );
|
||||||
const fastlaneCardholderName = usePersistent( 'fastlaneCardholderName' );
|
const [ fastlaneCardholderName ] = usePersistent(
|
||||||
const fastlaneDisplayWatermark = usePersistent(
|
'fastlaneCardholderName'
|
||||||
|
);
|
||||||
|
const [ fastlaneDisplayWatermark ] = usePersistent(
|
||||||
'fastlaneDisplayWatermark'
|
'fastlaneDisplayWatermark'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -68,6 +61,7 @@ const useHooks = () => {
|
||||||
persist,
|
persist,
|
||||||
isReady,
|
isReady,
|
||||||
setPersistent,
|
setPersistent,
|
||||||
|
changePaymentSettings,
|
||||||
paypal,
|
paypal,
|
||||||
venmo,
|
venmo,
|
||||||
payLater,
|
payLater,
|
||||||
|
@ -94,21 +88,26 @@ const useHooks = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useStore = () => {
|
export const useStore = () => {
|
||||||
const { persist, isReady } = useHooks();
|
const { persist, isReady, setPersistent, changePaymentSettings } =
|
||||||
return { persist, isReady };
|
useHooks();
|
||||||
|
return { persist, isReady, setPersistent, changePaymentSettings };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const usePaymentMethods = () => {
|
export const usePaymentMethods = () => {
|
||||||
const {
|
const {
|
||||||
setPersistent,
|
// PayPal Checkout.
|
||||||
paypal,
|
paypal,
|
||||||
venmo,
|
venmo,
|
||||||
payLater,
|
payLater,
|
||||||
creditCard,
|
creditCard,
|
||||||
|
|
||||||
|
// Online card payments.
|
||||||
advancedCreditCard,
|
advancedCreditCard,
|
||||||
fastlane,
|
fastlane,
|
||||||
applePay,
|
applePay,
|
||||||
googlePay,
|
googlePay,
|
||||||
|
|
||||||
|
// Local APMs.
|
||||||
bancontact,
|
bancontact,
|
||||||
blik,
|
blik,
|
||||||
eps,
|
eps,
|
||||||
|
@ -121,6 +120,25 @@ export const usePaymentMethods = () => {
|
||||||
oxxo,
|
oxxo,
|
||||||
} = useHooks();
|
} = useHooks();
|
||||||
|
|
||||||
|
const payPalCheckout = [ paypal, venmo, payLater, creditCard ];
|
||||||
|
const onlineCardPayments = [
|
||||||
|
advancedCreditCard,
|
||||||
|
fastlane,
|
||||||
|
applePay,
|
||||||
|
googlePay,
|
||||||
|
];
|
||||||
|
const alternative = [
|
||||||
|
bancontact,
|
||||||
|
blik,
|
||||||
|
eps,
|
||||||
|
ideal,
|
||||||
|
mybank,
|
||||||
|
p24,
|
||||||
|
trustly,
|
||||||
|
multibanco,
|
||||||
|
pui,
|
||||||
|
oxxo,
|
||||||
|
];
|
||||||
const paymentMethods = [
|
const paymentMethods = [
|
||||||
paypal,
|
paypal,
|
||||||
venmo,
|
venmo,
|
||||||
|
@ -143,8 +161,10 @@ export const usePaymentMethods = () => {
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setPersistent,
|
all: paymentMethods,
|
||||||
paymentMethods,
|
paypal: payPalCheckout,
|
||||||
|
cardPayment: onlineCardPayments,
|
||||||
|
apm: alternative,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -163,63 +183,3 @@ export const usePaymentMethodsModal = () => {
|
||||||
fastlaneDisplayWatermark,
|
fastlaneDisplayWatermark,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const usePaymentMethodsPayPalCheckout = () => {
|
|
||||||
const { paypal, venmo, payLater, creditCard } = useHooks();
|
|
||||||
const paymentMethodsPayPalCheckout = [
|
|
||||||
paypal,
|
|
||||||
venmo,
|
|
||||||
payLater,
|
|
||||||
creditCard,
|
|
||||||
];
|
|
||||||
|
|
||||||
return {
|
|
||||||
paymentMethodsPayPalCheckout,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const usePaymentMethodsOnlineCardPayments = () => {
|
|
||||||
const { advancedCreditCard, fastlane, applePay, googlePay } = useHooks();
|
|
||||||
const paymentMethodsOnlineCardPayments = [
|
|
||||||
advancedCreditCard,
|
|
||||||
fastlane,
|
|
||||||
applePay,
|
|
||||||
googlePay,
|
|
||||||
];
|
|
||||||
|
|
||||||
return {
|
|
||||||
paymentMethodsOnlineCardPayments,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const usePaymentMethodsAlternative = () => {
|
|
||||||
const {
|
|
||||||
bancontact,
|
|
||||||
blik,
|
|
||||||
eps,
|
|
||||||
ideal,
|
|
||||||
mybank,
|
|
||||||
p24,
|
|
||||||
trustly,
|
|
||||||
multibanco,
|
|
||||||
pui,
|
|
||||||
oxxo,
|
|
||||||
} = useHooks();
|
|
||||||
|
|
||||||
const paymentMethodsAlternative = [
|
|
||||||
bancontact,
|
|
||||||
blik,
|
|
||||||
eps,
|
|
||||||
ideal,
|
|
||||||
mybank,
|
|
||||||
p24,
|
|
||||||
trustly,
|
|
||||||
multibanco,
|
|
||||||
pui,
|
|
||||||
oxxo,
|
|
||||||
];
|
|
||||||
|
|
||||||
return {
|
|
||||||
paymentMethodsAlternative,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
|
@ -57,6 +57,20 @@ const reducer = createReducer( defaultTransient, defaultPersistent, {
|
||||||
[ ACTION_TYPES.SET_PERSISTENT ]: ( state, payload ) =>
|
[ ACTION_TYPES.SET_PERSISTENT ]: ( state, payload ) =>
|
||||||
changePersistent( state, payload ),
|
changePersistent( state, payload ),
|
||||||
|
|
||||||
|
[ ACTION_TYPES.CHANGE_PAYMENT_SETTING ]: ( state, payload ) => {
|
||||||
|
const methodId = payload.id;
|
||||||
|
const oldProps = state.data[ methodId ];
|
||||||
|
|
||||||
|
if ( ! oldProps || oldProps.id !== methodId ) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changePersistent( state, {
|
||||||
|
...state,
|
||||||
|
[ methodId ]: { ...oldProps, ...payload.props },
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
|
||||||
[ ACTION_TYPES.RESET ]: ( state ) => {
|
[ ACTION_TYPES.RESET ]: ( state ) => {
|
||||||
const cleanState = changeTransient(
|
const cleanState = changeTransient(
|
||||||
changePersistent( state, defaultPersistent ),
|
changePersistent( state, defaultPersistent ),
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { useCallback } from '@wordpress/element';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CommonHooks,
|
CommonHooks,
|
||||||
PaymentHooks,
|
PaymentHooks,
|
||||||
|
@ -12,7 +14,7 @@ export const useSaveSettings = () => {
|
||||||
const { persist: persistSettings } = SettingsHooks.useStore();
|
const { persist: persistSettings } = SettingsHooks.useStore();
|
||||||
const { persist: persistStyling } = StylingHooks.useStore();
|
const { persist: persistStyling } = StylingHooks.useStore();
|
||||||
|
|
||||||
const persistAll = () => {
|
const persistAll = useCallback( () => {
|
||||||
withActivity(
|
withActivity(
|
||||||
'persist-methods',
|
'persist-methods',
|
||||||
'Save payment methods',
|
'Save payment methods',
|
||||||
|
@ -28,7 +30,7 @@ export const useSaveSettings = () => {
|
||||||
'Save styling details',
|
'Save styling details',
|
||||||
persistStyling
|
persistStyling
|
||||||
);
|
);
|
||||||
};
|
}, [ persistPayment, persistSettings, persistStyling, withActivity ] );
|
||||||
|
|
||||||
return { persistAll };
|
return { persistAll };
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,24 +37,18 @@ class SettingsModel {
|
||||||
$settings = get_option( self::OPTION_NAME, array() );
|
$settings = get_option( self::OPTION_NAME, array() );
|
||||||
|
|
||||||
$formatted = array(
|
$formatted = array(
|
||||||
'invoicePrefix' => $settings['invoice_prefix'] ?? '',
|
'invoicePrefix' => $settings['invoice_prefix'] ?? '',
|
||||||
'authorizeOnly' => (bool) ( $settings['authorize_only'] ?? false ),
|
'authorizeOnly' => (bool) ( $settings['authorize_only'] ?? false ),
|
||||||
'captureVirtualOnlyOrders' => (bool) ( $settings['capture_virtual_only_orders'] ?? false ),
|
'captureVirtualOnlyOrders' => (bool) ( $settings['capture_virtual_only_orders'] ?? false ),
|
||||||
'savePaypalAndVenmo' => (bool) ( $settings['save_paypal_and_venmo'] ?? false ),
|
'savePaypalAndVenmo' => (bool) ( $settings['save_paypal_and_venmo'] ?? false ),
|
||||||
'saveCardDetails' => (bool) ( $settings['save_credit_card_and_debit_card'] ?? false ),
|
'saveCardDetails' => (bool) ( $settings['save_credit_card_and_debit_card'] ?? false ),
|
||||||
'payNowExperience' => (bool) ( $settings['pay_now_experience'] ?? false ),
|
'payNowExperience' => (bool) ( $settings['pay_now_experience'] ?? false ),
|
||||||
'sandboxAccountCredentials' => (bool) ( $settings['sandbox_account_credentials'] ?? false ),
|
'logging' => (bool) ( $settings['logging'] ?? false ),
|
||||||
'sandboxMode' => $settings['sandbox_mode'] ?? null,
|
'subtotalAdjustment' => $settings['subtotal_mismatch_fallback'] ?? null,
|
||||||
'sandboxEnabled' => (bool) ( $settings['sandbox_enabled'] ?? false ),
|
'brandName' => $settings['brand_name'] ?? '',
|
||||||
'sandboxClientId' => $settings['sandbox_client_id'] ?? '',
|
'softDescriptor' => $settings['soft_descriptor'] ?? '',
|
||||||
'sandboxSecretKey' => $settings['sandbox_secret_key'] ?? '',
|
'landingPage' => $settings['paypal_landing_page'] ?? null,
|
||||||
'sandboxConnected' => (bool) ( $settings['sandbox_connected'] ?? false ),
|
'buttonLanguage' => $settings['button_language'] ?? '',
|
||||||
'logging' => (bool) ( $settings['logging'] ?? false ),
|
|
||||||
'subtotalAdjustment' => $settings['subtotal_mismatch_fallback'] ?? null,
|
|
||||||
'brandName' => $settings['brand_name'] ?? '',
|
|
||||||
'softDescriptor' => $settings['soft_descriptor'] ?? '',
|
|
||||||
'landingPage' => $settings['paypal_landing_page'] ?? null,
|
|
||||||
'buttonLanguage' => $settings['button_language'] ?? '',
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return $formatted;
|
return $formatted;
|
||||||
|
@ -78,12 +72,6 @@ class SettingsModel {
|
||||||
'save_paypal_and_venmo' => (bool) ( $data['savePaypalAndVenmo'] ?? false ),
|
'save_paypal_and_venmo' => (bool) ( $data['savePaypalAndVenmo'] ?? false ),
|
||||||
'save_credit_card_and_debit_card' => (bool) ( $data['saveCardDetails'] ?? false ),
|
'save_credit_card_and_debit_card' => (bool) ( $data['saveCardDetails'] ?? false ),
|
||||||
'pay_now_experience' => (bool) ( $data['payNowExperience'] ?? false ),
|
'pay_now_experience' => (bool) ( $data['payNowExperience'] ?? false ),
|
||||||
'sandbox_account_credentials' => (bool) ( $data['sandboxAccountCredentials'] ?? false ),
|
|
||||||
'sandbox_mode' => $data['sandboxMode'] ?? null,
|
|
||||||
'sandbox_enabled' => (bool) ( $data['sandboxEnabled'] ?? false ),
|
|
||||||
'sandbox_client_id' => $data['sandboxClientId'] ?? '',
|
|
||||||
'sandbox_secret_key' => $data['sandboxSecretKey'] ?? '',
|
|
||||||
'sandbox_connected' => (bool) ( $data['sandboxConnected'] ?? false ),
|
|
||||||
'logging' => (bool) ( $data['logging'] ?? false ),
|
'logging' => (bool) ( $data['logging'] ?? false ),
|
||||||
'subtotal_mismatch_fallback' => $data['subtotalAdjustment'] ?? null,
|
'subtotal_mismatch_fallback' => $data['subtotalAdjustment'] ?? null,
|
||||||
'brand_name' => $data['brandName'] ?? '',
|
'brand_name' => $data['brandName'] ?? '',
|
||||||
|
|
|
@ -576,7 +576,7 @@ class PaymentRestEndpoint extends RestEndpoint {
|
||||||
'OXXO is a Mexican chain of convenience stores. *Get PayPal account permission to use OXXO payment functionality by contacting us at (+52) 800–925–0304',
|
'OXXO is a Mexican chain of convenience stores. *Get PayPal account permission to use OXXO payment functionality by contacting us at (+52) 800–925–0304',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
),
|
||||||
'icon' => '',
|
'icon' => 'payment-method-oxxo',
|
||||||
'itemTitle' => __( 'OXXO', 'woocommerce-paypal-payments' ),
|
'itemTitle' => __( 'OXXO', 'woocommerce-paypal-payments' ),
|
||||||
'itemDescription' => __(
|
'itemDescription' => __(
|
||||||
'OXXO is a Mexican chain of convenience stores. *Get PayPal account permission to use OXXO payment functionality by contacting us at (+52) 800–925–0304',
|
'OXXO is a Mexican chain of convenience stores. *Get PayPal account permission to use OXXO payment functionality by contacting us at (+52) 800–925–0304',
|
||||||
|
@ -669,7 +669,7 @@ class PaymentRestEndpoint extends RestEndpoint {
|
||||||
|
|
||||||
$gateway_settings[ $key ] = array(
|
$gateway_settings[ $key ] = array(
|
||||||
'enabled' => 'yes' === $gateway->enabled,
|
'enabled' => 'yes' === $gateway->enabled,
|
||||||
'title' => $gateway->get_title(),
|
'title' => str_replace( '&', '&', $gateway->get_title() ),
|
||||||
'description' => $gateway->get_description(),
|
'description' => $gateway->get_description(),
|
||||||
'id' => $this->gateways()[ $key ]['id'] ?? $key,
|
'id' => $this->gateways()[ $key ]['id'] ?? $key,
|
||||||
'icon' => $this->gateways()[ $key ]['icon'] ?? '',
|
'icon' => $this->gateways()[ $key ]['icon'] ?? '',
|
||||||
|
@ -687,7 +687,7 @@ class PaymentRestEndpoint extends RestEndpoint {
|
||||||
$gateway_settings['fastlaneCardholderName'] = $this->settings->get_fastlane_cardholder_name();
|
$gateway_settings['fastlaneCardholderName'] = $this->settings->get_fastlane_cardholder_name();
|
||||||
$gateway_settings['fastlaneDisplayWatermark'] = $this->settings->get_fastlane_display_watermark();
|
$gateway_settings['fastlaneDisplayWatermark'] = $this->settings->get_fastlane_display_watermark();
|
||||||
|
|
||||||
return $this->return_success( $gateway_settings );
|
return $this->return_success( apply_filters( 'woocommerce_paypal_payments_payment_methods', $gateway_settings ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,6 +9,17 @@ declare( strict_types = 1 );
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\Settings;
|
namespace WooCommerce\PayPalCommerce\Settings;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||||
|
use WooCommerce\PayPalCommerce\Applepay\Assets\AppleProductStatus;
|
||||||
|
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus;
|
||||||
|
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\BancontactGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\BlikGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\EPSGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\IDealGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\MultibancoGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\MyBankGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\P24Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\TrustlyGateway;
|
||||||
use WooCommerce\PayPalCommerce\Settings\Ajax\SwitchSettingsUiEndpoint;
|
use WooCommerce\PayPalCommerce\Settings\Ajax\SwitchSettingsUiEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
|
use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
|
||||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\RestEndpoint;
|
use WooCommerce\PayPalCommerce\Settings\Endpoint\RestEndpoint;
|
||||||
|
@ -17,6 +28,11 @@ use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXO;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\PayUponInvoiceGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,6 +185,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
|
||||||
'wcPaymentsTabUrl' => admin_url( 'admin.php?page=wc-settings&tab=checkout' ),
|
'wcPaymentsTabUrl' => admin_url( 'admin.php?page=wc-settings&tab=checkout' ),
|
||||||
'debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
|
'debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
|
||||||
'isPayLaterConfiguratorAvailable' => $is_pay_later_configurator_available,
|
'isPayLaterConfiguratorAvailable' => $is_pay_later_configurator_available,
|
||||||
|
'storeCountry' => $container->get( 'wcgateway.store-country' ),
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $is_pay_later_configurator_available ) {
|
if ( $is_pay_later_configurator_available ) {
|
||||||
|
@ -264,6 +281,69 @@ class SettingsModule implements ServiceModule, ExecutableModule {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_paypal_payments_payment_methods',
|
||||||
|
function( array $payment_methods ) use ( $container ) : array {
|
||||||
|
$all_payment_methods = $payment_methods;
|
||||||
|
|
||||||
|
$dcc_product_status = $container->get( 'wcgateway.helper.dcc-product-status' );
|
||||||
|
assert( $dcc_product_status instanceof DCCProductStatus );
|
||||||
|
|
||||||
|
$googlepay_product_status = $container->get( 'googlepay.helpers.apm-product-status' );
|
||||||
|
assert( $googlepay_product_status instanceof ApmProductStatus );
|
||||||
|
|
||||||
|
$applepay_product_status = $container->get( 'applepay.apple-product-status' );
|
||||||
|
assert( $applepay_product_status instanceof AppleProductStatus );
|
||||||
|
|
||||||
|
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
|
||||||
|
assert( $dcc_applies instanceof DCCApplies );
|
||||||
|
|
||||||
|
// Unset BCDC if merchant is eligible for ACDC.
|
||||||
|
if ( $dcc_product_status->dcc_is_active() && ! $container->get( 'wcgateway.settings.allow_card_button_gateway' ) ) {
|
||||||
|
unset( $payment_methods[ CardButtonGateway::ID ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset Venmo when store location is not United States.
|
||||||
|
if ( $container->get( 'api.shop.country' ) !== 'US' ) {
|
||||||
|
unset( $payment_methods['venmo'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset if not eligible for Google Pay.
|
||||||
|
if ( ! $googlepay_product_status->is_active() ) {
|
||||||
|
unset( $payment_methods['ppcp-googlepay'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset if not eligible for Apple Pay.
|
||||||
|
if ( ! $applepay_product_status->is_active() ) {
|
||||||
|
unset( $payment_methods['ppcp-applepay'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset Fastlane if store location is not United States or merchant is not eligible for ACDC.
|
||||||
|
if ( $container->get( 'api.shop.country' ) !== 'US' || ! $dcc_product_status->dcc_is_active() ) {
|
||||||
|
unset( $payment_methods['ppcp-axo-gateway'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// For non-ACDC regions unset ACDC, local APMs and set BCDC.
|
||||||
|
if ( ! $dcc_applies ) {
|
||||||
|
unset( $payment_methods[ CreditCardGateway::ID ] );
|
||||||
|
unset( $payment_methods[ BancontactGateway::ID ] );
|
||||||
|
unset( $payment_methods[ BlikGateway::ID ] );
|
||||||
|
unset( $payment_methods[ EPSGateway::ID ] );
|
||||||
|
unset( $payment_methods[ IDealGateway::ID ] );
|
||||||
|
unset( $payment_methods[ MyBankGateway::ID ] );
|
||||||
|
unset( $payment_methods[ P24Gateway::ID ] );
|
||||||
|
unset( $payment_methods[ TrustlyGateway::ID ] );
|
||||||
|
unset( $payment_methods[ MultibancoGateway::ID ] );
|
||||||
|
unset( $payment_methods[ PayUponInvoiceGateway::ID ] );
|
||||||
|
unset( $payment_methods[ OXXO::ID ] );
|
||||||
|
|
||||||
|
$payment_methods[ CardButtonGateway::ID ] = $all_payment_methods[ CardButtonGateway::ID ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $payment_methods;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1659,9 +1659,12 @@ return array(
|
||||||
$settings = $container->get( 'wcgateway.settings' );
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
assert( $settings instanceof ContainerInterface );
|
assert( $settings instanceof ContainerInterface );
|
||||||
|
|
||||||
return $settings->has( 'allow_card_button_gateway' ) ?
|
return apply_filters(
|
||||||
|
'woocommerce_paypal_payments_enable_standard_card_button_gateway_settings',
|
||||||
|
$settings->has( 'allow_card_button_gateway' ) ?
|
||||||
(bool) $settings->get( 'allow_card_button_gateway' ) :
|
(bool) $settings->get( 'allow_card_button_gateway' ) :
|
||||||
$container->get( 'wcgateway.settings.allow_card_button_gateway.default' );
|
$container->get( 'wcgateway.settings.allow_card_button_gateway.default' )
|
||||||
|
);
|
||||||
},
|
},
|
||||||
'wcgateway.settings.has_enabled_separate_button_gateways' => static function ( ContainerInterface $container ): bool {
|
'wcgateway.settings.has_enabled_separate_button_gateways' => static function ( ContainerInterface $container ): bool {
|
||||||
return (bool) $container->get( 'wcgateway.settings.allow_card_button_gateway' );
|
return (bool) $container->get( 'wcgateway.settings.allow_card_button_gateway' );
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue