Finish settings page

This commit is contained in:
inpsyde-maticluznar 2024-11-13 17:29:11 +01:00
parent e72cc8a213
commit b23a9a0fab
No known key found for this signature in database
GPG key ID: D005973F231309F6
20 changed files with 692 additions and 433 deletions

View file

@ -13,6 +13,7 @@
"@wordpress/scripts": "^30.3.0"
},
"dependencies": {
"@woocommerce/settings": "^1.0.0"
"@woocommerce/settings": "^1.0.0",
"react-select": "^5.8.3"
}
}

View file

@ -40,6 +40,9 @@
font-style: italic;
}
@mixin primaryFont{
font-family: "PayPalPro", sans-serif;
}
* {
font-family: "PayPalPro", sans-serif;
@ -56,16 +59,4 @@ a:not(.button) {
color: $color-blueberry;
}
input[type='text'] {
padding: 7px 11px;
@include font(14, 20, 400);
}
select {
padding: 7px 27px 7px 11px;
@include font(14, 20, 400);
}
.components-form-toggle.is-checked > .components-form-toggle__track {
background-color: $color-blueberry;
}

View file

@ -7,7 +7,7 @@
}
}
@mixin hide-input-field(){
@mixin hide-input-field() {
width: 100%;
height: 100%;
position: absolute;
@ -18,7 +18,7 @@
border-radius: 0;
}
@mixin fake-input-field($border-radius:0){
@mixin fake-input-field($border-radius:0) {
width: 20px;
height: 20px;
border: 1px solid $color-gray-600;
@ -27,8 +27,19 @@
border-radius: $border-radius;
}
@mixin small-button{
@mixin small-button {
border-radius: 2px;
padding: 6px 12px;
@include font(13, 20, 400);
}
@mixin vertical-layout-event-gap($gap:0) {
display: flex;
flex-direction: column;
gap: $gap;
}
@mixin horizontal-layout-even-gap($gap:0) {
display: flex;
gap: $gap;
}

View file

@ -55,10 +55,56 @@
&__radio-description {
@include font(14, 20, 400);
margin: 4px 0 0 0;
color:$color-gray-800;
margin: 0;
color: $color-gray-800;
}
&__radio-content-additional {
padding-left: 38px;
padding-top: 18px;
}
}
.components-base-control {
&__label {
color: $color-gray-900;
@include font(13, 16, 600);
text-transform: none;
}
&__input {
border: 1px solid $color-gray-700;
border-radius: 2px;
box-shadow: none;
&:focus {
border-color: $color-blueberry;
}
}
}
input[type='text'] {
padding: 7px 11px;
@include font(14, 20, 400);
@include primaryFont;
border-radius: 2px;
}
select {
padding: 7px 27px 7px 11px;
@include font(14, 20, 400);
}
.components-form-toggle.is-checked > .components-form-toggle__track {
background-color: $color-blueberry;
}
.ppcp-r-vertical-text-control {
.components-base-control__field {
display: flex;
flex-direction: column;
gap: 8px;
margin: 0;
}
}

View file

@ -72,11 +72,6 @@
margin: 0;
border-color: $color-gray-700;
}
label {
@include font(14, 16, 400);
color: $color-gray-900;
}
}
&__field-rows {

View file

@ -1,17 +0,0 @@
.components-base-control {
&__label {
color: $color-gray-900;
@include font(13, 16, 600);
margin: 0 0 8px 0;
text-transform: none;
}
&__input {
border: 1px solid $color-gray-700;
border-radius: 2px;
box-shadow: none;
&:focus{
border-color:$color-blueberry;
}
}
}

View file

@ -1,43 +1,39 @@
// Global settings styles
.ppcp-r-settings {
display: flex;
flex-direction: column;
gap: 48px;
@include vertical-layout-event-gap(48px);
}
.ppcp-r-settings-card {
&.ppcp-r-settings-card--expert-settings {
.ppcp-r-settings-card__header {
margin-bottom: 48px;
}
> .ppcp-r-settings-card__content > .ppcp-r-settings-block:not(.ppcp-r-settings-block--tertiary) {
padding-bottom: 32px;
margin-bottom: 32px;
&:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}
.ppcp-r-settings-card__content {
> .ppcp-r-settings-block {
&:not(:last-child) {
border-bottom: 1.5px solid $color-gray-700;
}
}
}
.ppcp-r-settings-block {
&--primary {
padding-bottom: 48px;
margin-bottom: 48px;
border-bottom: 1px solid $color-gray-700;
.ppcp-r-settings-block__header {
display: flex;
gap: 48px;
&-inner {
display: flex;
flex-direction: column;
gap: 4px;
}
}
&__action {
margin-left: auto;
}
&--primary {
> .ppcp-r-settings-block__header {
.ppcp-r-settings-block__title {
@include font(16, 20, 700);
color: $color-black;
}
.ppcp-r-settings-block__description {
margin-top: 8px;
}
}
}
@ -45,8 +41,7 @@
> .ppcp-r-settings-block__header {
.ppcp-r-settings-block__title {
@include font(16, 20, 600);
color: $color-gray-900;
margin-bottom: 8px;
color: $color-gray-800;
}
}
}
@ -65,64 +60,7 @@
}
}
&--separated-settings {
> .ppcp-r-settings-block__content {
gap: 0;
> .ppcp-r-settings-block {
border-bottom: 1px solid $color-gray-500;
padding-bottom: 32px;
margin-bottom: 32px;
&:last-child {
border: none;
padding: 0;
margin: 0;
}
}
}
}
&__title {
display: flex;
align-items: center;
gap: 12px;
}
&--toggle-content {
> .ppcp-r-settings-block__header {
align-items: center;
cursor: pointer;
* {
user-select: none;
}
.ppcp-r-settings-block__action {
transition: 0.2s transform ease-out;
}
&:hover {
.ppcp-r-settings-block__action {
transform: scale(1.2);
}
}
}
}
&--button {
> .ppcp-r-settings-block__header {
align-items: center;
}
}
&--content-visible {
.ppcp-r-settings-block__toggle-content {
transform: rotate(180deg);
}
}
&__description {
.ppcp-r-settings-block__description {
margin: 0;
@include font(14, 20, 400);
color: $color-gray-800;
@ -136,55 +74,77 @@
}
}
&__action {
margin-left: auto;
// Types
&--toggle-content {
&.ppcp-r-settings-block--content-visible {
.ppcp-r-settings-block__toggle-content {
transform: rotate(180deg);
}
}
.ppcp-r-settings-block__header {
user-select: none;
&:hover {
cursor: pointer;
}
}
}
&--sandbox-connected {
.ppcp-r-settings-block__content {
margin-top: 24px;
}
button.is-secondary {
padding: 6px 12px;
min-width: 166px;
@include font(13, 20, 400);
justify-content: center;
@include small-button;
}
.ppcp-r-connection-status__data {
margin-bottom: 20px;
}
}
&__toggle {
.components-form-toggle {
order: 1;
&--expert-rdb{
@include vertical-layout-event-gap(24px);
}
&--connect-sandbox {
button.components-button {
@include small-button;
}
.ppcp-r__radio-content-additional {
.ppcp-r-vertical-text-control {
width: 100%;
}
@include vertical-layout-event-gap(24px);
align-items: flex-start;
input[type='text'] {
width: 100%;
}
}
}
&__content {
display: flex;
flex-direction: column;
gap: 32px;
margin-top: 32px;
}
&__header {
display: flex;
gap: 48px;
&-inner {
display: flex;
flex-direction: column;
&--troubleshooting {
> .ppcp-r-settings-block__content > *:not(:last-child) {
padding-bottom: 32px;
margin-bottom: 32px;
border-bottom: 1px solid $color-gray-500;
}
}
&__mismatch-wrapper {
display: flex;
flex-direction: column;
gap: 24px;
}
&--order-intent {
.ppcp-r-settings-block__content .ppcp-r-settings-block__title {
font-size: 14px;
margin-bottom: 4px;
color: $color-gray-800;
&--settings{
> .ppcp-r-settings-block__content > *:not(:last-child){
padding-bottom: 32px;
margin-bottom: 32px;
border-bottom: 1px solid $color-gray-500;
}
}
input[type='text'], select {
// Fields
input[type='text'] {
border-color: $color-gray-700;
width: 282px;
max-width: 100%;
@ -197,37 +157,75 @@
}
}
.ppcp-r-select-no-value-assigned > div > select {
color: $color-gray-600;
}
&__sandbox {
button.is-secondary {
@include small-button;
.ppcp-r {
&__radio-wrapper {
align-items: flex-start;
gap: 12px;
}
.ppcp-r-connection-status__data {
margin-bottom: 24px;
&__radio-content {
display: flex;
flex-direction: column;
gap: 4px;
label {
font-weight: 600;
}
}
&__radio-content-additional {
padding-left: 32px;
}
}
.ppcp-r__radio-wrapper {
align-items: flex-start;
}
.ppcp-r__radio-content {
label {
font-weight: 600;
// MultiSelect control
.ppcp-r {
&__control {
border-radius: 2px;
border-color: $color-gray-700;
width: 282px;
min-height: auto;
padding: 0;
}
}
.ppcp-r__radio {
padding-top: 2px;
&__input-container {
padding: 0;
margin: 0;
}
&__value-container {
padding: 0 0 0 7px;
}
&__indicator {
padding: 5px;
}
&__indicator-separator {
display: none;
}
&__value-container--has-value {
.ppcp-r__single-value {
color: $color-gray-800;
}
}
&__placeholde, &__single-value {
@include font(13, 20, 400);
}
&__option {
&--is-selected {
background-color: $color-gray-200;
}
}
}
}
// Special settings styles
// Hooks table
.ppcp-r-table {
&__hooks-url {
width: 70%;
@ -264,3 +262,51 @@
padding-bottom: 4px;
}
}
// Common settings have 48px margin&padding bottom between blocks
.ppcp-r-settings-card--common-settings .ppcp-r-settings-card__content {
> .ppcp-r-settings-block {
&:not(:last-child) {
padding-bottom: 48px;
margin-bottom: 48px;
}
}
}
// Expert settings have 32px margin&padding bottom between blocks
.ppcp-r-settings-card--expert-settings .ppcp-r-settings-card__content {
> .ppcp-r-settings-block {
&:not(:last-child) {
padding-bottom: 32px;
margin-bottom: 32px;
}
}
}
// Order intent block has 32px gap and no lines in between
// Save payment methods block has 32px gap and no lines in between
.ppcp-r-settings-block {
&--order-intent, &--save-payment-methods {
@include vertical-layout-event-gap(32px);
> .ppcp-r-settings-block__content {
@include vertical-layout-event-gap(32px);
}
}
}
// Most primary settings block in the expert settings have 32px space after description
.ppcp-r-settings-block--toggle-content {
.ppcp-r-settings-block__content {
margin-top: 32px;
}
}
// Common settings have actions aligned top with the text, Expert settings have actions alligned middle with the text
.ppcp-r-settings-card--expert-settings {
.ppcp-r-settings-block__header {
align-items: center;
}
}

View file

@ -6,7 +6,6 @@
@import './components/reusable-components/onboarding-header';
@import './components/reusable-components/button';
@import './components/reusable-components/settings-toggle-block';
@import './components/reusable-components/text-control';
@import './components/reusable-components/separator';
@import './components/reusable-components/payment-method-icons';
@import "./components/reusable-components/payment-method-item";
@ -20,7 +19,7 @@
@import './components/screens/onboarding';
@import './components/screens/dashboard/tab-dashboard';
@import './components/screens/dashboard/tab-payment-methods';
@import './components/screens/dashboard/tab-settings';
@import 'components/screens/dashboard/tab-settings';
}
@import './components/reusable-components/payment-method-modal';

View file

@ -45,21 +45,25 @@ export const PayPalRdbWithContent = ( props ) => {
}
return (
<div className={ className }>
<PayPalRdb { ...props } />
<div className="ppcp-r__radio-content">
<label htmlFor={ props?.id }>{ props.label }</label>
{ props.description && (
<p className="ppcp-r__radio-description">
{ props.description }
</p>
) }
{ props.children && (
<div className="ppcp-r__radio-outer-wrapper">
<div className={ className }>
<PayPalRdb { ...props } />
<div className="ppcp-r__radio-content">
<label htmlFor={ props?.id }>{ props.label }</label>
{ props.description && (
<p className="ppcp-r__radio-description">
{ props.description }
</p>
) }
</div>
</div>
{ props?.toggleAdditionalContent &&
props.children &&
props.value === props.currentValue && (
<div className="ppcp-r__radio-content-additional">
{ props.children }
</div>
) }
</div>
</div>
);
};

View file

@ -1,6 +1,7 @@
import { Button, ToggleControl, SelectControl } from '@wordpress/components';
import { Button, ToggleControl, TextControl } from '@wordpress/components';
import data from '../../utils/data';
import { useState } from '@wordpress/element';
import Select, { components } from 'react-select';
export const SETTINGS_BLOCK_TYPE_EMPTY = 'empty';
export const SETTINGS_BLOCK_TYPE_TOGGLE = 'toggle';
@ -65,72 +66,65 @@ const SettingsBlock = ( {
dangerouslySetInnerHTML={ { __html: description } }
/>
</div>
<div className="ppcp-r-settings-block__action">
{ actionProps?.type === SETTINGS_BLOCK_TYPE_TOGGLE && (
<ToggleControl
className="ppcp-r-settings-block__toggle"
__nextHasNoMarginBottom={ true }
checked={ actionProps?.value }
onChange={ ( newValue ) =>
actionProps?.callback(
actionProps?.key,
newValue
)
}
/>
) }
{ actionProps?.type === SETTINGS_BLOCK_TYPE_INPUT && (
<div>
<input
placeholder={ actionProps?.placeholder }
type="text"
value={ actionProps?.value }
onInput={ ( e ) =>
{ actionProps?.type !== SETTINGS_BLOCK_TYPE_EMPTY && (
<div className="ppcp-r-settings-block__action">
{ actionProps?.type === SETTINGS_BLOCK_TYPE_TOGGLE && (
<ToggleControl
className="ppcp-r-settings-block__toggle"
__nextHasNoMarginBottom={ true }
checked={ actionProps?.value }
onChange={ ( newValue ) =>
actionProps?.callback(
actionProps?.key,
e.target.value
newValue
)
}
/>
</div>
) }
{ actionProps?.type === SETTINGS_BLOCK_TYPE_BUTTON && (
<Button
variant={ actionProps.buttonType }
onClick={
actionProps?.callback
? () => actionProps.callback()
: undefined
}
>
{ actionProps.value }
</Button>
) }
{ actionProps?.type ===
SETTINGS_BLOCK_TYPE_TOGGLE_CONTENT && (
<div className="ppcp-r-settings-block__toggle-content">
{ data().getImage( 'icon-arrow-down.svg' ) }
</div>
) }
{ actionProps?.type === SETTINGS_BLOCK_TYPE_SELECT && (
<SelectControl
className={
actionProps.value === '' &&
'ppcp-r-select-no-value-assigned'
}
value={ actionProps.value }
options={ actionProps?.options }
multiple={ true }
onChange={ ( newValue ) =>
actionProps?.callback &&
actionProps.callback(
actionProps?.key,
newValue
)
}
/>
) }
</div>
) }
{ actionProps?.type === SETTINGS_BLOCK_TYPE_INPUT && (
<>
<TextControl
className="ppcp-r-vertical-text-control"
placeholder={ actionProps?.placeholder }
value={ actionProps?.value }
onChange={ ( newValue ) =>
actionProps?.callback(
actionProps?.key,
newValue
)
}
/>
</>
) }
{ actionProps?.type === SETTINGS_BLOCK_TYPE_BUTTON && (
<Button
variant={ actionProps.buttonType }
onClick={
actionProps?.callback
? () => actionProps.callback()
: undefined
}
>
{ actionProps.value }
</Button>
) }
{ actionProps?.type ===
SETTINGS_BLOCK_TYPE_TOGGLE_CONTENT && (
<div className="ppcp-r-settings-block__toggle-content">
{ data().getImage( 'icon-arrow-down.svg' ) }
</div>
) }
{ actionProps?.type === SETTINGS_BLOCK_TYPE_SELECT && (
<Select
className="ppcp-r-multiselect"
classNamePrefix="ppcp-r"
isMulti={ actionProps?.isMulti }
options={ actionProps?.options }
components={ { DropdownIndicator } }
/>
) }
</div>
) }
</div>
{ children && toggleContentVisible && (
<div className="ppcp-r-settings-block__content">
@ -141,4 +135,12 @@ const SettingsBlock = ( {
);
};
const DropdownIndicator = ( props ) => {
return (
<components.DropdownIndicator { ...props }>
{ data().getImage( 'icon-arrow-down.svg' ) }
</components.DropdownIndicator>
);
};
export default SettingsBlock;

View file

@ -1,6 +1,6 @@
import PaymentMethodModal from '../../../ReusableComponents/PaymentMethodModal';
import { __ } from '@wordpress/i18n';
import { ToggleControl, Button } from '@wordpress/components';
import { ToggleControl, Button, TextControl } from '@wordpress/components';
import { useState } from '@wordpress/element';
const ModalPayPal = ( { setModalIsVisible } ) => {
@ -23,39 +23,30 @@ const ModalPayPal = ( { setModalIsVisible } ) => {
>
<div className="ppcp-r-modal__field-rows">
<div className="ppcp-r-modal__field-row">
<label htmlFor="ppcp-r-paypal-settings-checkout-title">
{ __(
<TextControl
className="ppcp-r-vertical-text-control"
label={ __(
'Checkout page title',
'woocommerce-paypal-payments'
) }
</label>
<input
type="text"
id="ppcp-r-paypal-settings-checkout-title"
value={ paypalSettings.checkoutPageTitle }
onInput={ ( e ) =>
updateFormValue(
'checkoutPageTitle',
e.target.value
)
onChange={ ( newValue ) =>
updateFormValue( 'checkoutPageTitle', newValue )
}
/>
</div>
<div className="ppcp-r-modal__field-row">
<label htmlFor="ppcp-r-paypal-settings-checkout-page-description">
{ __(
<TextControl
className="ppcp-r-vertical-text-control"
label={ __(
'Checkout page description',
'woocommerce-paypal-payments'
) }
</label>
<input
type="text"
id="ppcp-r-paypal-settings-checkout-page-description"
value={ paypalSettings.checkoutPageDescription }
onInput={ ( e ) =>
onChange={ ( newValue ) =>
updateFormValue(
'checkoutPageDescription',
e.target.value
newValue
)
}
/>

View file

@ -11,7 +11,11 @@ const TabSettings = () => {
saveCreditCardAndDebitCard: false,
payNowExperience: false,
sandboxAccountCredentials: false,
enableSandbox: false,
sandboxMode: null,
sandboxEnabled: false,
sandboxClientId: '',
sandboxSecretKey: '',
sandboxConnected: false,
logging: false,
subtotalMismatchFallback: null,
brandName: '',

View file

@ -0,0 +1,66 @@
import SettingsBlock, {
SETTINGS_BLOCK_STYLING_TYPE_PRIMARY,
SETTINGS_BLOCK_STYLING_TYPE_SECONDARY,
SETTINGS_BLOCK_TYPE_SELECT,
SETTINGS_BLOCK_TYPE_TOGGLE_CONTENT,
} from '../../../../ReusableComponents/SettingsBlock';
import { __ } from '@wordpress/i18n';
const OtherSettings = ( { settings, updateFormValue } ) => {
return (
<SettingsBlock
title={ __(
'Other payment method settings',
'woocommerce-paypal-payments'
) }
description={ __(
'Modify the checkout experience for alternative payment methods, credit cards, and digital wallets',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_PRIMARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_TOGGLE_CONTENT,
} }
>
<SettingsBlock
title={ __(
'Disable specific credit cards',
'woocommerce-paypal-payments'
) }
description={ __(
'If left blank, PayPal and other buttons will present in the users detected language. Enter a language here to force all buttons to display in that language.',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_SELECT,
options: creditCardExamples,
value: settings.buttonLanguage,
callback: updateFormValue,
key: 'buttonLanguage',
isMulti: true,
} }
/>
</SettingsBlock>
);
};
const creditCardExamples = [
{ value: '', label: __( 'Select', 'woocommerce-paypal-payments' ) },
{
value: 'mastercard',
label: __( 'Mastercard', 'woocommerce-paypal-payments' ),
},
{ value: 'visa', label: __( 'Visa', 'woocommerce-paypal-payments' ) },
{
value: 'amex',
label: __( 'American Express', 'woocommerce-paypal-payments' ),
},
{ value: 'jcb', label: __( 'JCB', 'woocommerce-paypal-payments' ) },
{
value: 'diners-club',
label: __( 'Diners Club', 'woocommerce-paypal-payments' ),
},
];
export default OtherSettings;

View file

@ -13,6 +13,7 @@ import { PayPalRdbWithContent } from '../../../../ReusableComponents/Fields';
const PaypalSettings = ( { updateFormValue, settings } ) => {
return (
<SettingsBlock
className="ppcp-r-settings-block--settings"
title={ __( 'PayPal Settings', 'woocommerce-paypal-payments' ) }
description={ __(
'Modify the PayPal checkout experience',
@ -40,7 +41,7 @@ const PaypalSettings = ( { updateFormValue, settings } ) => {
type: SETTINGS_BLOCK_TYPE_EMPTY,
} }
>
<div className="ppcp-r-settings-block__mismatch-wrapper">
<div className="ppcp-r-settings-block--mismatch-wrapper ppcp-r-settings-block--expert-rdb">
<PayPalRdbWithContent
id="add_a_correction"
name="paypal_settings_mismatch"
@ -151,7 +152,7 @@ const PaypalSettings = ( { updateFormValue, settings } ) => {
type: SETTINGS_BLOCK_TYPE_EMPTY,
} }
>
<div className="ppcp-r-settings-block__mismatch-wrapper">
<div className="ppcp-r-settings-block--landing ppcp-r-settings-block--expert-rdb">
<PayPalRdbWithContent
id="no_perference"
name="paypal_settings_landing"
@ -229,10 +230,6 @@ const PaypalSettings = ( { updateFormValue, settings } ) => {
};
const languagesExample = [
{
value: '',
label: __( 'Browser language', 'woocommerce-paypal-payments' ),
},
{ value: 'en', label: 'English' },
{ value: 'de', label: 'German' },
{ value: 'es', label: 'Spanish' },

View file

@ -13,12 +13,17 @@ import TitleBadge, {
import ConnectionInfo, {
connectionStatusDataDefault,
} from '../../../../ReusableComponents/ConnectionInfo';
import { Button } from '@wordpress/components';
import { Button, TextControl } from '@wordpress/components';
import { PayPalRdbWithContent } from '../../../../ReusableComponents/Fields';
const Sandbox = ( { settings, updateFormValue } ) => {
const className = settings.sandboxConnected
? 'ppcp-r-settings-block--sandbox-connected'
: 'ppcp-r-settings-block--sandbox-disconnected';
return (
<SettingsBlock
title={ __( 'Sandbox', 'woocommerce-paypal-payments' ) }
className={ className }
description={ __(
"Test your site in PayPal's Sandbox environment.<br /><strong>Note</strong>: No real payments/money movement occur in Sandbox mode. Do not ship orders made in this mode.",
'woocommerce-paypal-payments'
@ -31,59 +36,157 @@ const Sandbox = ( { settings, updateFormValue } ) => {
value: settings.payNowExperience,
} }
>
<SettingsBlock
title={ __(
'Sandbox account credentials',
'woocommerce-paypal-payments'
) }
description={ __(
'Your account is connected to sandbox, no real charging takes place. To accept live payments, turn off sandbox mode and connect your live PayPal account.',
'woocommerce-paypal-payments'
) }
tag={
<TitleBadge
type={ TITLE_BADGE_POSITIVE }
text={ __(
'Connected',
'woocommerce-paypal-payments'
) }
/>
}
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_EMPTY,
callback: updateFormValue,
key: 'sandboxAccountCredentials',
value: settings.sandboxAccountCredentials,
} }
>
<div className="ppcp-r-settings-block__sandbox">
<SettingsBlock
title={ __(
'Enable sandbox mode',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_TERTIARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_TOGGLE,
callback: updateFormValue,
key: 'enableSandbox',
value: settings.enableSandbox,
} }
/>
<ConnectionInfo
connectionStatusDataDefault={
connectionStatusDataDefault
}
/>
<Button variant="secondary">
{ __(
'Disconnect Sandbox',
'woocommerce-paypal-payments'
) }
</Button>
</div>
</SettingsBlock>
{ settings.sandboxConnected && (
<SettingsBlock
title={ __(
'Sandbox account credentials',
'woocommerce-paypal-payments'
) }
description={ __(
'Your account is connected to sandbox, no real charging takes place. To accept live payments, turn off sandbox mode and connect your live PayPal account.',
'woocommerce-paypal-payments'
) }
tag={
<TitleBadge
type={ TITLE_BADGE_POSITIVE }
text={ __(
'Connected',
'woocommerce-paypal-payments'
) }
/>
}
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_EMPTY,
callback: updateFormValue,
key: 'sandboxAccountCredentials',
value: settings.sandboxAccountCredentials,
} }
>
<div className="ppcp-r-settings-block--sandbox">
<SettingsBlock
title={ __(
'Enable sandbox mode',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_TERTIARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_TOGGLE,
callback: updateFormValue,
key: 'sandboxEnabled',
value: settings.sandboxEnabled,
} }
/>
<ConnectionInfo
connectionStatusDataDefault={
connectionStatusDataDefault
}
/>
<Button
variant="secondary"
onClick={ () =>
updateFormValue( 'sandboxConnected', false )
}
>
{ __(
'Disconnect Sandbox',
'woocommerce-paypal-payments'
) }
</Button>
</div>
</SettingsBlock>
) }
{ ! settings.sandboxConnected && (
<SettingsBlock
title={ __(
'Connect Sandbox Account',
'woocommerce-paypal-payments'
) }
description={ __(
'Connect a PayPal Sandbox account in order to test your website. Transactions made will not result in actual money movement. Do not fulfil orders completed in Sandbox mode.',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_EMPTY,
callback: updateFormValue,
key: 'sandboxAccountCredentials',
value: settings.sandboxAccountCredentials,
} }
>
<div className="ppcp-r-settings-block--connect-sandbox ppcp-r-settings-block--expert-rdb">
<PayPalRdbWithContent
id="sandbox_mode"
name="paypal_connect_sandbox"
value="sandbox_mode"
currentValue={ settings.sandboxMode }
toggleAdditionalContent={ true }
handleRdbState={ ( newValue ) =>
updateFormValue( 'sandboxMode', newValue )
}
label={ __(
'Sandbox Mode',
'woocommerce-paypal-payments'
) }
description={ __(
'Activate Sandbox mode to safely test PayPal with sample data. Once your store is ready to go live, you can easily switch to your production account.',
'woocommerce-paypal-payments'
) }
>
<Button
variant="primary"
onClick={ () =>
updateFormValue( 'sandboxConnected', true )
}
>
{ __(
'Connect Sandbox Account',
'woocommerce-paypal-payments'
) }
</Button>
</PayPalRdbWithContent>
<PayPalRdbWithContent
id="manual_connect"
name="paypal_connect_sandbox"
value="manual_connect"
currentValue={ settings.sandboxMode }
toggleAdditionalContent={ true }
handleRdbState={ ( newValue ) =>
updateFormValue( 'sandboxMode', newValue )
}
label={ __(
'Manual Connect',
'woocommerce-paypal-payments'
) }
description={ __(
'For advanced users: Connect a custom PayPal REST app for full control over your integration. For more information on creating a PayPal REST application, click here.',
'woocommerce-paypal-payments'
) }
>
<TextControl
className="ppcp-r-vertical-text-control"
label={ __(
'Sandbox Client ID',
'woocommerce-paypal-payments'
) }
/>
<TextControl
className="ppcp-r-vertical-text-control"
label={ __(
'Sandbox Secrey Key',
'woocommerce-paypal-payments'
) }
/>
<Button variant="primary">
{ __(
'Connect Account',
'woocommerce-paypal-payments'
) }
</Button>
</PayPalRdbWithContent>
</div>
</SettingsBlock>
) }
</SettingsBlock>
);
};

View file

@ -9,6 +9,7 @@ import { __ } from '@wordpress/i18n';
const SavePaymentMethods = ( { updateFormValue, settings } ) => {
return (
<SettingsBlock
className="ppcp-r-settings-block--save-payment-methods"
title={ __(
'Save Payment Methods',
'woocommerce-paypal-payments'
@ -29,7 +30,7 @@ const SavePaymentMethods = ( { updateFormValue, settings } ) => {
'woocommerce-paypal-payments'
) }
description={ __(
'Securely store your customers PayPal accounts for a seamless checkout experience. This will disable all Pay Later features and Alternative Payment Methods on your site.',
'Securely store your customers PayPal accounts for a seamless checkout experience. <br />This will disable all Pay Later features and Alternative Payment Methods on your site.',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }

View file

@ -11,7 +11,7 @@ import { __ } from '@wordpress/i18n';
const Troubleshooting = ( { updateFormValue, settings } ) => {
return (
<SettingsBlock
className="ppcp-r-settings-block--separated-settings"
className="ppcp-r-settings-block--troubleshooting"
title={ __( 'Troubleshooting', 'woocommerce-paypal-payments' ) }
description={ __(
'Access tools to help debug and resolve issues.',
@ -57,51 +57,52 @@ const Troubleshooting = ( { updateFormValue, settings } ) => {
} }
>
<HooksTable data={ hooksExampleData() } />
<SettingsBlock
title={ __(
'Resubscribe webhooks',
'woocommerce-paypal-payments'
) }
description={ __(
'Click to remove the current webhook subscription and subscribe again, for example, if the website domain or URL structure changed.',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_BUTTON,
buttonType: 'secondary',
callback: () =>
console.log(
'Resubscribe webhooks',
'woocommerce-paypal-payments'
),
value: __(
</SettingsBlock>
<SettingsBlock
title={ __(
'Resubscribe webhooks',
'woocommerce-paypal-payments'
) }
description={ __(
'Click to remove the current webhook subscription and subscribe again, for example, if the website domain or URL structure changed.',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_BUTTON,
buttonType: 'secondary',
callback: () =>
console.log(
'Resubscribe webhooks',
'woocommerce-paypal-payments'
),
} }
/>
<SettingsBlock
title={ __(
'Simulate webhooks',
value: __(
'Resubscribe webhooks',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_BUTTON,
buttonType: 'secondary',
callback: () =>
console.log(
'Simulate webhooks',
'woocommerce-paypal-payments'
),
value: __(
),
} }
/>
<SettingsBlock
title={ __(
'Simulate webhooks',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_BUTTON,
buttonType: 'secondary',
callback: () =>
console.log(
'Simulate webhooks',
'woocommerce-paypal-payments'
),
} }
/>
</SettingsBlock>
value: __(
'Simulate webhooks',
'woocommerce-paypal-payments'
),
} }
/>
</SettingsBlock>
);
};

View file

@ -9,6 +9,7 @@ import SettingsCard from '../../../ReusableComponents/SettingsCard';
import Sandbox from './Blocks/Sandbox';
import Troubleshooting from './Blocks/Troubleshooting';
import PaypalSettings from './Blocks/PaypalSettings';
import OtherSettings from './Blocks/OtherSettings';
const ExpertSettings = ( { updateFormValue, settings } ) => {
return (
@ -39,59 +40,12 @@ const ExpertSettings = ( { updateFormValue, settings } ) => {
updateFormValue={ updateFormValue }
settings={ settings }
/>
<SettingsBlock
title={ __(
'Other payment method settings',
'woocommerce-paypal-payments'
) }
description={ __(
'Modify the checkout experience for alternative payment methods, credit cards, and digital wallets',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_PRIMARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_TOGGLE_CONTENT,
} }
>
<SettingsBlock
title={ __(
'Disable specific credit cards',
'woocommerce-paypal-payments'
) }
description={ __(
'If left blank, PayPal and other buttons will present in the users detected language. Enter a language here to force all buttons to display in that language.',
'woocommerce-paypal-payments'
) }
style={ SETTINGS_BLOCK_STYLING_TYPE_SECONDARY }
actionProps={ {
type: SETTINGS_BLOCK_TYPE_SELECT,
options: creditCardExamples,
value: settings.buttonLanguage,
callback: updateFormValue,
key: 'buttonLanguage',
} }
/>
</SettingsBlock>
<OtherSettings
updateFormValue={ updateFormValue }
settings={ settings }
/>
</SettingsCard>
);
};
const creditCardExamples = [
{ value: '', label: __( 'Select', 'woocommerce-paypal-payments' ) },
{
value: 'mastercard',
label: __( 'Mastercard', 'woocommerce-paypal-payments' ),
},
{ value: 'visa', label: __( 'Visa', 'woocommerce-paypal-payments' ) },
{
value: 'amex',
label: __( 'American Express', 'woocommerce-paypal-payments' ),
},
{ value: 'jcb', label: __( 'JCB', 'woocommerce-paypal-payments' ) },
{
value: 'diners-club',
label: __( 'Diners Club', 'woocommerce-paypal-payments' ),
},
];
export default ExpertSettings;

View file

@ -1132,7 +1132,7 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.12.5", "@babel/runtime@^7.14.8", "@babel/runtime@^7.16.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.8", "@babel/runtime@^7.16.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.26.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
@ -1221,7 +1221,7 @@
source-map "^0.5.7"
stylis "4.2.0"
"@emotion/cache@^11.13.0", "@emotion/cache@^11.7.1":
"@emotion/cache@^11.13.0", "@emotion/cache@^11.4.0", "@emotion/cache@^11.7.1":
version "11.13.1"
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7"
integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==
@ -1272,7 +1272,7 @@
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102"
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
"@emotion/react@^11.7.1":
"@emotion/react@^11.7.1", "@emotion/react@^11.8.1":
version "11.13.3"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.3.tgz#a69d0de2a23f5b48e0acf210416638010e4bd2e4"
integrity sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==
@ -1385,6 +1385,13 @@
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.6.2.tgz#f2813f0e5f3d5ed7af5029e1a082203dadf02b7d"
integrity sha512-jktYRmZwmau63adUG3GKOAVCofBXkk55S/zQ94XOorAHhwqFIOFAy1rSp2N0Wp6/tGbe9V3u/ExlGZypyY17rg==
"@floating-ui/core@^1.6.0":
version "1.6.8"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.8.tgz#aa43561be075815879305965020f492cdb43da12"
integrity sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==
dependencies:
"@floating-ui/utils" "^0.2.8"
"@floating-ui/dom@^0.4.5":
version "0.4.5"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.4.5.tgz#2e88d16646119cc67d44683f75ee99840475bbfa"
@ -1392,6 +1399,14 @@
dependencies:
"@floating-ui/core" "^0.6.2"
"@floating-ui/dom@^1.0.1":
version "1.6.12"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.12.tgz#6333dcb5a8ead3b2bf82f33d6bc410e95f54e556"
integrity sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==
dependencies:
"@floating-ui/core" "^1.6.0"
"@floating-ui/utils" "^0.2.8"
"@floating-ui/react-dom@0.6.3":
version "0.6.3"
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.6.3.tgz#7b64cfd4fd12e4a0515dbf1b2be16e48c9a06c5a"
@ -1400,6 +1415,11 @@
"@floating-ui/dom" "^0.4.5"
use-isomorphic-layout-effect "^1.1.1"
"@floating-ui/utils@^0.2.8":
version "0.2.8"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.8.tgz#21a907684723bbbaa5f0974cf7730bd797eb8e62"
integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
@ -2428,6 +2448,13 @@
dependencies:
"@types/react" "*"
"@types/react-transition-group@^4.4.0":
version "4.4.11"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.11.tgz#d963253a611d757de01ebb241143b1017d5d63d5"
integrity sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^18.2.79":
version "18.3.12"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.12.tgz#99419f182ccd69151813b7ee24b792fe08774f60"
@ -5209,6 +5236,14 @@ document.contains@^1.0.1:
dependencies:
define-properties "^1.1.3"
dom-helpers@^5.0.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
dependencies:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
dom-scroll-into-view@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz#e8f36732dd089b0201a88d7815dc3f88e6d66c7e"
@ -8218,6 +8253,11 @@ memize@^2.1.0:
resolved "https://registry.yarnpkg.com/memize/-/memize-2.1.0.tgz#6ddd4717887d94825748149ece00d04cf868ce0d"
integrity sha512-yywVJy8ctVlN5lNPxsep5urnZ6TTclwPEyigM9M3Bi8vseJBOfqNrGWN/r8NzuIt3PovM323W04blJfGQfQSVg==
memoize-one@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
meow@^13.2.0:
version "13.2.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-13.2.0.tgz#6b7d63f913f984063b3cc261b6e8800c4cd3474f"
@ -9340,7 +9380,7 @@ prop-types-exact@^1.2.0:
object.assign "^4.1.5"
reflect.ownkeys "^1.1.4"
prop-types@^15.5.8, prop-types@^15.7.2, prop-types@^15.8.1:
prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -9596,6 +9636,31 @@ react-refresh@^0.14.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9"
integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==
react-select@^5.8.3:
version "5.8.3"
resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.8.3.tgz#64e89ad20a846348b18c6fbb395b939d0153ed74"
integrity sha512-lVswnIq8/iTj1db7XCG74M/3fbGB6ZaluCzvwPGT5ZOjCdL/k0CLWhEK0vCBLuU5bHTEf6Gj8jtSvi+3v+tO1w==
dependencies:
"@babel/runtime" "^7.12.0"
"@emotion/cache" "^11.4.0"
"@emotion/react" "^11.8.1"
"@floating-ui/dom" "^1.0.1"
"@types/react-transition-group" "^4.4.0"
memoize-one "^6.0.0"
prop-types "^15.6.0"
react-transition-group "^4.3.0"
use-isomorphic-layout-effect "^1.1.2"
react-transition-group@^4.3.0:
version "4.4.5"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-with-direction@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/react-with-direction/-/react-with-direction-1.4.0.tgz#ebdf64d685d0650ce966e872e6431ad5a2485444"
@ -11272,7 +11337,7 @@ urlpattern-polyfill@10.0.0:
resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz#f0a03a97bfb03cdf33553e5e79a2aadd22cac8ec"
integrity sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==
use-isomorphic-layout-effect@^1.1.1:
use-isomorphic-layout-effect@^1.1.1, use-isomorphic-layout-effect@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb"
integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==

View file

@ -233,4 +233,3 @@ define( 'PPCP_PAYPAL_BN_CODE', 'Woo_PPCP' );
}
} )();
add_filter( 'woocommerce.feature-flags.woocommerce_paypal_payments.settings_enabled', '__return_true' );