mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 06:10:31 +00:00
WIP Toasts localizations.
This commit is contained in:
@@ -1,35 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
fetchCurrencies,
|
||||
submitCurrencies,
|
||||
deleteCurrency,
|
||||
editCurrency,
|
||||
} from 'store/currencies/currencies.actions';
|
||||
import { getDialogPayload } from 'store/dashboard/dashboard.reducer';
|
||||
import { getCurrencyById } from 'store/currencies/currencies.selector';
|
||||
|
||||
export const mapStateToProps = (state, props) => {
|
||||
const dialogPayload = getDialogPayload(state, 'currency-form');
|
||||
|
||||
return {
|
||||
currencies: state.currencies.preferences.currencies,
|
||||
name: 'currency-form',
|
||||
payload: { action: 'new', id: null, ...dialogPayload },
|
||||
editCurrency:
|
||||
dialogPayload && dialogPayload.action === 'edit'
|
||||
? state.currencies.preferences.currencies[dialogPayload.currency_code]
|
||||
: {},
|
||||
getCurrencyId: (id) =>
|
||||
getCurrencyById(state.currencies.preferences.currencies, id),
|
||||
};
|
||||
};
|
||||
|
||||
export const mapDispatchToProps = (dispatch) => ({
|
||||
requestFetchCurrencies: () => dispatch(fetchCurrencies({})),
|
||||
requestSubmitCurrencies: (form) => dispatch(submitCurrencies({ form })),
|
||||
requestEditCurrency: (id, form) => dispatch(editCurrency({ id, form })),
|
||||
requestDeleteCurrency: (currency_code) =>
|
||||
dispatch(deleteCurrency({ currency_code })),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps);
|
||||
@@ -1,21 +0,0 @@
|
||||
import {connect} from 'react-redux';
|
||||
import {
|
||||
fetchJournalSheet
|
||||
} from 'store/financialStatement/financialStatements.actions';
|
||||
import {
|
||||
getFinancialSheetIndexByQuery,
|
||||
getFinancialSheet,
|
||||
} from 'store/financialStatement/financialStatements.selectors';
|
||||
|
||||
|
||||
export const mapStateToProps = (state, props) => ({
|
||||
getJournalSheetIndex: (query) => getFinancialSheetIndexByQuery(state.financialStatements.journal.sheets, query),
|
||||
getJournalSheet: (index) => getFinancialSheet(state.financialStatements.journal.sheets, index),
|
||||
journalSheetLoading: state.financialStatements.journal.loading,
|
||||
});
|
||||
|
||||
export const mapDispatchToProps = (dispatch) => ({
|
||||
fetchJournalSheet: (query) => dispatch(fetchJournalSheet({ query })),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps);
|
||||
@@ -1,21 +0,0 @@
|
||||
import {connect} from 'react-redux';
|
||||
import {
|
||||
makeJournalEntries,
|
||||
fetchManualJournal,
|
||||
editManualJournal,
|
||||
} from 'store/manualJournals/manualJournals.actions';
|
||||
import {
|
||||
getManualJournal,
|
||||
} from 'store/manualJournals/manualJournals.reducers';
|
||||
|
||||
export const mapStateToProps = (state, props) => ({
|
||||
getManualJournal: (id) => getManualJournal(state, id),
|
||||
});
|
||||
|
||||
export const mapDispatchToProps = (dispatch) => ({
|
||||
requestMakeJournalEntries: (form) => dispatch(makeJournalEntries({ form })),
|
||||
fetchManualJournal: (id) => dispatch(fetchManualJournal({ id })),
|
||||
requestEditManualJournal: (id, form) => dispatch(editManualJournal({ id, form }))
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps);
|
||||
@@ -3,6 +3,7 @@ import * as Yup from 'yup';
|
||||
import {useFormik} from "formik";
|
||||
import moment from 'moment';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import MakeJournalEntriesHeader from './MakeJournalEntriesHeader';
|
||||
import MakeJournalEntriesFooter from './MakeJournalEntriesFooter';
|
||||
@@ -40,6 +41,7 @@ function MakeJournalEntriesForm({
|
||||
onFormSubmit,
|
||||
onCancelForm,
|
||||
}) {
|
||||
const { formatMessage } = useIntl();
|
||||
const { setFiles, saveMedia, deletedFiles, setDeletedFiles, deleteMedia } = useMedia({
|
||||
saveCallback: requestSubmitMedia,
|
||||
deleteCallback: requestDeleteMedia,
|
||||
@@ -159,7 +161,11 @@ function MakeJournalEntriesForm({
|
||||
requestEditManualJournal(manualJournal.id, requestForm)
|
||||
.then((response) => {
|
||||
AppToaster.show({
|
||||
message: 'manual_journal_has_been_edited',
|
||||
message: formatMessage({
|
||||
id: 'the_journal_has_been_successfully_edited',
|
||||
}, {
|
||||
number: values.journal_number,
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setSubmitting(false);
|
||||
@@ -178,9 +184,13 @@ function MakeJournalEntriesForm({
|
||||
requestMakeJournalEntries(requestForm)
|
||||
.then((response) => {
|
||||
AppToaster.show({
|
||||
message: 'manual_journal_has_been_submit',
|
||||
message: formatMessage({
|
||||
id: 'the_journal_has_been_successfully_created',
|
||||
}, {
|
||||
number: values.journal_number,
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
});
|
||||
setSubmitting(false);
|
||||
saveInvokeSubmit({ action: 'new', ...payload });
|
||||
clearSavedMediaIds();
|
||||
|
||||
@@ -2,7 +2,9 @@ import React, { useEffect, useCallback, useState, useMemo } from 'react';
|
||||
import {
|
||||
Intent,
|
||||
Button,
|
||||
Classes,
|
||||
Popover,
|
||||
Tooltip,
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuDivider,
|
||||
@@ -25,6 +27,8 @@ import withViewDetails from 'containers/Views/withViewDetails';
|
||||
import withManualJournals from 'containers/Accounting/withManualJournals';
|
||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||
|
||||
import { If } from 'components';
|
||||
|
||||
|
||||
function ManualJournalsDataTable({
|
||||
loading,
|
||||
@@ -135,7 +139,17 @@ function ManualJournalsDataTable({
|
||||
{
|
||||
id: 'note',
|
||||
Header: 'Note',
|
||||
accessor: r => (<Icon icon={'file-alt'} iconSize={16} />),
|
||||
accessor: (row) => (
|
||||
<If condition={row.description}>
|
||||
<Tooltip
|
||||
className={Classes.TOOLTIP_INDICATOR}
|
||||
content={row.description}
|
||||
position={Position.TOP}
|
||||
hoverOpenDelay={250}>
|
||||
<Icon icon={'file-alt'} iconSize={16} />
|
||||
</Tooltip>
|
||||
</If>
|
||||
),
|
||||
disableResizing: true,
|
||||
disableSorting: true,
|
||||
width: 100,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
||||
import {
|
||||
Route,
|
||||
Switch,
|
||||
} from 'react-router-dom';
|
||||
import { Alert, Intent } from '@blueprintjs/core';
|
||||
import { useQuery } from 'react-query'
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import AppToaster from 'components/AppToaster';
|
||||
|
||||
@@ -22,6 +23,7 @@ import withViewsActions from 'containers/Views/withViewsActions';
|
||||
import withAccounts from 'containers/Accounts/withAccounts';
|
||||
|
||||
import { compose } from 'utils';
|
||||
import { FormattedMessage as T, FormattedHTMLMessage } from 'react-intl';
|
||||
|
||||
|
||||
function AccountsChart({
|
||||
@@ -32,6 +34,7 @@ function AccountsChart({
|
||||
// #withAccountsActions
|
||||
requestDeleteAccount,
|
||||
requestInactiveAccount,
|
||||
requestActivateAccount,
|
||||
|
||||
// #withViewsActions
|
||||
requestFetchResourceViews,
|
||||
@@ -47,8 +50,11 @@ function AccountsChart({
|
||||
// #withAccounts
|
||||
accountsTableQuery,
|
||||
}) {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const [deleteAccount, setDeleteAccount] = useState(false);
|
||||
const [inactiveAccount, setInactiveAccount] = useState(false);
|
||||
const [activateAccount, setActivateAccount] = useState(false);
|
||||
const [bulkDelete, setBulkDelete] = useState(false);
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
|
||||
@@ -64,8 +70,7 @@ function AccountsChart({
|
||||
|
||||
// Fetch accounts list according to the given custom view id.
|
||||
const fetchAccountsHook = useQuery(['accounts-table', accountsTableQuery],
|
||||
() => requestFetchAccountsTable(),
|
||||
{ refetchInterval: 3000 });
|
||||
() => requestFetchAccountsTable());
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle('Chart of Accounts');
|
||||
@@ -76,25 +81,34 @@ function AccountsChart({
|
||||
|
||||
// handle cancel delete account alert.
|
||||
const handleCancelAccountDelete = useCallback(() => { setDeleteAccount(false); }, []);
|
||||
|
||||
const handleDeleteErrors = (errors) => {
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.PREDEFINED')) {
|
||||
AppToaster.show({
|
||||
message: formatMessage({
|
||||
id: 'you_could_not_delete_predefined_accounts',
|
||||
}),
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
}
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.HAS.ASSOCIATED.TRANSACTIONS')) {
|
||||
AppToaster.show({
|
||||
message: 'cannot_delete_account_has_associated_transactions'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Handle confirm account delete
|
||||
const handleConfirmAccountDelete = useCallback(() => {
|
||||
requestDeleteAccount(deleteAccount.id).then(() => {
|
||||
setDeleteAccount(false);
|
||||
AppToaster.show({ message: 'the_account_has_been_deleted' });
|
||||
AppToaster.show({
|
||||
message: formatMessage({ id: 'the_account_has_been_successfully_deleted' }),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
}).catch(errors => {
|
||||
setDeleteAccount(false);
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.PREDEFINED')) {
|
||||
AppToaster.show({
|
||||
message: 'cannot_delete_predefined_account',
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
}
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.HAS.ASSOCIATED.TRANSACTIONS')) {
|
||||
AppToaster.show({
|
||||
message: 'cannot_delete_account_has_associated_transactions'
|
||||
});
|
||||
}
|
||||
handleDeleteErrors(errors);
|
||||
});
|
||||
}, [deleteAccount, requestDeleteAccount]);
|
||||
|
||||
@@ -112,11 +126,34 @@ function AccountsChart({
|
||||
const handleConfirmAccountActive = useCallback(() => {
|
||||
requestInactiveAccount(inactiveAccount.id).then(() => {
|
||||
setInactiveAccount(false);
|
||||
requestFetchAccountsTable();
|
||||
AppToaster.show({ message: 'the_account_has_been_inactivated' });
|
||||
AppToaster.show({
|
||||
message: formatMessage({
|
||||
id: 'the_account_has_been_successfully_inactivated',
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
});
|
||||
}, [inactiveAccount, requestFetchAccountsTable, requestInactiveAccount]);
|
||||
}, [inactiveAccount, requestInactiveAccount]);
|
||||
|
||||
const handleActivateAccount = useCallback((account) => {
|
||||
setActivateAccount(account);
|
||||
});
|
||||
|
||||
const handleCancelActivateAccount = useCallback(() => {
|
||||
setActivateAccount(false);
|
||||
});
|
||||
|
||||
const handleConfirmAccountActivate = useCallback(() => {
|
||||
requestActivateAccount(activateAccount.id).then(() => {
|
||||
setActivateAccount(false);
|
||||
AppToaster.show({
|
||||
message: formatMessage({
|
||||
id: 'the_account_has_been_successfully_activated',
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const handleEditAccount = (account) => {
|
||||
|
||||
@@ -133,9 +170,13 @@ function AccountsChart({
|
||||
const handleConfirmBulkDelete = useCallback(() => {
|
||||
requestDeleteBulkAccounts(bulkDelete).then(() => {
|
||||
setBulkDelete(false);
|
||||
AppToaster.show({ message: 'the_accounts_have_been_deleted' });
|
||||
}).catch((error) => {
|
||||
AppToaster.show({
|
||||
message: formatMessage({ id: 'the_accounts_has_been_successfully_deleted' }),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
}).catch((errors) => {
|
||||
setBulkDelete(false);
|
||||
handleDeleteErrors(errors);
|
||||
});
|
||||
}, [requestDeleteBulkAccounts, bulkDelete]);
|
||||
|
||||
@@ -179,6 +220,9 @@ function AccountsChart({
|
||||
fetchAccountsHook.refetch();
|
||||
}, [fetchAccountsHook, addAccountsTableQueries]);
|
||||
|
||||
// Calculates the data table selected rows count.
|
||||
const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [selectedRows]);
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={fetchHook.isFetching}
|
||||
@@ -203,6 +247,7 @@ function AccountsChart({
|
||||
<AccountsDataTable
|
||||
onDeleteAccount={handleDeleteAccount}
|
||||
onInactiveAccount={handleInactiveAccount}
|
||||
onActivateAccount={handleActivateAccount}
|
||||
onRestoreAccount={handleRestoreAccount}
|
||||
onEditAccount={handleEditAccount}
|
||||
onFetchData={handleFetchData}
|
||||
@@ -213,43 +258,52 @@ function AccountsChart({
|
||||
|
||||
<Alert
|
||||
cancelButtonText="Cancel"
|
||||
confirmButtonText="Move to Trash"
|
||||
confirmButtonText="Delete"
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={deleteAccount}
|
||||
onCancel={handleCancelAccountDelete}
|
||||
onConfirm={handleConfirmAccountDelete}>
|
||||
<p>
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
||||
but it will become private to you.
|
||||
<FormattedHTMLMessage
|
||||
id={'once_delete_this_account_you_will_able_to_restore_it'} />
|
||||
</p>
|
||||
</Alert>
|
||||
|
||||
<Alert
|
||||
cancelButtonText="Cancel"
|
||||
confirmButtonText="Inactivate"
|
||||
icon="trash"
|
||||
intent={Intent.WARNING}
|
||||
isOpen={inactiveAccount}
|
||||
onCancel={handleCancelInactiveAccount}
|
||||
onConfirm={handleConfirmAccountActive}>
|
||||
<p>
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
||||
but it will become private to you.
|
||||
<T id={'are_sure_to_inactive_this_account'} />
|
||||
</p>
|
||||
</Alert>
|
||||
|
||||
<Alert
|
||||
cancelButtonText="Cancel"
|
||||
confirmButtonText="Delete"
|
||||
confirmButtonText="Activate"
|
||||
intent={Intent.WARNING}
|
||||
isOpen={activateAccount}
|
||||
onCancel={handleCancelActivateAccount}
|
||||
onConfirm={handleConfirmAccountActivate}>
|
||||
<p>
|
||||
<T id={'are_sure_to_activate_this_account'} />
|
||||
</p>
|
||||
</Alert>
|
||||
|
||||
<Alert
|
||||
cancelButtonText="Cancel"
|
||||
confirmButtonText={`Delete (${selectedRowsCount})`}
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={bulkDelete}
|
||||
onCancel={handleCancelBulkDelete}
|
||||
onConfirm={handleConfirmBulkDelete}>
|
||||
<p>
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
||||
but it will become private to you.
|
||||
<T id={'once_delete_these_accounts_you_will_not_able_restore_them'} />
|
||||
</p>
|
||||
</Alert>
|
||||
</DashboardPageContent>
|
||||
|
||||
@@ -9,6 +9,8 @@ import {
|
||||
Classes,
|
||||
Tooltip,
|
||||
} from '@blueprintjs/core';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import { compose } from 'utils';
|
||||
import DialogConnect from 'connectors/Dialog.connector';
|
||||
@@ -21,6 +23,8 @@ import withDashboardActions from 'containers/Dashboard/withDashboard';
|
||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||
import withAccounts from 'containers/Accounts/withAccounts';
|
||||
|
||||
import { If } from 'components';
|
||||
|
||||
|
||||
function AccountsDataTable({
|
||||
// #withAccounts
|
||||
@@ -36,8 +40,10 @@ function AccountsDataTable({
|
||||
onSelectedRowsChange,
|
||||
onDeleteAccount,
|
||||
onInactiveAccount,
|
||||
onActivateAccount,
|
||||
}) {
|
||||
const [initialMount, setInitialMount] = useState(false);
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
useUpdateEffect(() => {
|
||||
if (!accountsLoading) {
|
||||
@@ -64,9 +70,16 @@ function AccountsDataTable({
|
||||
text='New Account'
|
||||
onClick={() => handleNewParentAccount(account)} />
|
||||
<MenuDivider />
|
||||
<MenuItem
|
||||
text='Inactivate Account'
|
||||
onClick={() => onInactiveAccount(account)} />
|
||||
<If condition={account.active}>
|
||||
<MenuItem
|
||||
text='Inactivate Account'
|
||||
onClick={() => onInactiveAccount(account)} />
|
||||
</If>
|
||||
<If condition={!account.active}>
|
||||
<MenuItem
|
||||
text='Activate Account'
|
||||
onClick={() => onActivateAccount(account)} />
|
||||
</If>
|
||||
<MenuItem
|
||||
text='Delete Account'
|
||||
onClick={() => onDeleteAccount(account)} />
|
||||
@@ -109,10 +122,18 @@ function AccountsDataTable({
|
||||
Header: 'Normal',
|
||||
Cell: ({ cell }) => {
|
||||
const account = cell.row.original;
|
||||
const type = account.type ? account.type.normal : '';
|
||||
const arrowDirection = type === 'credit' ? 'down' : 'up';
|
||||
const normal = account.type ? account.type.normal : '';
|
||||
const arrowDirection = normal === 'credit' ? 'down' : 'up';
|
||||
|
||||
return (<Icon icon={`arrow-${arrowDirection}`} />);
|
||||
return (
|
||||
<Tooltip
|
||||
className={Classes.TOOLTIP_INDICATOR}
|
||||
content={formatMessage({ id: normal })}
|
||||
position={Position.RIGHT}
|
||||
hoverOpenDelay={500}>
|
||||
<Icon icon={`arrow-${arrowDirection}`} />
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
className: 'normal',
|
||||
width: 75,
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
fetchAccountsList,
|
||||
deleteAccount,
|
||||
inactiveAccount,
|
||||
activateAccount,
|
||||
submitAccount,
|
||||
fetchAccount,
|
||||
deleteBulkAccounts,
|
||||
@@ -15,6 +16,7 @@ const mapActionsToProps = (dispatch) => ({
|
||||
requestSubmitAccount: ({ form }) => dispatch(submitAccount({ form })),
|
||||
requestDeleteAccount: (id) => dispatch(deleteAccount({ id })),
|
||||
requestInactiveAccount: (id) => dispatch(inactiveAccount({ id })),
|
||||
requestActivateAccount: (id) => dispatch(activateAccount({ id })),
|
||||
requestFetchAccount: (id) => dispatch(fetchAccount({ id })),
|
||||
requestDeleteBulkAccounts: (ids) => dispatch(deleteBulkAccounts({ ids })),
|
||||
});
|
||||
|
||||
@@ -49,14 +49,14 @@ function AccountFormDialog({
|
||||
|
||||
// #withDialog
|
||||
closeDialog,
|
||||
}) {
|
||||
const intl = useIntl();
|
||||
}) {
|
||||
const { formatMessage } = useIntl();
|
||||
const accountFormValidationSchema = Yup.object().shape({
|
||||
name: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||
name: Yup.string().required(formatMessage({ id: 'required' })),
|
||||
code: Yup.number(),
|
||||
account_type_id: Yup.string()
|
||||
.nullable()
|
||||
.required(intl.formatMessage({ id: 'required' })),
|
||||
.required(formatMessage({ id: 'required' })),
|
||||
description: Yup.string().trim()
|
||||
});
|
||||
|
||||
@@ -89,6 +89,7 @@ function AccountFormDialog({
|
||||
validationSchema: accountFormValidationSchema,
|
||||
onSubmit: (values, { setSubmitting, setErrors }) => {
|
||||
const exclude = ['subaccount'];
|
||||
const toastAccountName = (values.code) ? `${values.code} - ${values.name}` : values.name;
|
||||
|
||||
if (payload.action === 'edit') {
|
||||
requestEditAccount({
|
||||
@@ -97,7 +98,12 @@ function AccountFormDialog({
|
||||
}).then((response) => {
|
||||
closeDialog(name);
|
||||
AppToaster.show({
|
||||
message: 'the_account_has_been_edited',
|
||||
message: formatMessage({
|
||||
id: 'service_has_been_successful_edited',
|
||||
}, {
|
||||
name: toastAccountName,
|
||||
service: formatMessage({ id: 'account' }),
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setSubmitting(false);
|
||||
@@ -110,7 +116,12 @@ function AccountFormDialog({
|
||||
requestSubmitAccount({ form: { ...omit(values, exclude) } }).then((response) => {
|
||||
closeDialog(name);
|
||||
AppToaster.show({
|
||||
message: 'the_account_has_been_submit',
|
||||
message: formatMessage({
|
||||
id: 'service_has_been_successful_created',
|
||||
}, {
|
||||
name: toastAccountName,
|
||||
service: formatMessage({ id: 'account' }),
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
position: Position.BOTTOM,
|
||||
});
|
||||
|
||||
@@ -55,13 +55,13 @@ function ItemCategoryDialog({
|
||||
requestEditItemCategory,
|
||||
}) {
|
||||
const [selectedParentCategory, setParentCategory] = useState(null);
|
||||
const intl = useIntl();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const fetchList = useQuery(['items-categories-list'],
|
||||
() => requestFetchItemCategories());
|
||||
|
||||
const ValidationSchema = Yup.object().shape({
|
||||
name: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||
const validationSchema = Yup.object().shape({
|
||||
name: Yup.string().required(),
|
||||
parent_category_id: Yup.string().nullable(),
|
||||
description: Yup.string().trim()
|
||||
});
|
||||
@@ -88,13 +88,15 @@ function ItemCategoryDialog({
|
||||
...(payload.action === 'edit' &&
|
||||
pick(itemCategory, Object.keys(initialValues)))
|
||||
},
|
||||
validationSchema: ValidationSchema,
|
||||
validationSchema,
|
||||
onSubmit: (values, { setSubmitting }) => {
|
||||
if (payload.action === 'edit') {
|
||||
requestEditItemCategory(payload.id, values).then(response => {
|
||||
closeDialog(name);
|
||||
AppToaster.show({
|
||||
message: 'the_category_has_been_edited',
|
||||
message: formatMessage({
|
||||
id: 'the_item_category_has_been_successfully_edited',
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setSubmitting(false);
|
||||
@@ -107,7 +109,9 @@ function ItemCategoryDialog({
|
||||
.then((response) => {
|
||||
closeDialog(name);
|
||||
AppToaster.show({
|
||||
message: 'the_category_has_been_submit',
|
||||
message: formatMessage({
|
||||
id: 'the_item_category_has_been_successfully_created',
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setSubmitting(false);
|
||||
|
||||
@@ -23,13 +23,12 @@ import { compose } from 'utils';
|
||||
function UserFormDialog({
|
||||
requestFetchUser,
|
||||
requestSubmitInvite,
|
||||
requestEditUser,
|
||||
name,
|
||||
payload,
|
||||
isOpen,
|
||||
closeDialog,
|
||||
}) {
|
||||
const intl = useIntl();
|
||||
const { formatMessage } = useIntl();
|
||||
const fetchHook = useAsync(async () => {
|
||||
await Promise.all([
|
||||
...(payload.action === 'edit' ? [requestFetchUser(payload.user.id)] : []),
|
||||
@@ -37,7 +36,7 @@ function UserFormDialog({
|
||||
}, false);
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
email: Yup.string().email().required(intl.formatMessage({id:'required'})),
|
||||
email: Yup.string().email().required(),
|
||||
});
|
||||
|
||||
const initialValues = {
|
||||
@@ -56,29 +55,23 @@ function UserFormDialog({
|
||||
resetForm,
|
||||
getFieldProps,
|
||||
handleSubmit,
|
||||
isSubmitting,
|
||||
} = useFormik({
|
||||
enableReinitialize: true,
|
||||
initialValues,
|
||||
validationSchema,
|
||||
onSubmit: (values) => {
|
||||
const form = {
|
||||
...values,
|
||||
};
|
||||
if (payload.action === 'edit') {
|
||||
requestEditUser(payload.user.id, form).then((response) => {
|
||||
AppToaster.show({
|
||||
message: 'the_user_details_has_been_updated',
|
||||
});
|
||||
closeDialog(name);
|
||||
const form = { ...values };
|
||||
|
||||
requestSubmitInvite(form).then((response) => {
|
||||
AppToaster.show({
|
||||
message: formatMessage({
|
||||
id: 'teammate_invited_to_organization_account',
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
} else {
|
||||
requestSubmitInvite(form).then((response) => {
|
||||
AppToaster.show({
|
||||
message: 'the_user_has_been_invited',
|
||||
});
|
||||
closeDialog(name);
|
||||
});
|
||||
}
|
||||
closeDialog(name);
|
||||
});
|
||||
},
|
||||
});
|
||||
const onDialogOpening = () => {
|
||||
@@ -89,9 +82,7 @@ function UserFormDialog({
|
||||
resetForm();
|
||||
}, [resetForm]);
|
||||
|
||||
const handleClose = () => {
|
||||
closeDialog(name);
|
||||
};
|
||||
const handleClose = () => { closeDialog(name); };
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
@@ -130,7 +121,7 @@ function UserFormDialog({
|
||||
<div className={Classes.DIALOG_FOOTER}>
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<Button onClick={handleClose}>Close</Button>
|
||||
<Button intent={Intent.PRIMARY} type='submit'>
|
||||
<Button intent={Intent.PRIMARY} type='submit' disabled={isSubmitting}>
|
||||
{payload.action === 'edit' ? 'Edit' : 'invite'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
Checkbox,
|
||||
} from '@blueprintjs/core';
|
||||
import { Row, Col } from 'react-grid-system';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Select } from '@blueprintjs/select';
|
||||
import AppToaster from 'components/AppToaster';
|
||||
import AccountsConnect from 'connectors/Accounts.connector';
|
||||
@@ -27,6 +28,7 @@ import Dragzone from 'components/Dragzone';
|
||||
import MediaConnect from 'connectors/Media.connect';
|
||||
import useMedia from 'hooks/useMedia';
|
||||
|
||||
|
||||
const ItemForm = ({
|
||||
requestSubmitItem,
|
||||
|
||||
@@ -38,6 +40,7 @@ const ItemForm = ({
|
||||
}) => {
|
||||
const [selectedAccounts, setSelectedAccounts] = useState({});
|
||||
const history = useHistory();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const {
|
||||
files,
|
||||
@@ -49,7 +52,7 @@ const ItemForm = ({
|
||||
} = useMedia({
|
||||
saveCallback: requestSubmitMedia,
|
||||
deleteCallback: requestDeleteMedia,
|
||||
})
|
||||
});
|
||||
|
||||
const ItemTypeDisplay = useMemo(() => ([
|
||||
{ value: null, label: 'Select Item Type' },
|
||||
@@ -97,6 +100,7 @@ const ItemForm = ({
|
||||
touched,
|
||||
errors,
|
||||
handleSubmit,
|
||||
isSubmitting,
|
||||
} = useFormik({
|
||||
enableReinitialize: true,
|
||||
validationSchema: validationSchema,
|
||||
@@ -109,7 +113,13 @@ const ItemForm = ({
|
||||
|
||||
return requestSubmitItem(formValues).then((response) => {
|
||||
AppToaster.show({
|
||||
message: 'The_Items_has_been_submit'
|
||||
message: formatMessage({
|
||||
id: 'service_has_been_successful_created',
|
||||
}, {
|
||||
name: values.name,
|
||||
service: formatMessage({ id: 'item' }),
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setSubmitting(false);
|
||||
history.push('/dashboard/items');
|
||||
@@ -439,11 +449,11 @@ const ItemForm = ({
|
||||
</Row>
|
||||
|
||||
<div class='form__floating-footer'>
|
||||
<Button intent={Intent.PRIMARY} type='submit'>
|
||||
<Button intent={Intent.PRIMARY} disabled={isSubmitting} type='submit'>
|
||||
Save
|
||||
</Button>
|
||||
|
||||
<Button className={'ml1'}>Save as Draft</Button>
|
||||
<Button className={'ml1'} disabled={isSubmitting}>Save as Draft</Button>
|
||||
<Button className={'ml1'} onClick={handleCancelClickBtn}>Close</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Alert,
|
||||
} from '@blueprintjs/core';
|
||||
import { useQuery } from 'react-query';
|
||||
import { FormattedHTMLMessage, useIntl } from 'react-intl';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import ItemsActionsBar from 'containers/Items/ItemsActionsBar';
|
||||
@@ -26,6 +27,7 @@ import withItemsActions from 'containers/Items/withItemsActions';
|
||||
import withViewsActions from 'containers/Views/withViewsActions';
|
||||
|
||||
|
||||
|
||||
function ItemsList({
|
||||
// #withDashboard
|
||||
changePageTitle,
|
||||
@@ -46,6 +48,8 @@ function ItemsList({
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
const [tableLoading, setTableLoading] = useState(false);
|
||||
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle('Items List');
|
||||
}, [changePageTitle]);
|
||||
@@ -75,7 +79,12 @@ function ItemsList({
|
||||
// handle confirm delete item.
|
||||
const handleConfirmDeleteItem = useCallback(() => {
|
||||
requestDeleteItem(deleteItem.id).then(() => {
|
||||
AppToaster.show({ message: 'the_item_has_been_deleted' });
|
||||
AppToaster.show({
|
||||
message: formatMessage({
|
||||
id: 'the_item_has_been_successfully_deleted',
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setDeleteItem(false);
|
||||
});
|
||||
}, [requestDeleteItem, deleteItem]);
|
||||
@@ -142,15 +151,15 @@ function ItemsList({
|
||||
|
||||
<Alert
|
||||
cancelButtonText="Cancel"
|
||||
confirmButtonText="Move to Trash"
|
||||
confirmButtonText="Delete"
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={deleteItem}
|
||||
onCancel={handleCancelDeleteItem}
|
||||
onConfirm={handleConfirmDeleteItem}>
|
||||
<p>
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
||||
but it will become private to you.
|
||||
<FormattedHTMLMessage
|
||||
id={'once_delete_this_item_you_will_able_to_restore_it'} />
|
||||
</p>
|
||||
</Alert>
|
||||
</Route>
|
||||
|
||||
@@ -18,7 +18,7 @@ const viewFormConnect = connect(mapStateToProps);
|
||||
export default compose(
|
||||
withDashboard,
|
||||
withViewsActions,
|
||||
withViewsDetails(),
|
||||
withViewsDetails,
|
||||
viewFormConnect,
|
||||
withResourceDetail(),
|
||||
);
|
||||
@@ -2,6 +2,8 @@ import React, {useEffect, useState, useMemo, useCallback} from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Intent, Alert } from '@blueprintjs/core';
|
||||
import { FormattedHTMLMessage, useIntl } from 'react-intl';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||
import ViewForm from 'containers/Views/ViewForm';
|
||||
@@ -30,6 +32,8 @@ function ViewFormPage({
|
||||
const { resource_slug: resourceSlug, view_id: viewId } = useParams();
|
||||
const [stateDeleteView, setStateDeleteView] = useState(null);
|
||||
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const fetchHook = useAsync(async () => {
|
||||
return Promise.all([
|
||||
...(resourceSlug) ? [
|
||||
@@ -67,7 +71,9 @@ function ViewFormPage({
|
||||
requestDeleteView(stateDeleteView.id).then((response) => {
|
||||
setStateDeleteView(null);
|
||||
AppToaster.show({
|
||||
message: 'the_custom_view_has_been_deleted',
|
||||
message: formatMessage({
|
||||
id: 'the_custom_view_has_been_successfully_deleted',
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
})
|
||||
@@ -87,15 +93,15 @@ function ViewFormPage({
|
||||
|
||||
<Alert
|
||||
cancelButtonText="Cancel"
|
||||
confirmButtonText="Move to Trash"
|
||||
confirmButtonText="Delete"
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={stateDeleteView}
|
||||
onCancel={handleCancelDeleteView}
|
||||
onConfirm={handleConfirmDeleteView}>
|
||||
<p>
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
||||
but it will become private to you.
|
||||
<FormattedHTMLMessage
|
||||
id={'once_delete_these_views_you_will_not_able_restore_them'} />
|
||||
</p>
|
||||
</Alert>
|
||||
</If>
|
||||
|
||||
@@ -27,4 +27,37 @@ export default {
|
||||
'need_bigcapital_account?': 'Need a Bigcapital account ?',
|
||||
'show': 'Show',
|
||||
'hide': 'Hide',
|
||||
'item': 'Item',
|
||||
'account': 'Account',
|
||||
'service_has_been_successful_created': '{service} {name} has been successfully created.',
|
||||
'service_has_been_successful_edited': '{service} {name} has been successfully edited.',
|
||||
'you_are_about_permanently_delete_this_journal': `You're about to permanently delete this journal and all its transactions on accounts and attachments, and all of its data. <br /><br />If you're not sure, you can archive this journal instead.`,
|
||||
'once_delete_these_accounts_you_will_not_able_restore_them': 'Once you delete these accounts, you won\'t be able to retrieve them later. Are you sure you want to delete them?',
|
||||
'once_delete_these_service_you_will_not_able_restore_it': 'Once you delete these {service}, you won\'t be able to retrieve them later. Are you sure you want to delete this {service}?',
|
||||
'you_could_not_delete_predefined_accounts': 'You could\'t delete predefined accounts.',
|
||||
'cannot_delete_account_has_associated_transactions': 'you could\'t not delete account that has associated transactions.',
|
||||
'the_account_has_been_successfully_inactivated': 'The account has been successfully inactivated.',
|
||||
'the_account_has_been_successfully_activated': 'The account has been successfully activated.',
|
||||
'the_account_has_been_successfully_deleted': 'The account has been successfully deleted.',
|
||||
'the_accounts_has_been_successfully_deleted': 'The accounts have been successfully deleted.',
|
||||
'are_sure_to_inactive_this_account': 'Are you sure you want to inactive this account? You will be able to activate it later',
|
||||
'are_sure_to_activate_this_account': 'Are you sure you want to activate this account? You will be able to inactivate it later',
|
||||
|
||||
'once_delete_this_account_you_will_able_to_restore_it': `Once you delete this account, you won\'t be able to restore it later. Are you sure you want to delete this account?<br /><br />If you're not sure, you can inactivate this account instead.`,
|
||||
'the_journal_has_been_successfully_created': 'The journal #{number} has been successfully created.',
|
||||
'the_journal_has_been_successfully_edited': 'The journal #{number} has been successfully edited.',
|
||||
|
||||
'credit': 'Credit',
|
||||
'debit': 'Debit',
|
||||
|
||||
'once_delete_this_item_you_will_able_to_restore_it': `Once you delete this item, you won\'t be able to restore the item later. Are you sure you want to delete ?<br /><br />If you're not sure, you can inactivate it instead.`,
|
||||
'the_item_has_been_successfully_deleted': 'The item has been successfully deleted.',
|
||||
|
||||
'the_item_category_has_been_successfully_created': 'The item category has been successfully created.',
|
||||
'the_item_category_has_been_successfully_edited': 'The item category has been successfully edited.',
|
||||
|
||||
'once_delete_these_views_you_will_not_able_restore_them': 'Once you delete the custom view, you won\'t be able to restore it later. Are you sure you want to delete this view?',
|
||||
'the_custom_view_has_been_successfully_deleted': 'The custom view has been successfully deleted.',
|
||||
|
||||
'teammate_invited_to_organization_account': 'Your teammate has been invited to the organization account.'
|
||||
};
|
||||
@@ -177,7 +177,7 @@ export const editAccount = ({ id, form }) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const activeAccount = ({ id }) => {
|
||||
export const activateAccount = ({ id }) => {
|
||||
return dispatch => ApiService.post(`accounts/${id}/active`);
|
||||
};
|
||||
|
||||
@@ -205,7 +205,11 @@ export const deleteBulkAccounts = ({ ids }) => {
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => {
|
||||
reject(error.response.data.errors || []);
|
||||
const { response } = error;
|
||||
const { data } = response;
|
||||
const { errors } = data;
|
||||
|
||||
reject(errors);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
.code{
|
||||
color: #666;
|
||||
}
|
||||
.normal{
|
||||
.bp3-popover-wrapper{
|
||||
width: 100%;
|
||||
}
|
||||
.bp3-tooltip-indicator{
|
||||
cursor: initial;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
.actions{
|
||||
padding-right: 18px;
|
||||
justify-content: right;
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
.bp3-icon{
|
||||
color: #666;
|
||||
}
|
||||
.bp3-tooltip-indicator{
|
||||
cursor: initial;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
.status{
|
||||
font-size: 13px;
|
||||
|
||||
Reference in New Issue
Block a user