mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
fix(Setup): fix organization setup.
This commit is contained in:
@@ -63,7 +63,6 @@
|
|||||||
"postcss-preset-env": "6.7.0",
|
"postcss-preset-env": "6.7.0",
|
||||||
"postcss-safe-parser": "4.0.1",
|
"postcss-safe-parser": "4.0.1",
|
||||||
"react": "^16.12.0",
|
"react": "^16.12.0",
|
||||||
"react-albus": "^2.0.0",
|
|
||||||
"react-app-polyfill": "^1.0.6",
|
"react-app-polyfill": "^1.0.6",
|
||||||
"react-body-classname": "^1.3.1",
|
"react-body-classname": "^1.3.1",
|
||||||
"react-content-loader": "^6.0.1",
|
"react-content-loader": "^6.0.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{ name: 'English', value: 'EN' },
|
{ name: 'English', value: 'en' },
|
||||||
{ name: 'Arabic', value: 'AR' },
|
{ name: 'Arabic', value: 'ar' },
|
||||||
];
|
];
|
||||||
@@ -11,7 +11,7 @@ export default function BigcapitalLoading({ className }) {
|
|||||||
return (
|
return (
|
||||||
<div className={classNames('bigcapital-loading', className)}>
|
<div className={classNames('bigcapital-loading', className)}>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<Icon icon="bigcapital" height={37} width={214} />
|
<Icon icon="bigcapital" height={37} width={228} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,18 +4,17 @@ import { Formik } from 'formik';
|
|||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import Toaster from 'components/AppToaster';
|
||||||
|
|
||||||
import 'style/pages/Setup/PaymentViaVoucherDialog.scss';
|
import 'style/pages/Setup/PaymentViaVoucherDialog.scss';
|
||||||
|
|
||||||
|
import { usePaymentByVoucher } from 'hooks/query';
|
||||||
import { DialogContent } from 'components';
|
import { DialogContent } from 'components';
|
||||||
import PaymentViaLicenseForm from './PaymentViaVoucherForm';
|
import PaymentViaLicenseForm from './PaymentViaVoucherForm';
|
||||||
|
|
||||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||||
import withBillingActions from 'containers/Subscriptions/withBillingActions';
|
|
||||||
import withSubscriptionsActions from 'containers/Subscriptions/withSubscriptionsActions';
|
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
import { Intent } from '@blueprintjs/core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payment via license dialog content.
|
* Payment via license dialog content.
|
||||||
@@ -26,30 +25,43 @@ function PaymentViaLicenseDialogContent({
|
|||||||
|
|
||||||
// #withDialog
|
// #withDialog
|
||||||
closeDialog,
|
closeDialog,
|
||||||
|
|
||||||
// #withBillingActions
|
|
||||||
requestSubmitBilling,
|
|
||||||
|
|
||||||
// #withSubscriptionsActions
|
|
||||||
requestFetchSubscriptions,
|
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
|
// Payment via voucher
|
||||||
|
const {
|
||||||
|
mutateAsync: paymentViaVoucherMutate,
|
||||||
|
} = usePaymentByVoucher();
|
||||||
|
|
||||||
// Handle submit.
|
// Handle submit.
|
||||||
const handleSubmit = (values, { setSubmitting }) => {
|
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
|
|
||||||
requestSubmitBilling({ ...values, ...subscriptionForm })
|
paymentViaVoucherMutate({ ...values })
|
||||||
.then(() => {
|
|
||||||
return requestFetchSubscriptions();
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
Toaster.show({
|
||||||
|
message: 'Payment has been done successfully.',
|
||||||
|
intent: Intent.SUCCESS,
|
||||||
|
});
|
||||||
return closeDialog('payment-via-voucher');
|
return closeDialog('payment-via-voucher');
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
history.push('initializing');
|
history.push('initializing');
|
||||||
})
|
})
|
||||||
|
.catch(
|
||||||
|
({
|
||||||
|
response: {
|
||||||
|
data: { errors },
|
||||||
|
},
|
||||||
|
}) => {
|
||||||
|
if (errors.find((e) => e.type === 'LICENSE.CODE.IS.INVALID')) {
|
||||||
|
setErrors({
|
||||||
|
license_code: 'The license code is not valid, please try agin.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
.finally((errors) => {
|
.finally((errors) => {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
});
|
});
|
||||||
@@ -57,17 +69,18 @@ function PaymentViaLicenseDialogContent({
|
|||||||
|
|
||||||
// Initial values.
|
// Initial values.
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
license_number: '',
|
license_code: '',
|
||||||
plan_slug: '',
|
plan_slug: '',
|
||||||
period: '',
|
period: '',
|
||||||
|
...subscriptionForm,
|
||||||
};
|
};
|
||||||
// Validation schema.
|
// Validation schema.
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
license_number: Yup.string()
|
license_code: Yup.string()
|
||||||
.required()
|
.required()
|
||||||
.min(10)
|
.min(10)
|
||||||
.max(10)
|
.max(10)
|
||||||
.label(formatMessage({ id: 'license_number' })),
|
.label(formatMessage({ id: 'license_code' })),
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -82,8 +95,4 @@ function PaymentViaLicenseDialogContent({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(withDialogActions)(PaymentViaLicenseDialogContent);
|
||||||
withDialogActions,
|
|
||||||
withBillingActions,
|
|
||||||
withSubscriptionsActions,
|
|
||||||
)(PaymentViaLicenseDialogContent);
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button, FormGroup, InputGroup, Intent } from '@blueprintjs/core';
|
import { Button, FormGroup, InputGroup, Intent } from '@blueprintjs/core';
|
||||||
import { Form, FastField, ErrorMessage } from 'formik';
|
import { Form, FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import { compose } from 'redux';
|
import { compose } from 'redux';
|
||||||
|
|
||||||
@@ -15,12 +15,12 @@ import withDialogActions from 'containers/Dialog/withDialogActions';
|
|||||||
* Payment via license form.
|
* Payment via license form.
|
||||||
*/
|
*/
|
||||||
function PaymentViaLicenseForm({
|
function PaymentViaLicenseForm({
|
||||||
// #ownProps
|
|
||||||
isSubmitting,
|
|
||||||
|
|
||||||
// #withDialogActions
|
// #withDialogActions
|
||||||
closeDialog,
|
closeDialog,
|
||||||
}) {
|
}) {
|
||||||
|
// Formik context.
|
||||||
|
const { isSubmitting } = useFormikContext();
|
||||||
|
|
||||||
const licenseNumberRef = useAutofocus();
|
const licenseNumberRef = useAutofocus();
|
||||||
|
|
||||||
// Handle close button click.
|
// Handle close button click.
|
||||||
@@ -33,15 +33,17 @@ function PaymentViaLicenseForm({
|
|||||||
<div className={CLASSES.DIALOG_BODY}>
|
<div className={CLASSES.DIALOG_BODY}>
|
||||||
<p>Please enter your preferred payment method below.</p>
|
<p>Please enter your preferred payment method below.</p>
|
||||||
|
|
||||||
<FastField name="license_number">
|
<FastField name="license_code">
|
||||||
{({ field, meta: { error, touched } }) => (
|
{({ field, meta: { error, touched } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'voucher_number'} />}
|
label={<T id={'voucher_number'} />}
|
||||||
intent={inputIntent({ error, touched })}
|
intent={inputIntent({ error, touched })}
|
||||||
helperText={<ErrorMessage name="voucher_number" />}
|
helperText={<ErrorMessage name="license_code" />}
|
||||||
className={'form-group--voucher_number'}
|
className={'form-group--voucher_number'}
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
|
large={true}
|
||||||
|
intent={inputIntent({ error, touched })}
|
||||||
{...field}
|
{...field}
|
||||||
inputRef={(ref) => (licenseNumberRef.current = ref)}
|
inputRef={(ref) => (licenseNumberRef.current = ref)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -7,16 +7,14 @@ import withDialogRedux from 'components/DialogReduxConnect';
|
|||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
// Lazy loading the content.
|
// Lazy loading the content.
|
||||||
const PaymentViaLicenseDialogContent = lazy(() => import('./PaymentViaVoucherDialogContent'));
|
const PaymentViaLicenseDialogContent = lazy(() =>
|
||||||
|
import('./PaymentViaVoucherDialogContent'),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payment via license dialog.
|
* Payment via license dialog.
|
||||||
*/
|
*/
|
||||||
function PaymentViaLicenseDialog({
|
function PaymentViaLicenseDialog({ dialogName, payload, isOpen }) {
|
||||||
dialogName,
|
|
||||||
payload,
|
|
||||||
isOpen
|
|
||||||
}) {
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
name={dialogName}
|
name={dialogName}
|
||||||
@@ -33,9 +31,7 @@ function PaymentViaLicenseDialog({
|
|||||||
/>
|
/>
|
||||||
</DialogSuspense>
|
</DialogSuspense>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(withDialogRedux())(PaymentViaLicenseDialog);
|
||||||
withDialogRedux(),
|
|
||||||
)(PaymentViaLicenseDialog);
|
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchOrganizations,
|
|
||||||
buildTenant,
|
|
||||||
seedTenant,
|
|
||||||
setOrganizationSetupCompleted,
|
setOrganizationSetupCompleted,
|
||||||
} from 'store/organizations/organizations.actions';
|
} from 'store/organizations/organizations.actions';
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
requestOrganizationBuild: () => dispatch(buildTenant()),
|
setOrganizationSetupCompleted: (congrats) =>
|
||||||
requestOrganizationSeed: () => dispatch(seedTenant()),
|
dispatch(setOrganizationSetupCompleted(congrats)),
|
||||||
requestAllOrganizations: () => dispatch(fetchOrganizations()),
|
|
||||||
|
|
||||||
setOrganizationSetupCompleted: (congrats) => dispatch(setOrganizationSetupCompleted(congrats)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps);
|
export default connect(null, mapDispatchToProps);
|
||||||
@@ -1,53 +1,49 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useQuery } from 'react-query';
|
|
||||||
import { withWizard } from 'react-albus'
|
|
||||||
import { ProgressBar, Intent } from '@blueprintjs/core';
|
import { ProgressBar, Intent } from '@blueprintjs/core';
|
||||||
|
import { useBuildTenant } from 'hooks/query';
|
||||||
|
|
||||||
import 'style/pages/Setup/Initializing.scss';
|
import 'style/pages/Setup/Initializing.scss';
|
||||||
|
|
||||||
import withOrganizationActions from 'containers/Organization/withOrganizationActions';
|
|
||||||
|
|
||||||
import { compose } from 'utils';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup initializing step form.
|
* Setup initializing step form.
|
||||||
*/
|
*/
|
||||||
function SetupInitializingForm({
|
export default function SetupInitializingForm() {
|
||||||
|
const {
|
||||||
// #withOrganizationActions
|
mutateAsync: buildTenantMutate,
|
||||||
requestOrganizationBuild,
|
isLoading,
|
||||||
|
isError,
|
||||||
wizard: { next },
|
} = useBuildTenant();
|
||||||
}) {
|
|
||||||
const { isSuccess } = useQuery(
|
|
||||||
['build-tenant'], () => requestOrganizationBuild(),
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSuccess) {
|
buildTenantMutate();
|
||||||
next();
|
}, [buildTenantMutate]);
|
||||||
}
|
|
||||||
}, [isSuccess, next]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="setup-initializing-form">
|
<div class="setup-initializing-form">
|
||||||
<ProgressBar intent={Intent.PRIMARY} value={null} />
|
{isLoading && <ProgressBar intent={Intent.PRIMARY} value={null} />}
|
||||||
|
|
||||||
<div className={'setup-initializing-form__title'}>
|
<div className={'setup-initializing-form__title'}>
|
||||||
<h1>
|
{isLoading ? (
|
||||||
{/* You organization is initializin... */}
|
<>
|
||||||
It's time to make your accounting really simple!
|
<h1>It's time to make your accounting really simple!</h1>
|
||||||
</h1>
|
|
||||||
<p className={'paragraph'}>
|
<p className={'paragraph'}>
|
||||||
while we set up your account, please remember to verify your account by
|
while we set up your account, please remember to verify your
|
||||||
clicking on the link we sent to yout registered email address
|
account by clicking on the link we sent to yout registered email
|
||||||
|
address
|
||||||
</p>
|
</p>
|
||||||
|
</>
|
||||||
|
) : isError ? (
|
||||||
|
<>
|
||||||
|
<h1>Something went wrong!</h1>
|
||||||
|
<p class="paragraph">Please refresh the page</p>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<h1>Waiting to redirect</h1>
|
||||||
|
<p class="paragraph">Refresh the page if redirect not worked.</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withOrganizationActions,
|
|
||||||
withWizard,
|
|
||||||
)(SetupInitializingForm);
|
|
||||||
@@ -14,7 +14,7 @@ import classNames from 'classnames';
|
|||||||
import { TimezonePicker } from '@blueprintjs/timezone';
|
import { TimezonePicker } from '@blueprintjs/timezone';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
|
||||||
import { Col, Row, ListSelect } from 'components';
|
import { FieldRequiredHint, Col, Row, ListSelect } from 'components';
|
||||||
import {
|
import {
|
||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
@@ -38,9 +38,10 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{/* ---------- Organization name ---------- */}
|
{/* ---------- Organization name ---------- */}
|
||||||
<FastField name={'name'}>
|
<FastField name={'organization_name'}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
{({ form, field, meta: { error, touched } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
labelInfo={<FieldRequiredHint />}
|
||||||
label={<T id={'legal_organization_name'} />}
|
label={<T id={'legal_organization_name'} />}
|
||||||
className={'form-group--name'}
|
className={'form-group--name'}
|
||||||
intent={inputIntent({ error, touched })}
|
intent={inputIntent({ error, touched })}
|
||||||
@@ -55,6 +56,7 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
<FastField name={'financialDateStart'}>
|
<FastField name={'financialDateStart'}>
|
||||||
{({ form: { setFieldValue }, field: { value }, meta: { error, touched } }) => (
|
{({ form: { setFieldValue }, field: { value }, meta: { error, touched } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
labelInfo={<FieldRequiredHint />}
|
||||||
label={<T id={'financial_starting_date'} />}
|
label={<T id={'financial_starting_date'} />}
|
||||||
intent={inputIntent({ error, touched })}
|
intent={inputIntent({ error, touched })}
|
||||||
helperText={<ErrorMessage name="financialDateStart" />}
|
helperText={<ErrorMessage name="financialDateStart" />}
|
||||||
@@ -82,6 +84,7 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
meta: { error, touched },
|
meta: { error, touched },
|
||||||
}) => (
|
}) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
labelInfo={<FieldRequiredHint />}
|
||||||
label={<T id={'base_currency'} />}
|
label={<T id={'base_currency'} />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'form-group--base-currency',
|
'form-group--base-currency',
|
||||||
@@ -137,6 +140,7 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
selectedItemProp={'value'}
|
selectedItemProp={'value'}
|
||||||
defaultText={<T id={'select_language'} />}
|
defaultText={<T id={'select_language'} />}
|
||||||
popoverProps={{ minimal: true }}
|
popoverProps={{ minimal: true }}
|
||||||
|
filterable={false}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
@@ -147,6 +151,7 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
<FastField name={'fiscalYear'}>
|
<FastField name={'fiscalYear'}>
|
||||||
{({ form: { setFieldValue }, field: { value }, meta: { error, touched } }) => (
|
{({ form: { setFieldValue }, field: { value }, meta: { error, touched } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
labelInfo={<FieldRequiredHint />}
|
||||||
label={<T id={'fiscal_year'} />}
|
label={<T id={'fiscal_year'} />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'form-group--fiscal_year',
|
'form-group--fiscal_year',
|
||||||
@@ -167,6 +172,7 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
onItemSelect={(item) => {
|
onItemSelect={(item) => {
|
||||||
setFieldValue('fiscalYear', item.value)
|
setFieldValue('fiscalYear', item.value)
|
||||||
}}
|
}}
|
||||||
|
filterable={false}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
@@ -180,6 +186,7 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
meta: { error, touched },
|
meta: { error, touched },
|
||||||
}) => (
|
}) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
labelInfo={<FieldRequiredHint />}
|
||||||
label={<T id={'time_zone'} />}
|
label={<T id={'time_zone'} />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'form-group--time-zone',
|
'form-group--time-zone',
|
||||||
|
|||||||
@@ -3,49 +3,33 @@ import * as Yup from 'yup';
|
|||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
import { snakeCase } from 'lodash';
|
|
||||||
|
|
||||||
import { withWizard } from 'react-albus';
|
|
||||||
import { useQuery } from 'react-query';
|
|
||||||
|
|
||||||
import 'style/pages/Setup/Organization.scss';
|
import 'style/pages/Setup/Organization.scss';
|
||||||
|
|
||||||
import SetupOrganizationForm from './SetupOrganizationForm';
|
import SetupOrganizationForm from './SetupOrganizationForm';
|
||||||
|
|
||||||
|
import { useOrganizationSetup } from 'hooks/query';
|
||||||
import withSettingsActions from 'containers/Settings/withSettingsActions';
|
import withSettingsActions from 'containers/Settings/withSettingsActions';
|
||||||
import withSettings from 'containers/Settings/withSettings';
|
|
||||||
import withOrganizationActions from 'containers/Organization/withOrganizationActions';
|
import withOrganizationActions from 'containers/Organization/withOrganizationActions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
compose,
|
compose,
|
||||||
transformToForm,
|
transfromToSnakeCase,
|
||||||
optionsMapToArray,
|
|
||||||
} from 'utils';
|
} from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup organization form.
|
* Setup organization form.
|
||||||
*/
|
*/
|
||||||
function SetupOrganizationPage({
|
function SetupOrganizationPage({
|
||||||
// #withSettingsActions
|
|
||||||
requestSubmitOptions,
|
|
||||||
requestFetchOptions,
|
|
||||||
|
|
||||||
// #withOrganizationActions
|
|
||||||
requestOrganizationSeed,
|
|
||||||
|
|
||||||
// #withSettings
|
|
||||||
organizationSettings,
|
|
||||||
|
|
||||||
wizard,
|
wizard,
|
||||||
setOrganizationSetupCompleted,
|
setOrganizationSetupCompleted,
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
const { mutateAsync: organizationSetupMutate } = useOrganizationSetup();
|
||||||
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
|
|
||||||
|
|
||||||
// Validation schema.
|
// Validation schema.
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
name: Yup.string()
|
organization_name: Yup.string()
|
||||||
.required()
|
.required()
|
||||||
.label(formatMessage({ id: 'organization_name_' })),
|
.label(formatMessage({ id: 'organization_name_' })),
|
||||||
financialDateStart: Yup.date()
|
financialDateStart: Yup.date()
|
||||||
@@ -67,35 +51,21 @@ function SetupOrganizationPage({
|
|||||||
|
|
||||||
// Initial values.
|
// Initial values.
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
name: '',
|
organization_name: '',
|
||||||
financialDateStart: moment(new Date()).format('YYYY-MM-DD'),
|
financialDateStart: moment(new Date()).format('YYYY-MM-DD'),
|
||||||
baseCurrency: '',
|
baseCurrency: '',
|
||||||
language: '',
|
language: 'en',
|
||||||
fiscalYear: '',
|
fiscalYear: '',
|
||||||
timeZone: '',
|
timeZone: '',
|
||||||
...organizationSettings,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
...defaultValues,
|
...defaultValues,
|
||||||
|
|
||||||
/**
|
|
||||||
* We only care about the fields in the form. Previously unfilled optional
|
|
||||||
* values such as `notes` come back from the API as null, so remove those
|
|
||||||
* as well.
|
|
||||||
*/
|
|
||||||
...transformToForm(organizationSettings, defaultValues),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle the form submit.
|
// Handle the form submit.
|
||||||
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
||||||
const options = optionsMapToArray(values).map((option) => {
|
organizationSetupMutate({ ...transfromToSnakeCase(values) })
|
||||||
return { ...option, key: snakeCase(option.key), group: 'organization' };
|
|
||||||
});
|
|
||||||
requestSubmitOptions({ options })
|
|
||||||
.then(() => {
|
|
||||||
return requestOrganizationSeed();
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return setOrganizationSetupCompleted(true);
|
return setOrganizationSetupCompleted(true);
|
||||||
})
|
})
|
||||||
@@ -132,8 +102,4 @@ function SetupOrganizationPage({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withSettingsActions,
|
withSettingsActions,
|
||||||
withOrganizationActions,
|
withOrganizationActions,
|
||||||
withWizard,
|
|
||||||
withSettings(({ organizationSettings }) => ({
|
|
||||||
organizationSettings,
|
|
||||||
})),
|
|
||||||
)(SetupOrganizationPage);
|
)(SetupOrganizationPage);
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Wizard } from 'react-albus';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
|
||||||
|
|
||||||
import withSubscriptions from 'containers/Subscriptions/withSubscriptions';
|
|
||||||
|
|
||||||
import SetupDialogs from './SetupDialogs';
|
import SetupDialogs from './SetupDialogs';
|
||||||
import SetupWizardContent from './SetupWizardContent';
|
import SetupWizardContent from './SetupWizardContent';
|
||||||
|
|
||||||
|
import withSubscriptions from 'containers/Subscriptions/withSubscriptions';
|
||||||
import withOrganization from 'containers/Organization/withOrganization';
|
import withOrganization from 'containers/Organization/withOrganization';
|
||||||
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
||||||
import withSetupWizard from '../../store/organizations/withSetupWizard';
|
import withSetupWizard from '../../store/organizations/withSetupWizard';
|
||||||
@@ -24,37 +20,17 @@ function SetupRightSection({
|
|||||||
isOrganizationSetupCompleted,
|
isOrganizationSetupCompleted,
|
||||||
|
|
||||||
// #withSetupWizard
|
// #withSetupWizard
|
||||||
isCongratsStep,
|
setupStepId,
|
||||||
isSubscriptionStep,
|
setupStepIndex,
|
||||||
isInitializingStep,
|
|
||||||
isOrganizationStep,
|
|
||||||
|
|
||||||
// #withSubscriptions
|
// #withSubscriptions
|
||||||
isSubscriptionActive,
|
isSubscriptionActive,
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
|
||||||
|
|
||||||
const handleSkip = ({ step, push }) => {
|
|
||||||
const scenarios = [
|
|
||||||
{ condition: isCongratsStep, redirectTo: 'congrats' },
|
|
||||||
{ condition: isSubscriptionStep, redirectTo: 'subscription' },
|
|
||||||
{ condition: isInitializingStep, redirectTo: 'initializing' },
|
|
||||||
{ condition: isOrganizationStep, redirectTo: 'organization' },
|
|
||||||
];
|
|
||||||
const scenario = scenarios.find((scenario) => scenario.condition);
|
|
||||||
|
|
||||||
if (scenario) {
|
|
||||||
push(scenario.redirectTo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={'setup-page__right-section'}>
|
<section className={'setup-page__right-section'}>
|
||||||
<Wizard
|
<SetupWizardContent
|
||||||
onNext={handleSkip}
|
setupStepId={setupStepId}
|
||||||
basename={'/setup'}
|
setupStepIndex={setupStepIndex}
|
||||||
history={history}
|
|
||||||
render={SetupWizardContent}
|
|
||||||
/>
|
/>
|
||||||
<SetupDialogs />
|
<SetupDialogs />
|
||||||
</section>
|
</section>
|
||||||
@@ -84,17 +60,8 @@ export default compose(
|
|||||||
}),
|
}),
|
||||||
'main',
|
'main',
|
||||||
),
|
),
|
||||||
withSetupWizard(
|
withSetupWizard(({ setupStepId, setupStepIndex }) => ({
|
||||||
({
|
setupStepId,
|
||||||
isCongratsStep,
|
setupStepIndex,
|
||||||
isSubscriptionStep,
|
})),
|
||||||
isInitializingStep,
|
|
||||||
isOrganizationStep,
|
|
||||||
}) => ({
|
|
||||||
isCongratsStep,
|
|
||||||
isSubscriptionStep,
|
|
||||||
isInitializingStep,
|
|
||||||
isOrganizationStep,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)(SetupRightSection);
|
)(SetupRightSection);
|
||||||
|
|||||||
8
client/src/containers/Setup/SetupSteps.js
Normal file
8
client/src/containers/Setup/SetupSteps.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function SetupSteps({ step, children }) {
|
||||||
|
const activeStep = React.Children.toArray(children).filter(
|
||||||
|
(child) => child.props.id === step.id,
|
||||||
|
);
|
||||||
|
return activeStep;
|
||||||
|
}
|
||||||
@@ -1,21 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import { withWizard } from 'react-albus';
|
|
||||||
|
|
||||||
import 'style/pages/Setup/Subscription.scss';
|
import 'style/pages/Setup/Subscription.scss';
|
||||||
|
|
||||||
import SetupSubscriptionForm from './SetupSubscriptionForm';
|
import SetupSubscriptionForm from './SetupSubscriptionForm';
|
||||||
import { SubscriptionFormSchema } from './SubscriptionForm.schema';
|
import { SubscriptionFormSchema } from './SubscriptionForm.schema';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscription step of wizard setup.
|
* Subscription step of wizard setup.
|
||||||
*/
|
*/
|
||||||
function SetupSubscription({
|
export default function SetupSubscription() {
|
||||||
// #withWizard
|
|
||||||
wizard,
|
|
||||||
}) {
|
|
||||||
// Initial values.
|
// Initial values.
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
plan_slug: 'free',
|
plan_slug: 'free',
|
||||||
@@ -23,6 +17,7 @@ function SetupSubscription({
|
|||||||
license_code: '',
|
license_code: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle form submit.
|
||||||
const handleSubmit = () => {};
|
const handleSubmit = () => {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -36,7 +31,3 @@ function SetupSubscription({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withWizard,
|
|
||||||
)(SetupSubscription);
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Steps, Step } from 'react-albus';
|
|
||||||
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
|
||||||
|
|
||||||
|
import SetupSteps from './SetupSteps';
|
||||||
import WizardSetupSteps from './WizardSetupSteps';
|
import WizardSetupSteps from './WizardSetupSteps';
|
||||||
|
|
||||||
import SetupSubscription from './SetupSubscription';
|
import SetupSubscription from './SetupSubscription';
|
||||||
@@ -12,37 +11,19 @@ import SetupCongratsPage from './SetupCongratsPage';
|
|||||||
/**
|
/**
|
||||||
* Setup wizard content.
|
* Setup wizard content.
|
||||||
*/
|
*/
|
||||||
export default function SetupWizardContent({
|
export default function SetupWizardContent({ setupStepIndex, setupStepId }) {
|
||||||
step,
|
|
||||||
steps
|
|
||||||
}) {
|
|
||||||
return (
|
return (
|
||||||
<div class="setup-page__content">
|
<div class="setup-page__content">
|
||||||
<WizardSetupSteps currentStep={steps.indexOf(step) + 1} />
|
<WizardSetupSteps currentStep={setupStepIndex} />
|
||||||
|
|
||||||
<TransitionGroup>
|
|
||||||
<CSSTransition key={step.id} timeout={{ enter: 500, exit: 500 }}>
|
|
||||||
<div class="setup-page-form">
|
<div class="setup-page-form">
|
||||||
<Steps key={step.id} step={step}>
|
<SetupSteps step={{ id: setupStepId }}>
|
||||||
<Step id="subscription">
|
<SetupSubscription id="subscription" />
|
||||||
<SetupSubscription />
|
<SetupInitializingForm id={'initializing'} />
|
||||||
</Step>
|
<SetupOrganizationPage id="organization" />
|
||||||
|
<SetupCongratsPage id="congrats" />
|
||||||
<Step id={'initializing'}>
|
</SetupSteps>
|
||||||
<SetupInitializingForm />
|
|
||||||
</Step>
|
|
||||||
|
|
||||||
<Step id="organization">
|
|
||||||
<SetupOrganizationPage />
|
|
||||||
</Step>
|
|
||||||
|
|
||||||
<Step id="congrats">
|
|
||||||
<SetupCongratsPage />
|
|
||||||
</Step>
|
|
||||||
</Steps>
|
|
||||||
</div>
|
</div>
|
||||||
</CSSTransition>
|
|
||||||
</TransitionGroup>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,19 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import { registerWizardSteps } from 'common/registerWizard'
|
import { registerWizardSteps } from 'common/registerWizard';
|
||||||
|
|
||||||
function WizardSetupStep({
|
function WizardSetupStep({ label, isActive = false }) {
|
||||||
label,
|
|
||||||
isActive = false
|
|
||||||
}) {
|
|
||||||
return (
|
return (
|
||||||
<li className={classNames({ 'is-active': isActive })}>
|
<li className={classNames({ 'is-active': isActive })}>
|
||||||
<p className={'wizard-info'}><T id={label} /></p>
|
<p className={'wizard-info'}>
|
||||||
|
<T id={label} />
|
||||||
|
</p>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function WizardSetupSteps({
|
export default function WizardSetupSteps({ currentStep = 1 }) {
|
||||||
currentStep = 1,
|
|
||||||
}) {
|
|
||||||
return (
|
return (
|
||||||
<div className={'setup-page-steps-container'}>
|
<div className={'setup-page-steps-container'}>
|
||||||
<div className={'setup-page-steps'}>
|
<div className={'setup-page-steps'}>
|
||||||
@@ -24,7 +21,7 @@ function WizardSetupSteps({
|
|||||||
{registerWizardSteps.map((step, index) => (
|
{registerWizardSteps.map((step, index) => (
|
||||||
<WizardSetupStep
|
<WizardSetupStep
|
||||||
label={step.label}
|
label={step.label}
|
||||||
isActive={(index + 1) == currentStep}
|
isActive={index + 1 === currentStep}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -32,5 +29,3 @@ function WizardSetupSteps({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WizardSetupSteps;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation, useQueryClient } from 'react-query';
|
import { useMutation, useQueryClient } from 'react-query';
|
||||||
import { useQueryTenant, useRequestQuery } from '../useQueryRequest';
|
import { useRequestQuery } from '../useQueryRequest';
|
||||||
import useApiRequest from '../useRequest';
|
import useApiRequest from '../useRequest';
|
||||||
import t from './types';
|
import t from './types';
|
||||||
|
|
||||||
@@ -24,9 +24,7 @@ export function useAccounts(query, props) {
|
|||||||
[t.ACCOUNTS, query],
|
[t.ACCOUNTS, query],
|
||||||
{ method: 'get', url: 'accounts', params: query },
|
{ method: 'get', url: 'accounts', params: query },
|
||||||
{
|
{
|
||||||
select: (response) => {
|
select: (res) => res.data.accounts,
|
||||||
return response.data.accounts;
|
|
||||||
},
|
|
||||||
defaultData: [],
|
defaultData: [],
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { useEffect } from 'react';
|
|
||||||
import { useMutation } from 'react-query';
|
import { useMutation } from 'react-query';
|
||||||
import useApiRequest from '../useRequest';
|
import useApiRequest from '../useRequest';
|
||||||
import { useAuthActions } from '../state';
|
import { useAuthActions } from '../state';
|
||||||
@@ -10,20 +9,16 @@ export const useAuthLogin = (props) => {
|
|||||||
const { setLogin } = useAuthActions();
|
const { setLogin } = useAuthActions();
|
||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
const states = useMutation(
|
return useMutation(
|
||||||
(values) => apiRequest.post('auth/login', values),
|
(values) => apiRequest.post('auth/login', values),
|
||||||
{
|
{
|
||||||
select: (res) => res.data,
|
select: (res) => res.data,
|
||||||
|
onSuccess: (data) => {
|
||||||
|
setLogin(data.data);
|
||||||
|
},
|
||||||
...props
|
...props
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const { isSuccess, data: response } = states;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isSuccess) { setLogin(response.data); }
|
|
||||||
}, [isSuccess, response, setLogin]);
|
|
||||||
|
|
||||||
return states;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,3 +21,5 @@ export * from './users';
|
|||||||
export * from './invite';
|
export * from './invite';
|
||||||
export * from './exchangeRates';
|
export * from './exchangeRates';
|
||||||
export * from './contacts';
|
export * from './contacts';
|
||||||
|
export * from './subscriptions';
|
||||||
|
export * from './organization';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useMutation } from 'react-query';
|
import { useMutation, useQueryClient } from 'react-query';
|
||||||
|
import { batch } from 'react-redux';
|
||||||
import t from './types';
|
import t from './types';
|
||||||
import useApiRequest from '../useRequest';
|
import useApiRequest from '../useRequest';
|
||||||
import { useRequestQuery } from '../useQueryRequest';
|
import { useRequestQuery } from '../useQueryRequest';
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { useSetOrganizations, useSetSubscriptions } from '../state';
|
import { useSetOrganizations, useSetSubscriptions } from '../state';
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
@@ -33,29 +33,26 @@ export function useCurrentOrganization(props) {
|
|||||||
const setOrganizations = useSetOrganizations();
|
const setOrganizations = useSetOrganizations();
|
||||||
const setSubscriptions = useSetSubscriptions();
|
const setSubscriptions = useSetSubscriptions();
|
||||||
|
|
||||||
const query = useRequestQuery(
|
return useRequestQuery(
|
||||||
[t.ORGANIZATION_CURRENT],
|
[t.ORGANIZATION_CURRENT],
|
||||||
{ method: 'get', url: `organization/current` },
|
{ method: 'get', url: `organization/current` },
|
||||||
{
|
{
|
||||||
select: (res) => res.data.organization,
|
select: (res) => res.data.organization,
|
||||||
defaultData: {},
|
defaultData: {},
|
||||||
...props,
|
onSuccess: (data) => {
|
||||||
},
|
const organization = omit(data, ['subscriptions']);
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
batch(() => {
|
||||||
if (query.isSuccess) {
|
// Sets subscriptions.
|
||||||
const organization = omit(query.data, ['subscriptions']);
|
setSubscriptions(data.subscriptions);
|
||||||
|
|
||||||
// Sets organizations.
|
// Sets organizations.
|
||||||
setOrganizations([organization]);
|
setOrganizations([organization]);
|
||||||
|
});
|
||||||
// Sets subscriptions.
|
},
|
||||||
setSubscriptions(query.data.subscriptions);
|
...props,
|
||||||
}
|
},
|
||||||
}, [query.data, query.isSuccess, setOrganizations, setSubscriptions]);
|
);
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,30 +60,46 @@ export function useCurrentOrganization(props) {
|
|||||||
*/
|
*/
|
||||||
export function useBuildTenant(props) {
|
export function useBuildTenant(props) {
|
||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation(
|
return useMutation((values) => apiRequest.post('organization/build'), {
|
||||||
(values) => apiRequest.post('organization/build'),
|
|
||||||
{
|
|
||||||
onSuccess: (res, values) => {
|
onSuccess: (res, values) => {
|
||||||
|
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
|
||||||
|
queryClient.invalidateQueries(t.ORGANIZATIONS);
|
||||||
},
|
},
|
||||||
...props,
|
...props,
|
||||||
},
|
});
|
||||||
);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seeds the current tenant
|
* Seeds the current tenant
|
||||||
*/
|
*/
|
||||||
export function useSeedTenant() {
|
export function useSeedTenant() {
|
||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation((values) => apiRequest.post('organization/seed'), {
|
||||||
|
onSuccess: (res) => {
|
||||||
|
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
|
||||||
|
queryClient.invalidateQueries(t.ORGANIZATIONS);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Organization setup.
|
||||||
|
*/
|
||||||
|
export function useOrganizationSetup() {
|
||||||
|
const apiRequest = useApiRequest();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
(values) => apiRequest.post('organization/seed'),
|
(values) => apiRequest.post(`setup/organization`, values),
|
||||||
{
|
{
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
|
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
|
||||||
|
queryClient.invalidateQueries(t.ORGANIZATIONS);
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
)
|
);
|
||||||
};
|
}
|
||||||
|
|||||||
44
client/src/hooks/query/subscriptions.js
Normal file
44
client/src/hooks/query/subscriptions.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { useEffect } from "react"
|
||||||
|
import { useMutation, useQueryClient } from "react-query";
|
||||||
|
import { useRequestQuery } from "../useQueryRequest";
|
||||||
|
import useApiRequest from "../useRequest";
|
||||||
|
import { useSetSubscriptions } from '../state/subscriptions';
|
||||||
|
import T from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscription payment via voucher.
|
||||||
|
*/
|
||||||
|
export const usePaymentByVoucher = (props) => {
|
||||||
|
const apiRequest = useApiRequest();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation(
|
||||||
|
(values) => apiRequest.post('subscription/license/payment', values),
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries(T.SUBSCRIPTIONS);
|
||||||
|
queryClient.invalidateQueries(T.ORGANIZATION_CURRENT);
|
||||||
|
queryClient.invalidateQueries(T.ORGANIZATIONS);
|
||||||
|
},
|
||||||
|
...props,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the organization subscriptions.
|
||||||
|
*/
|
||||||
|
export const useOrganizationSubscriptions = (props) => {
|
||||||
|
const setSubscriptions = useSetSubscriptions();
|
||||||
|
|
||||||
|
const state = useRequestQuery(
|
||||||
|
[T.SUBSCRIPTIONS],
|
||||||
|
{ method: 'get', url: 'subscriptions' },
|
||||||
|
{ ...props },
|
||||||
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
if (state.isSuccess) {
|
||||||
|
setSubscriptions(state.data);
|
||||||
|
}
|
||||||
|
}, [state.isSuccess, state.data, setSubscriptions])
|
||||||
|
};
|
||||||
@@ -94,6 +94,10 @@ const ORGANIZATIONS = {
|
|||||||
ORGANIZATION_CURRENT: 'ORGANIZATION_CURRENT',
|
ORGANIZATION_CURRENT: 'ORGANIZATION_CURRENT',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SUBSCRIPTIONS = {
|
||||||
|
SUBSCRIPTIONS: 'SUBSCRIPTIONS',
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...ACCOUNTS,
|
...ACCOUNTS,
|
||||||
...BILLS,
|
...BILLS,
|
||||||
@@ -111,4 +115,5 @@ export default {
|
|||||||
...USERS,
|
...USERS,
|
||||||
...SETTING,
|
...SETTING,
|
||||||
...ORGANIZATIONS,
|
...ORGANIZATIONS,
|
||||||
|
...SUBSCRIPTIONS
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import { createTableStateReducers } from 'store/tableState.reducer';
|
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -12,15 +13,21 @@ const initialState = {
|
|||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:bills';
|
const STORAGE_KEY = 'bigcapital:bills';
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
const CONFIG = {
|
||||||
...createTableStateReducers('BILLS'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default persistReducer(
|
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
},
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('BILLS'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(
|
||||||
|
CONFIG,
|
||||||
reducerInstance,
|
reducerInstance,
|
||||||
);
|
);
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import {
|
import {
|
||||||
createTableStateReducers,
|
createTableStateReducers,
|
||||||
} from 'store/tableState.reducer';
|
} from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -12,17 +13,23 @@ const initialState = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('ESTIMATES'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:estimates';
|
const STORAGE_KEY = 'bigcapital:estimates';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('ESTIMATES'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(
|
||||||
|
CONFIG,
|
||||||
reducerInstance,
|
reducerInstance,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import {
|
import {
|
||||||
createTableStateReducers,
|
createTableStateReducers,
|
||||||
} from 'store/tableState.reducer';
|
} from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -12,17 +13,23 @@ const initialState = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('INVOICES'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:invoices';
|
const STORAGE_KEY = 'bigcapital:invoices';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
},
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('INVOICES'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(
|
||||||
|
CONFIG,
|
||||||
reducerInstance,
|
reducerInstance,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import {
|
import {
|
||||||
createTableStateReducers,
|
createTableStateReducers,
|
||||||
} from 'store/tableState.reducer';
|
} from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -13,17 +14,20 @@ const initialState = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('PAYMENT_MADES'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:paymentMades';
|
const STORAGE_KEY = 'bigcapital:paymentMades';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
|
}
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('PAYMENT_MADES'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
},
|
},
|
||||||
reducerInstance,
|
});
|
||||||
);
|
|
||||||
|
export default persistReducer(CONFIG, reducerInstance);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import {
|
import {
|
||||||
createTableStateReducers,
|
createTableStateReducers,
|
||||||
} from 'store/tableState.reducer';
|
} from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -12,17 +13,23 @@ const initialState = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('PAYMENT_RECEIVES'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:paymentReceives';
|
const STORAGE_KEY = 'bigcapital:paymentReceives';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('PAYMENT_RECEIVES'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(
|
||||||
|
CONFIG,
|
||||||
reducerInstance,
|
reducerInstance,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,25 +1,27 @@
|
|||||||
import { createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import {
|
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||||
createTableStateReducers,
|
import t from 'store/types';
|
||||||
} from 'store/tableState.reducer';
|
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {},
|
tableState: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('ACCOUNTS'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:accounts';
|
const STORAGE_KEY = 'bigcapital:accounts';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
},
|
};
|
||||||
reducerInstance,
|
|
||||||
);
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('ACCOUNTS'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(CONFIG, reducerInstance);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer } from 'redux-persist';
|
||||||
|
import purgeStoredState from 'redux-persist/es/purgeStoredState';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
|
||||||
@@ -14,10 +15,16 @@ const initialState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:authentication';
|
const STORAGE_KEY = 'bigcapital:authentication';
|
||||||
|
const CONFIG = {
|
||||||
|
key: STORAGE_KEY,
|
||||||
|
blacklist: ['errors'],
|
||||||
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
const reducerInstance = createReducer(initialState, {
|
||||||
[t.LOGIN_SUCCESS]: (state, action) => {
|
[t.LOGIN_SUCCESS]: (state, action) => {
|
||||||
const { token, user, tenant } = action.payload;
|
const { token, user, tenant } = action.payload;
|
||||||
|
|
||||||
state.token = token;
|
state.token = token;
|
||||||
state.user = user;
|
state.user = user;
|
||||||
state.organization = tenant.organization_id;
|
state.organization = tenant.organization_id;
|
||||||
@@ -32,14 +39,14 @@ const reducerInstance = createReducer(initialState, {
|
|||||||
[t.LOGIN_CLEAR_ERRORS]: (state) => {
|
[t.LOGIN_CLEAR_ERRORS]: (state) => {
|
||||||
state.errors = [];
|
state.errors = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default persistReducer(
|
export default persistReducer(
|
||||||
{
|
CONFIG,
|
||||||
key: STORAGE_KEY,
|
|
||||||
blacklist: ['errors'],
|
|
||||||
storage,
|
|
||||||
},
|
|
||||||
reducerInstance,
|
reducerInstance,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
@@ -20,6 +20,12 @@ const initialState = {
|
|||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:dashboard';
|
const STORAGE_KEY = 'bigcapital:dashboard';
|
||||||
|
|
||||||
|
const CONFIG = {
|
||||||
|
key: STORAGE_KEY,
|
||||||
|
whitelist: ['sidebarExpended', 'previousSidebarExpended'],
|
||||||
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
const reducerInstance = createReducer(initialState, {
|
||||||
[t.CHANGE_DASHBOARD_PAGE_TITLE]: (state, action) => {
|
[t.CHANGE_DASHBOARD_PAGE_TITLE]: (state, action) => {
|
||||||
state.pageTitle = action.pageTitle;
|
state.pageTitle = action.pageTitle;
|
||||||
@@ -115,19 +121,13 @@ const reducerInstance = createReducer(initialState, {
|
|||||||
const { backLink } = action.payload;
|
const { backLink } = action.payload;
|
||||||
state.backLink = backLink;
|
state.backLink = backLink;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default persistReducer(
|
export default persistReducer(CONFIG, reducerInstance);
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
|
||||||
whitelist: [
|
|
||||||
'sidebarExpended',
|
|
||||||
'previousSidebarExpended',
|
|
||||||
],
|
|
||||||
storage,
|
|
||||||
},
|
|
||||||
reducerInstance,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getDialogPayload = (state, dialogName) => {
|
export const getDialogPayload = (state, dialogName) => {
|
||||||
return typeof state.dashboard.dialogs[dialogName] !== 'undefined'
|
return typeof state.dashboard.dialogs[dialogName] !== 'undefined'
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import { createTableStateReducers } from 'store/tableState.reducer';
|
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -10,17 +11,20 @@ const initialState = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('EXPENSES'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:expenses';
|
const STORAGE_KEY = 'bigcapital:expenses';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
},
|
};
|
||||||
reducerInstance,
|
|
||||||
);
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('EXPENSES'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(CONFIG, reducerInstance);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import { createTableStateReducers } from 'store/tableState.reducer';
|
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -12,17 +13,20 @@ const initialState = {
|
|||||||
selectedRows: [],
|
selectedRows: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('INVENTORY_ADJUSTMENTS'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:inventoryAdjustments';
|
const STORAGE_KEY = 'bigcapital:inventoryAdjustments';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('INVENTORY_ADJUSTMENTS'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
},
|
},
|
||||||
reducerInstance,
|
});
|
||||||
);
|
|
||||||
|
export default persistReducer(CONFIG, reducerInstance);
|
||||||
|
|||||||
@@ -1,27 +1,33 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import {
|
import {
|
||||||
createTableStateReducers,
|
createTableStateReducers,
|
||||||
} from 'store/tableState.reducer';
|
} from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
// Initial state.
|
// Initial state.
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {},
|
tableState: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('ITEMS_CATEGORIES'),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:itemCategories';
|
const STORAGE_KEY = 'bigcapital:itemCategories';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('ITEMS_CATEGORIES'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(
|
||||||
|
CONFIG,
|
||||||
reducerInstance,
|
reducerInstance,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import { createTableStateReducers } from 'store/tableState.reducer';
|
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -12,17 +13,23 @@ const initialState = {
|
|||||||
selectedRows: [],
|
selectedRows: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('ITEMS'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:items';
|
const STORAGE_KEY = 'bigcapital:items';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('ITEMS'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(
|
||||||
|
CONFIG,
|
||||||
reducerInstance,
|
reducerInstance,
|
||||||
);
|
);
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import { createTableStateReducers } from 'store/tableState.reducer';
|
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -10,17 +11,20 @@ const initialState = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('MANUAL_JOURNALS'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:manualJournals';
|
const STORAGE_KEY = 'bigcapital:manualJournals';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('MANUAL_JOURNALS'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
},
|
},
|
||||||
reducerInstance,
|
});
|
||||||
);
|
|
||||||
|
export default persistReducer(CONFIG, reducerInstance);
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ const reducer = createReducer(initialState, {
|
|||||||
const _dataByOrganizationId = {};
|
const _dataByOrganizationId = {};
|
||||||
|
|
||||||
organizations.forEach((organization) => {
|
organizations.forEach((organization) => {
|
||||||
_data[organization.id] = organization;
|
_data[organization.id] = {
|
||||||
|
...state.data[organization.id],
|
||||||
|
...organization,
|
||||||
|
};
|
||||||
_dataByOrganizationId[organization.organization_id] = organization.id;
|
_dataByOrganizationId[organization.organization_id] = organization.id;
|
||||||
});
|
});
|
||||||
state.data = _data;
|
state.data = _data;
|
||||||
|
|||||||
@@ -6,16 +6,28 @@ export default (mapState) => {
|
|||||||
isOrganizationSetupCompleted,
|
isOrganizationSetupCompleted,
|
||||||
isOrganizationInitialized,
|
isOrganizationInitialized,
|
||||||
isOrganizationSeeded,
|
isOrganizationSeeded,
|
||||||
|
|
||||||
isSubscriptionActive
|
isSubscriptionActive
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const mapped = {
|
const condits = {
|
||||||
isCongratsStep: isOrganizationSetupCompleted,
|
isCongratsStep: isOrganizationSetupCompleted,
|
||||||
isSubscriptionStep: !isSubscriptionActive,
|
isSubscriptionStep: !isSubscriptionActive,
|
||||||
isInitializingStep: isSubscriptionActive && !isOrganizationInitialized,
|
isInitializingStep: isSubscriptionActive && !isOrganizationInitialized,
|
||||||
isOrganizationStep: isOrganizationInitialized && !isOrganizationSeeded,
|
isOrganizationStep: isOrganizationInitialized && !isOrganizationSeeded,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const scenarios = [
|
||||||
|
{ condition: condits.isCongratsStep, step: 'congrats' },
|
||||||
|
{ condition: condits.isSubscriptionStep, step: 'subscription' },
|
||||||
|
{ condition: condits.isInitializingStep, step: 'initializing' },
|
||||||
|
{ condition: condits.isOrganizationStep, step: 'organization' },
|
||||||
|
];
|
||||||
|
const setupStep = scenarios.find((scenario) => scenario.condition);
|
||||||
|
const mapped = {
|
||||||
|
...condits,
|
||||||
|
setupStepId: setupStep?.step,
|
||||||
|
setupStepIndex: scenarios.indexOf(setupStep) ,
|
||||||
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
return connect(mapStateToProps);
|
return connect(mapStateToProps);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import {
|
import {
|
||||||
createTableStateReducers,
|
createTableStateReducers,
|
||||||
} from 'store/tableState.reducer';
|
} from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -12,17 +13,23 @@ const initialState = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('RECEIPTS'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:receipts';
|
const STORAGE_KEY = 'bigcapital:receipts';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('RECEIPTS'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(
|
||||||
|
CONFIG,
|
||||||
reducerInstance,
|
reducerInstance,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { camelCase } from 'lodash';
|
import { camelCase } from 'lodash';
|
||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
import { optionsArrayToMap } from 'utils';
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
data: {
|
data: {
|
||||||
organization: {
|
organization: {
|
||||||
name: 'Bigcapital, Limited Liabilities',
|
name: 'Bigcapital, LLC',
|
||||||
},
|
},
|
||||||
manualJournals: {},
|
manualJournals: {},
|
||||||
bills: {},
|
bills: {},
|
||||||
|
|||||||
@@ -22,3 +22,4 @@ export const setSubscriptions = (subscriptions) => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
27
client/src/store/vendors/vendors.reducer.js
vendored
27
client/src/store/vendors/vendors.reducer.js
vendored
@@ -1,9 +1,8 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { persistReducer } from 'redux-persist';
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import {
|
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||||
createTableStateReducers,
|
import t from 'store/types';
|
||||||
} from 'store/tableState.reducer';
|
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
tableState: {
|
tableState: {
|
||||||
@@ -11,17 +10,21 @@ const initialState = {
|
|||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const reducerInstance = createReducer(initialState, {
|
|
||||||
...createTableStateReducers('VENDORS'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'bigcapital:vendors';
|
const STORAGE_KEY = 'bigcapital:vendors';
|
||||||
|
|
||||||
export default persistReducer(
|
const CONFIG = {
|
||||||
{
|
|
||||||
key: STORAGE_KEY,
|
key: STORAGE_KEY,
|
||||||
whitelist: ['tableState'],
|
whitelist: ['tableState'],
|
||||||
storage,
|
storage,
|
||||||
},
|
};
|
||||||
reducerInstance,
|
|
||||||
);
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('VENDORS'),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(CONFIG, reducerInstance);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
color: #565e6c;
|
color: #565e6c;
|
||||||
}
|
}
|
||||||
.paragraph {
|
.paragraph {
|
||||||
opacity: 0.75;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +38,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label.bp3-label{
|
||||||
|
color: #313744;
|
||||||
|
}
|
||||||
|
|
||||||
.form-group--language {
|
.form-group--language {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
&__period{
|
&__period{
|
||||||
color: #666;
|
color: #2f3863;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
}
|
}
|
||||||
&__period {
|
&__period {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #666;
|
color: #2f3863;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '/';
|
content: '/';
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import {
|
|||||||
NoPaymentModelWithPricedPlan,
|
NoPaymentModelWithPricedPlan,
|
||||||
PaymentAmountInvalidWithPlan,
|
PaymentAmountInvalidWithPlan,
|
||||||
PaymentInputInvalid,
|
PaymentInputInvalid,
|
||||||
|
VoucherCodeRequired
|
||||||
} from 'exceptions';
|
} from 'exceptions';
|
||||||
import { ILicensePaymentModel } from 'interfaces';
|
import { ILicensePaymentModel } from 'interfaces';
|
||||||
|
import instance from 'tsyringe/dist/typings/dependency-container';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class PaymentViaLicenseController extends PaymentMethodController {
|
export default class PaymentViaLicenseController extends PaymentMethodController {
|
||||||
@@ -67,6 +69,11 @@ export default class PaymentViaLicenseController extends PaymentMethodController
|
|||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
const errorReasons = [];
|
const errorReasons = [];
|
||||||
|
|
||||||
|
if (exception instanceof VoucherCodeRequired) {
|
||||||
|
errorReasons.push({
|
||||||
|
type: 'VOUCHER_CODE_REQUIRED', code: 100,
|
||||||
|
});
|
||||||
|
}
|
||||||
if (exception instanceof NoPaymentModelWithPricedPlan) {
|
if (exception instanceof NoPaymentModelWithPricedPlan) {
|
||||||
errorReasons.push({
|
errorReasons.push({
|
||||||
type: 'NO_PAYMENT_WITH_PRICED_PLAN',
|
type: 'NO_PAYMENT_WITH_PRICED_PLAN',
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ export default () => {
|
|||||||
app.use('/organization', Container.get(Organization).router());
|
app.use('/organization', Container.get(Organization).router());
|
||||||
app.use('/ping', Container.get(Ping).router());
|
app.use('/ping', Container.get(Ping).router());
|
||||||
app.use('/setup', Container.get(Setup).router());
|
app.use('/setup', Container.get(Setup).router());
|
||||||
|
|
||||||
// - Dashboard routes.
|
// - Dashboard routes.
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
const dashboard = Router();
|
const dashboard = Router();
|
||||||
|
|||||||
Reference in New Issue
Block a user