* add shipping address to self hosted signup model
* purchase modals allow scroll
* fix z-index issues with payment modal dropdowns
Этот коммит содержится в:
Nathaniel Allred
2023-03-24 14:46:22 -05:00
коммит произвёл GitHub
родитель 379dbb1ca8
Коммит 9105077ee1
15 изменённых файлов: 438 добавлений и 171 удалений

Просмотреть файл

@@ -21,10 +21,11 @@ type BootstrapSelfHostedSignupResponseInternal struct {
// email contained in token, so not in the request body. // email contained in token, so not in the request body.
type SelfHostedCustomerForm struct { type SelfHostedCustomerForm struct {
FirstName string `json:"first_name"` FirstName string `json:"first_name"`
LastName string `json:"last_name"` LastName string `json:"last_name"`
BillingAddress *Address `json:"billing_address"` BillingAddress *Address `json:"billing_address"`
Organization string `json:"organization"` ShippingAddress *Address `json:"shipping_address"`
Organization string `json:"organization"`
} }
type SelfHostedConfirmPaymentMethodRequest struct { type SelfHostedConfirmPaymentMethodRequest struct {

Просмотреть файл

@@ -0,0 +1,37 @@
.shipping-address-section {
display: flex;
align-content: flex-start;
padding-bottom: 24px;
font-weight: normal;
button.no-style {
padding-left: 0;
border: none;
background: transparent;
outline: unset;
text-align: left;
&:focus {
outline: unset;
}
}
#address-same-than-billing-address {
width: 17px;
height: 17px;
flex-shrink: 0;
}
.Form-checkbox-label {
padding-left: 12px;
cursor: default;
font-family: 'Open Sans', sans-serif;
vertical-align: middle;
}
.billing_address_btn_text {
color: var(--center-channel-color);
font-family: 'Open Sans', sans-serif;
font-weight: bold;
}
}

Просмотреть файл

@@ -0,0 +1,45 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {useIntl} from 'react-intl';
import './choose_different_shipping.scss';
interface Props {
shippingIsSame: boolean;
setShippingIsSame: (different: boolean) => void;
}
export default function ChooseDifferentShipping(props: Props) {
const intl = useIntl();
const toggle = () => props.setShippingIsSame(!props.shippingIsSame);
return (
<div className='shipping-address-section'>
<input
id='address-same-than-billing-address'
className='Form-checkbox-input'
name='terms'
type='checkbox'
checked={props.shippingIsSame}
onChange={toggle}
/>
<span className='Form-checkbox-label'>
<button
onClick={toggle}
type='button'
className='no-style'
>
<span className='billing_address_btn_text'>
{intl.formatMessage({
id: 'admin.billing.subscription.complianceScreenShippingSameAsBilling',
defaultMessage:
'My shipping address is the same as my billing address',
})}
</span>
</button>
</span>
</div>
);
}

Просмотреть файл

@@ -1,5 +1,7 @@
$dropdown_input_index: 999999;
.DropdownInput { .DropdownInput {
z-index: 999999; z-index: $dropdown_input_index;
&.Input_container { &.Input_container {
margin-top: 20px; margin-top: 20px;
@@ -37,7 +39,7 @@
} }
.DropdownInput__option > div { .DropdownInput__option > div {
z-index: 999999; z-index: $dropdown_input_index;
padding: 10px 24px; padding: 10px 24px;
cursor: pointer; cursor: pointer;
line-height: 16px; line-height: 16px;
@@ -51,3 +53,33 @@
.DropdownInput__option.focused > div { .DropdownInput__option.focused > div {
background-color: rgba(var(--center-channel-color-rgb), 0.08); background-color: rgba(var(--center-channel-color-rgb), 0.08);
} }
.second-dropdown-sibling-wrapper {
.DropdownInput {
z-index: $dropdown_input_index - 1;
}
.DropdownInput__option > div {
z-index: $dropdown_input_index - 1;
}
}
.third-dropdown-sibling-wrapper {
.DropdownInput {
z-index: $dropdown_input_index - 2;
}
.DropdownInput__option > div {
z-index: $dropdown_input_index - 2;
}
}
.fourth-dropdown-sibling-wrapper {
.DropdownInput {
z-index: $dropdown_input_index - 3;
}
.DropdownInput__option > div {
z-index: $dropdown_input_index - 3;
}
}

Просмотреть файл

@@ -61,25 +61,27 @@ const AddressForm = (props: AddressFormProps) => {
{...props.title} {...props.title}
/> />
</div> </div>
<DropdownInput <div className='third-dropdown-sibling-wrapper'>
onChange={handleCountryChange} <DropdownInput
value={ onChange={handleCountryChange}
props.address.country ? {value: props.address.country, label: props.address.country} : undefined value={
} props.address.country ? {value: props.address.country, label: props.address.country} : undefined
options={COUNTRIES.map((country) => ({ }
value: country.name, options={COUNTRIES.map((country) => ({
label: country.name, value: country.name,
}))} label: country.name,
legend={formatMessage({ }))}
id: 'payment_form.country', legend={formatMessage({
defaultMessage: 'Country', id: 'payment_form.country',
})} defaultMessage: 'Country',
placeholder={formatMessage({ })}
id: 'payment_form.country', placeholder={formatMessage({
defaultMessage: 'Country', id: 'payment_form.country',
})} defaultMessage: 'Country',
name={'billing_dropdown'} })}
/> name={'billing_dropdown'}
/>
</div>
<div className='form-row'> <div className='form-row'>
<Input <Input
name='address' name='address'
@@ -122,7 +124,7 @@ const AddressForm = (props: AddressFormProps) => {
/> />
</div> </div>
<div className='form-row'> <div className='form-row'>
<div className='form-row-third-1 selector'> <div className='form-row-third-1 selector fourth-dropdown-sibling-wrapper'>
<StateSelector <StateSelector
country={props.address.country} country={props.address.country}
state={props.address.state} state={props.address.state}

Просмотреть файл

@@ -12,7 +12,6 @@
.form-row-third-1 { .form-row-third-1 {
.DropdownInput { .DropdownInput {
z-index: 99999;
margin-top: 0; margin-top: 0;
} }
@@ -37,7 +36,6 @@
.DropdownInput { .DropdownInput {
position: relative; position: relative;
z-index: 999999;
height: 36px; height: 36px;
margin-bottom: 24px; margin-bottom: 24px;
font-weight: normal; font-weight: normal;

Просмотреть файл

@@ -251,7 +251,7 @@ export default class PaymentForm extends React.PureComponent<Props, State> {
/> />
</div> </div>
<div className='form-row'> <div className='form-row'>
<div className='form-row-third-1 selector'> <div className='form-row-third-1 selector second-dropdown-sibling-wrapper'>
<StateSelector <StateSelector
country={this.state.country} country={this.state.country}
state={this.state.state} state={this.state.state}

Просмотреть файл

@@ -2,42 +2,8 @@
overflow: hidden; overflow: hidden;
height: 100%; height: 100%;
.shipping-address-section { & &__purchase-body {
display: flex; overflow-y: auto;
align-content: center;
padding: 0 96px;
padding-bottom: 28px;
font-weight: normal;
button.no-style {
padding-left: 0;
background: transparent;
outline: unset;
&:focus {
outline: unset;
}
}
#address-same-than-billing-address {
width: 20px;
height: 20px;
margin-top: auto;
margin-bottom: auto;
}
.Form-checkbox-label {
padding-left: 12px;
cursor: default;
font-family: 'Open Sans', sans-serif;
vertical-align: middle;
}
.billing_address_btn_text {
color: var(--center-channel-color);
font-family: 'Open Sans', sans-serif;
font-weight: normal;
}
} }
>div { >div {

Просмотреть файл

@@ -6,6 +6,7 @@
import React, {ReactNode} from 'react'; import React, {ReactNode} from 'react';
import {FormattedMessage, injectIntl, IntlShape} from 'react-intl'; import {FormattedMessage, injectIntl, IntlShape} from 'react-intl';
import classnames from 'classnames';
import {Stripe, StripeCardElementChangeEvent} from '@stripe/stripe-js'; import {Stripe, StripeCardElementChangeEvent} from '@stripe/stripe-js';
import {loadStripe} from '@stripe/stripe-js/pure'; // https://github.com/stripe/stripe-js#importing-loadstripe-without-side-effects import {loadStripe} from '@stripe/stripe-js/pure'; // https://github.com/stripe/stripe-js#importing-loadstripe-without-side-effects
import {Elements} from '@stripe/react-stripe-js'; import {Elements} from '@stripe/react-stripe-js';
@@ -812,7 +813,7 @@ class PurchaseModal extends React.PureComponent<Props, State> {
} }
return ( return (
<div className={this.state.processing ? 'processing' : ''}> <div className={classnames('PurchaseModal__purchase-body', {processing: this.state.processing})}>
<div className='LHS'> <div className='LHS'>
<h2 className='title'>{title}</h2> <h2 className='title'>{title}</h2>
<UpgradeSvg <UpgradeSvg

Просмотреть файл

@@ -0,0 +1,132 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {useIntl} from 'react-intl';
import classNames from 'classnames';
import {COUNTRIES} from 'utils/countries';
import DropdownInput from 'components/dropdown_input';
import Input from 'components/widgets/inputs/input/input';
import StateSelector from 'components/payment_form/state_selector';
interface Props {
type: 'shipping' | 'billing';
testPrefix?: string;
country: string;
changeCountry: (option: {value: string}) => void;
address: string;
changeAddress: (e: React.ChangeEvent<HTMLInputElement>) => void;
address2: string;
changeAddress2: (e: React.ChangeEvent<HTMLInputElement>) => void;
city: string;
changeCity: (e: React.ChangeEvent<HTMLInputElement>) => void;
state: string;
changeState: (postalCode: string) => void;
postalCode: string;
changePostalCode: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
export default function Address(props: Props) {
const testPrefix = props.testPrefix || 'selfHostedPurchase';
const intl = useIntl();
let countrySelectorId = `${testPrefix}CountrySelector`;
let stateSelectorId = `${testPrefix}StateSelector`;
if (props.type === 'shipping') {
countrySelectorId += '_Shipping';
stateSelectorId += '_Shipping';
}
return (
<>
<div className={classNames({'third-dropdown-sibling-wrapper': props.type === 'shipping'})}>
<DropdownInput
testId={countrySelectorId}
onChange={props.changeCountry}
value={
props.country ? {value: props.country, label: props.country} : undefined
}
options={COUNTRIES.map((country) => ({
value: country.name,
label: country.name,
}))}
legend={intl.formatMessage({
id: 'payment_form.country',
defaultMessage: 'Country',
})}
placeholder={intl.formatMessage({
id: 'payment_form.country',
defaultMessage: 'Country',
})}
name={'billing_dropdown'}
/>
</div>
<div className='form-row'>
<Input
name='address'
type='text'
value={props.address}
onChange={props.changeAddress}
placeholder={intl.formatMessage({
id: 'payment_form.address',
defaultMessage: 'Address',
})}
required={true}
/>
</div>
<div className='form-row'>
<Input
name='address2'
type='text'
value={props.address2}
onChange={props.changeAddress2}
placeholder={intl.formatMessage({
id: 'payment_form.address_2',
defaultMessage: 'Address 2',
})}
/>
</div>
<div className='form-row'>
<Input
name='city'
type='text'
value={props.city}
onChange={props.changeCity}
placeholder={intl.formatMessage({
id: 'payment_form.city',
defaultMessage: 'City',
})}
required={true}
/>
</div>
<div className='form-row'>
<div className={classNames('form-row-third-1', {'second-dropdown-sibling-wrapper': props.type === 'billing', 'fourth-dropdown-sibling-wrapper': props.type === 'shipping'})}>
<StateSelector
testId={stateSelectorId}
country={props.country}
state={props.state}
onChange={props.changeState}
/>
</div>
<div className='form-row-third-2'>
<Input
name='postalCode'
type='text'
value={props.postalCode}
onChange={props.changePostalCode}
placeholder={intl.formatMessage({
id: 'payment_form.zipcode',
defaultMessage: 'Zip/Postal Code',
})}
required={true}
/>
</div>
</div>
</>
);
}

Просмотреть файл

@@ -310,6 +310,15 @@ describe('SelfHostedPurchaseModal :: canSubmit', () => {
state: 'string', state: 'string',
country: 'string', country: 'string',
postalCode: '12345', postalCode: '12345',
shippingSame: true,
shippingAddress: '',
shippingAddress2: '',
shippingCity: '',
shippingState: '',
shippingCountry: '',
shippingPostalCode: '',
cardName: 'string', cardName: 'string',
organization: 'string', organization: 'string',
agreedTerms: true, agreedTerms: true,
@@ -361,6 +370,21 @@ describe('SelfHostedPurchaseModal :: canSubmit', () => {
expect(canSubmit(state, SelfHostedSignupProgress.CREATED_CUSTOMER)).toBe(false); expect(canSubmit(state, SelfHostedSignupProgress.CREATED_CUSTOMER)).toBe(false);
expect(canSubmit(state, SelfHostedSignupProgress.CREATED_INTENT)).toBe(false); expect(canSubmit(state, SelfHostedSignupProgress.CREATED_INTENT)).toBe(false);
}); });
it('if shipping address different and is not filled, can not submit', () => {
const state = makeHappyPathState();
state.shippingSame = false;
expect(canSubmit(state, SelfHostedSignupProgress.START)).toBe(false);
state.shippingAddress = 'more shipping info';
state.shippingAddress2 = 'more shipping info';
state.shippingCity = 'more shipping info';
state.shippingState = 'more shipping info';
state.shippingCountry = 'more shipping info';
state.shippingPostalCode = 'more shipping info';
expect(canSubmit(state, SelfHostedSignupProgress.START)).toBe(true);
});
it('if card number missing and card has not been confirmed, can not submit', () => { it('if card number missing and card has not been confirmed, can not submit', () => {
const state = makeHappyPathState(); const state = makeHappyPathState();
state.cardFilled = false; state.cardFilled = false;

Просмотреть файл

@@ -26,8 +26,6 @@ import {GlobalState} from 'types/store';
import {isModalOpen} from 'selectors/views/modals'; import {isModalOpen} from 'selectors/views/modals';
import {isDevModeEnabled} from 'selectors/general'; import {isDevModeEnabled} from 'selectors/general';
import {COUNTRIES} from 'utils/countries';
import { import {
ModalIdentifiers, ModalIdentifiers,
StatTypes, StatTypes,
@@ -35,8 +33,6 @@ import {
} from 'utils/constants'; } from 'utils/constants';
import CardInput, {CardInputType} from 'components/payment_form/card_input'; import CardInput, {CardInputType} from 'components/payment_form/card_input';
import StateSelector from 'components/payment_form/state_selector';
import DropdownInput from 'components/dropdown_input';
import BackgroundSvg from 'components/common/svg_images_components/background_svg'; import BackgroundSvg from 'components/common/svg_images_components/background_svg';
import UpgradeSvg from 'components/common/svg_images_components/upgrade_svg'; import UpgradeSvg from 'components/common/svg_images_components/upgrade_svg';
@@ -47,6 +43,7 @@ import RootPortal from 'components/root_portal';
import useLoadStripe from 'components/common/hooks/useLoadStripe'; import useLoadStripe from 'components/common/hooks/useLoadStripe';
import useControlSelfHostedPurchaseModal from 'components/common/hooks/useControlSelfHostedPurchaseModal'; import useControlSelfHostedPurchaseModal from 'components/common/hooks/useControlSelfHostedPurchaseModal';
import useFetchStandardAnalytics from 'components/common/hooks/useFetchStandardAnalytics'; import useFetchStandardAnalytics from 'components/common/hooks/useFetchStandardAnalytics';
import ChooseDifferentShipping from 'components/choose_different_shipping';
import {ValueOf} from '@mattermost/types/utilities'; import {ValueOf} from '@mattermost/types/utilities';
import {UserProfile} from '@mattermost/types/users'; import {UserProfile} from '@mattermost/types/users';
@@ -64,6 +61,7 @@ import SuccessPage from './success_page';
import SelfHostedCard from './self_hosted_card'; import SelfHostedCard from './self_hosted_card';
import StripeProvider from './stripe_provider'; import StripeProvider from './stripe_provider';
import Terms from './terms'; import Terms from './terms';
import Address from './address';
import useNoEscape from './useNoEscape'; import useNoEscape from './useNoEscape';
import {SetPrefix, UnionSetActions} from './types'; import {SetPrefix, UnionSetActions} from './types';
@@ -73,12 +71,24 @@ import './self_hosted_purchase_modal.scss';
import {STORAGE_KEY_PURCHASE_IN_PROGRESS} from './constants'; import {STORAGE_KEY_PURCHASE_IN_PROGRESS} from './constants';
export interface State { export interface State {
// billing address
address: string; address: string;
address2: string; address2: string;
city: string; city: string;
state: string; state: string;
country: string; country: string;
postalCode: string; postalCode: string;
// shipping address
shippingSame: boolean;
shippingAddress: string;
shippingAddress2: string;
shippingCity: string;
shippingState: string;
shippingCountry: string;
shippingPostalCode: string;
cardName: string; cardName: string;
organization: string; organization: string;
agreedTerms: boolean; agreedTerms: boolean;
@@ -113,6 +123,15 @@ export function makeInitialState(): State {
state: '', state: '',
country: '', country: '',
postalCode: '', postalCode: '',
shippingSame: true,
shippingAddress: '',
shippingAddress2: '',
shippingCity: '',
shippingState: '',
shippingCountry: '',
shippingPostalCode: '',
cardName: '', cardName: '',
organization: '', organization: '',
agreedTerms: false, agreedTerms: false,
@@ -170,8 +189,18 @@ const simpleSetters: Array<Extract<keyof State, string>> = [
'address2', 'address2',
'city', 'city',
'country', 'country',
'postalCode',
'state', 'state',
'postalCode',
// shipping address
'shippingSame',
'shippingAddress',
'shippingAddress2',
'shippingCity',
'shippingState',
'shippingCountry',
'shippingPostalCode',
'agreedTerms', 'agreedTerms',
'cardFilled', 'cardFilled',
'cardName', 'cardName',
@@ -220,7 +249,7 @@ export function canSubmit(state: State, progress: ValueOf<typeof SelfHostedSignu
return false; return false;
} }
const validAddress = Boolean( let validAddress = Boolean(
state.organization && state.organization &&
state.address && state.address &&
state.city && state.city &&
@@ -228,6 +257,16 @@ export function canSubmit(state: State, progress: ValueOf<typeof SelfHostedSignu
state.postalCode && state.postalCode &&
state.country, state.country,
); );
if (!state.shippingSame) {
validAddress = validAddress && Boolean(
state.shippingAddress &&
state.shippingCity &&
state.shippingState &&
state.shippingPostalCode &&
state.shippingCountry,
);
}
const validCard = Boolean( const validCard = Boolean(
state.cardName && state.cardName &&
state.cardFilled, state.cardFilled,
@@ -366,16 +405,25 @@ export default function SelfHostedPurchaseModal(props: Props) {
try { try {
const [firstName, lastName] = inferNames(user, state.cardName); const [firstName, lastName] = inferNames(user, state.cardName);
const billingAddress = {
city: state.city,
country: state.country,
line1: state.address,
line2: state.address2,
postal_code: state.postalCode,
state: state.state,
};
signupCustomerResult = await Client4.createCustomerSelfHostedSignup({ signupCustomerResult = await Client4.createCustomerSelfHostedSignup({
first_name: firstName, first_name: firstName,
last_name: lastName, last_name: lastName,
billing_address: { billing_address: billingAddress,
city: state.city, shipping_address: state.shippingSame ? billingAddress : {
country: state.country, city: state.shippingCity,
line1: state.address, country: state.shippingCountry,
line2: state.address2, line1: state.shippingAddress,
postal_code: state.postalCode, line2: state.shippingAddress2,
state: state.state, postal_code: state.shippingPostalCode,
state: state.shippingState,
}, },
organization: state.organization, organization: state.organization,
}); });
@@ -586,99 +634,76 @@ export default function SelfHostedPurchaseModal(props: Props) {
defaultMessage='Billing address' defaultMessage='Billing address'
/> />
</div> </div>
<DropdownInput <Address
testId='selfHostedPurchaseCountrySelector' type='billing'
onChange={(option: {value: string}) => { country={state.country}
changeCountry={(option) => {
dispatch({type: 'set_country', data: option.value}); dispatch({type: 'set_country', data: option.value});
}} }}
value={ address={state.address}
state.country ? {value: state.country, label: state.country} : undefined changeAddress={(e) => {
} dispatch({type: 'set_address', data: e.target.value});
options={COUNTRIES.map((country) => ({ }}
value: country.name, address2={state.address2}
label: country.name, changeAddress2={(e) => {
}))} dispatch({type: 'set_address2', data: e.target.value});
legend={intl.formatMessage({ }}
id: 'payment_form.country', city={state.city}
defaultMessage: 'Country', changeCity={(e) => {
})} dispatch({type: 'set_city', data: e.target.value});
placeholder={intl.formatMessage({ }}
id: 'payment_form.country', state={state.state}
defaultMessage: 'Country', changeState={(state: string) => {
})} dispatch({type: 'set_state', data: state});
name={'billing_dropdown'} }}
postalCode={state.postalCode}
changePostalCode={(e) => {
dispatch({type: 'set_postalCode', data: e.target.value});
}}
/> />
<div className='form-row'> <ChooseDifferentShipping
<Input shippingIsSame={state.shippingSame}
name='address' setShippingIsSame={(val: boolean) => {
type='text' dispatch({type: 'set_shippingSame', data: val});
value={state.address} }}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { />
dispatch({type: 'set_address', data: e.target.value}); {!state.shippingSame && (
}} <>
placeholder={intl.formatMessage({ <div className='section-title'>
id: 'payment_form.address', <FormattedMessage
defaultMessage: 'Address', id='payment_form.shipping_address'
})} defaultMessage='Shipping Address'
required={true} />
/> </div>
</div> <Address
<div className='form-row'> type='shipping'
<Input country={state.shippingCountry}
name='address2' changeCountry={(option) => {
type='text' dispatch({type: 'set_shippingCountry', data: option.value});
value={state.address2} }}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { address={state.shippingAddress}
dispatch({type: 'set_address2', data: e.target.value}); changeAddress={(e) => {
}} dispatch({type: 'set_shippingAddress', data: e.target.value});
placeholder={intl.formatMessage({ }}
id: 'payment_form.address_2', address2={state.shippingAddress2}
defaultMessage: 'Address 2', changeAddress2={(e) => {
})} dispatch({type: 'set_shippingAddress2', data: e.target.value});
/> }}
</div> city={state.shippingCity}
<div className='form-row'> changeCity={(e) => {
<Input dispatch({type: 'set_shippingCity', data: e.target.value});
name='city' }}
type='text' state={state.shippingState}
value={state.city} changeState={(state: string) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { dispatch({type: 'set_shippingState', data: state});
dispatch({type: 'set_city', data: e.target.value}); }}
}} postalCode={state.shippingPostalCode}
placeholder={intl.formatMessage({ changePostalCode={(e) => {
id: 'payment_form.city', dispatch({type: 'set_shippingPostalCode', data: e.target.value});
defaultMessage: 'City',
})}
required={true}
/>
</div>
<div className='form-row'>
<div className='form-row-third-1'>
<StateSelector
testId='selfHostedPurchaseStateSelector'
country={state.country}
state={state.state}
onChange={(state: string) => {
dispatch({type: 'set_state', data: state});
}} }}
/> />
</div> </>
<div className='form-row-third-2'> )}
<Input
name='postalCode'
type='text'
value={state.postalCode}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
dispatch({type: 'set_postalCode', data: e.target.value});
}}
placeholder={intl.formatMessage({
id: 'payment_form.zipcode',
defaultMessage: 'Zip/Postal Code',
})}
required={true}
/>
</div>
</div>
<Terms <Terms
agreed={state.agreedTerms} agreed={state.agreedTerms}
setAgreed={(data: boolean) => { setAgreed={(data: boolean) => {

Просмотреть файл

@@ -4,19 +4,20 @@
.form-view { .form-view {
display: flex; display: flex;
overflow: hidden;
width: 100%; width: 100%;
height: 100%; height: 100%;
flex-direction: row; flex-direction: row;
flex-grow: 1; flex-grow: 1;
flex-wrap: wrap; flex-wrap: wrap;
align-content: top; align-items: flex-start;
justify-content: center; justify-content: center;
padding: 77px 107px; padding: 77px 107px;
color: var(--center-channel-color); color: var(--center-channel-color);
font-family: "Open Sans"; font-family: "Open Sans";
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
overflow-x: hidden;
overflow-y: auto;
.title { .title {
font-size: 22px; font-size: 22px;
@@ -39,14 +40,12 @@
margin-right: 16px; margin-right: 16px;
.DropdownInput { .DropdownInput {
z-index: 99999;
margin-top: 0; margin-top: 0;
} }
} }
.DropdownInput { .DropdownInput {
position: relative; position: relative;
z-index: 999999;
height: 36px; height: 36px;
margin-bottom: 24px; margin-bottom: 24px;
@@ -517,6 +516,9 @@
} }
input[type=checkbox] { input[type=checkbox] {
width: 17px;
height: 17px;
flex-shrink: 0;
margin-right: 12px; margin-right: 12px;
} }

Просмотреть файл

@@ -4378,6 +4378,7 @@
"payment_form.no_billing_address": "No billing address added", "payment_form.no_billing_address": "No billing address added",
"payment_form.no_credit_card": "No credit card added", "payment_form.no_credit_card": "No credit card added",
"payment_form.saved_payment_method": "Saved Payment Method", "payment_form.saved_payment_method": "Saved Payment Method",
"payment_form.shipping_address": "Shipping Address",
"payment_form.zipcode": "Zip/Postal Code", "payment_form.zipcode": "Zip/Postal Code",
"payment.card_number": "Card Number", "payment.card_number": "Card Number",
"payment.field_required": "This field is required", "payment.field_required": "This field is required",

Просмотреть файл

@@ -18,6 +18,7 @@ export interface SelfHostedSignupForm {
first_name: string; first_name: string;
last_name: string; last_name: string;
billing_address: Address; billing_address: Address;
shipping_address: Address;
organization: string; organization: string;
} }