mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77f0a767b3 | ||
|
|
8a982e5c7e | ||
|
|
2f7564eb9c | ||
|
|
7c2c362585 | ||
|
|
786aad438a | ||
|
|
d6c78a9908 | ||
|
|
0aca6d9af7 | ||
|
|
696943153d | ||
|
|
2e437d7b65 | ||
|
|
5b12c4a433 | ||
|
|
96269ccafb | ||
|
|
f556f061cb | ||
|
|
b98e8aeeb4 | ||
|
|
17d5bbd9d1 | ||
|
|
e1ab4e4d65 | ||
|
|
b86a3a19dc | ||
|
|
3b2796cb6d | ||
|
|
15ee32f6a4 | ||
|
|
90e550c902 | ||
|
|
cbc0ccbfb9 | ||
|
|
526c46b24d | ||
|
|
6041c175fd | ||
|
|
0f58665a0d | ||
|
|
91036c3e52 | ||
|
|
555e3a2434 | ||
|
|
b87e85d5ff | ||
|
|
288225a0c1 | ||
|
|
71f9fa47d4 | ||
|
|
fcace4213c | ||
|
|
31d2b1b09a | ||
|
|
cd5116dbcb | ||
|
|
010b660318 | ||
|
|
4e99607b06 | ||
|
|
a3f1857e91 | ||
|
|
460ee2718e | ||
|
|
87938b8f41 | ||
|
|
cd70bf1d80 | ||
|
|
c4f2ea405c | ||
|
|
d1cb7eb51b | ||
|
|
e949b1b0c7 | ||
|
|
9b7382e222 | ||
|
|
364859a793 | ||
|
|
fd07306102 | ||
|
|
5fc4897663 | ||
|
|
7b85dfee5d | ||
|
|
14012c4d7e | ||
|
|
ecf56f3b99 |
@@ -6,6 +6,15 @@ WORKDIR /app
|
|||||||
|
|
||||||
COPY ./package.json /app/package.json
|
COPY ./package.json /app/package.json
|
||||||
COPY ./package-lock.json /app/package-lock.json
|
COPY ./package-lock.json /app/package-lock.json
|
||||||
|
COPY ./.npmrc /app/.npmrc
|
||||||
|
|
||||||
|
ARG GITHUB_USERNAME
|
||||||
|
ARG GITHUB_PASS
|
||||||
|
ARG GITHUB_EMAIL
|
||||||
|
|
||||||
|
RUN npm install -g npm-cli-login
|
||||||
|
|
||||||
|
RUN npm-cli-login -s @bigcapitalhq -r https://npm.pkg.github.com -u $GITHUB_USERNAME -p $GITHUB_PASS -e $GITHUB_EMAIL
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
|
|||||||
17639
package-lock.json
generated
17639
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "7.8.4",
|
"@babel/core": "7.8.4",
|
||||||
"@blueprintjs/core": "^3.38.1",
|
"@blueprintjs/core": "^3.50.2",
|
||||||
"@blueprintjs/datetime": "^3.15.2",
|
"@blueprintjs/datetime": "^3.23.12",
|
||||||
"@blueprintjs/popover2": "^0.11.1",
|
"@blueprintjs/popover2": "^0.11.1",
|
||||||
"@blueprintjs/select": "^3.11.2",
|
"@blueprintjs/select": "^3.11.2",
|
||||||
"@blueprintjs/table": "^3.8.3",
|
"@blueprintjs/table": "^3.8.3",
|
||||||
|
|||||||
@@ -13,3 +13,9 @@ export const TABLES = {
|
|||||||
MANUAL_JOURNALS: 'manual_journal',
|
MANUAL_JOURNALS: 'manual_journal',
|
||||||
EXPENSES: 'expenses',
|
EXPENSES: 'expenses',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const TABLE_SIZE = {
|
||||||
|
COMPACT: 'compact',
|
||||||
|
SMALL: 'small',
|
||||||
|
MEDIUM: 'medium',
|
||||||
|
}
|
||||||
@@ -4,8 +4,9 @@ import { DateInput } from '@blueprintjs/datetime';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { isUndefined } from 'lodash';
|
import { isUndefined } from 'lodash';
|
||||||
|
|
||||||
import { useAutofocus } from 'hooks';
|
import { useAutofocus } from 'hooks';
|
||||||
import { Choose, ListSelect } from 'components';
|
import { T, Choose, ListSelect } from 'components';
|
||||||
import { momentFormatter } from 'utils';
|
import { momentFormatter } from 'utils';
|
||||||
|
|
||||||
function AdvancedFilterEnumerationField({ options, value, ...rest }) {
|
function AdvancedFilterEnumerationField({ options, value, ...rest }) {
|
||||||
@@ -19,7 +20,7 @@ function AdvancedFilterEnumerationField({ options, value, ...rest }) {
|
|||||||
minimal: true,
|
minimal: true,
|
||||||
captureDismiss: true,
|
captureDismiss: true,
|
||||||
}}
|
}}
|
||||||
defaultText={`Select an option`}
|
defaultText={<T id={'filter.select_option'} />}
|
||||||
textProp={'label'}
|
textProp={'label'}
|
||||||
selectedItemProp={'key'}
|
selectedItemProp={'key'}
|
||||||
{...rest}
|
{...rest}
|
||||||
@@ -32,8 +33,7 @@ const IFieldType = {
|
|||||||
BOOLEAN: 'boolean',
|
BOOLEAN: 'boolean',
|
||||||
NUMBER: 'number',
|
NUMBER: 'number',
|
||||||
DATE: 'date',
|
DATE: 'date',
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function tansformDateValue(date, defaultValue = null) {
|
function tansformDateValue(date, defaultValue = null) {
|
||||||
return date ? moment(date).toDate() : defaultValue;
|
return date ? moment(date).toDate() : defaultValue;
|
||||||
@@ -46,13 +46,13 @@ export default function AdvancedFilterValueField2({
|
|||||||
fieldType,
|
fieldType,
|
||||||
options,
|
options,
|
||||||
onChange,
|
onChange,
|
||||||
isFocus
|
isFocus,
|
||||||
}) {
|
}) {
|
||||||
const [localValue, setLocalValue] = React.useState(value);
|
const [localValue, setLocalValue] = React.useState(value);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (localValue !== value && !isUndefined(value)) {
|
if (localValue !== value && !isUndefined(value)) {
|
||||||
setLocalValue(value)
|
setLocalValue(value);
|
||||||
}
|
}
|
||||||
}, [localValue, value]);
|
}, [localValue, value]);
|
||||||
|
|
||||||
@@ -106,10 +106,10 @@ export default function AdvancedFilterValueField2({
|
|||||||
position: Position.BOTTOM,
|
position: Position.BOTTOM,
|
||||||
}}
|
}}
|
||||||
shortcuts={true}
|
shortcuts={true}
|
||||||
placeholder={'Enter date'}
|
placeholder={intl.get('filter.enter_date')}
|
||||||
fill={true}
|
fill={true}
|
||||||
inputProps={{
|
inputProps={{
|
||||||
fill: true
|
fill: true,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Choose.When>
|
</Choose.When>
|
||||||
@@ -120,7 +120,7 @@ export default function AdvancedFilterValueField2({
|
|||||||
|
|
||||||
<Choose.Otherwise>
|
<Choose.Otherwise>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
placeholder={intl.get('value')}
|
placeholder={intl.get('filter.value')}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
value={localValue}
|
value={localValue}
|
||||||
inputRef={valueRef}
|
inputRef={valueRef}
|
||||||
@@ -128,4 +128,4 @@ export default function AdvancedFilterValueField2({
|
|||||||
</Choose.Otherwise>
|
</Choose.Otherwise>
|
||||||
</Choose>
|
</Choose>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,36 @@ import { ReactQueryDevtools } from 'react-query/devtools';
|
|||||||
|
|
||||||
import 'style/App.scss';
|
import 'style/App.scss';
|
||||||
import 'moment/locale/ar-ly';
|
import 'moment/locale/ar-ly';
|
||||||
import 'moment/locale/es-us'
|
import 'moment/locale/es-us';
|
||||||
|
|
||||||
import AppIntlLoader from './AppIntlLoader';
|
import AppIntlLoader from './AppIntlLoader';
|
||||||
import PrivateRoute from 'components/Guards/PrivateRoute';
|
import PrivateRoute from 'components/Guards/PrivateRoute';
|
||||||
import GlobalErrors from 'containers/GlobalErrors/GlobalErrors';
|
import GlobalErrors from 'containers/GlobalErrors/GlobalErrors';
|
||||||
import DashboardPrivatePages from 'components/Dashboard/PrivatePages';
|
import DashboardPrivatePages from 'components/Dashboard/PrivatePages';
|
||||||
import Authentication from 'components/Authentication';
|
import Authentication from 'components/Authentication';
|
||||||
|
|
||||||
import { SplashScreen } from '../components';
|
import { SplashScreen } from '../components';
|
||||||
import { queryConfig } from '../hooks/query/base'
|
import { queryConfig } from '../hooks/query/base';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App inner.
|
||||||
|
*/
|
||||||
|
function AppInsider({ history }) {
|
||||||
|
return (
|
||||||
|
<div className="App">
|
||||||
|
<Router history={history}>
|
||||||
|
<Switch>
|
||||||
|
<Route path={'/auth'} component={Authentication} />
|
||||||
|
<Route path={'/'}>
|
||||||
|
<PrivateRoute component={DashboardPrivatePages} />
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
</Router>
|
||||||
|
|
||||||
|
<GlobalErrors />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core application.
|
* Core application.
|
||||||
@@ -31,21 +52,10 @@ export default function App() {
|
|||||||
<SplashScreen />
|
<SplashScreen />
|
||||||
|
|
||||||
<AppIntlLoader>
|
<AppIntlLoader>
|
||||||
<div className="App">
|
<AppInsider history={history} />
|
||||||
<Router history={history}>
|
|
||||||
<Switch>
|
|
||||||
<Route path={'/auth'} component={Authentication} />
|
|
||||||
<Route path={'/'}>
|
|
||||||
<PrivateRoute component={DashboardPrivatePages} />
|
|
||||||
</Route>
|
|
||||||
</Switch>
|
|
||||||
</Router>
|
|
||||||
|
|
||||||
<GlobalErrors />
|
|
||||||
</div>
|
|
||||||
</AppIntlLoader>
|
</AppIntlLoader>
|
||||||
|
|
||||||
<ReactQueryDevtools initialIsOpen />
|
<ReactQueryDevtools initialIsOpen />
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ import rtlDetect from 'rtl-detect';
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
|
|
||||||
import { AppIntlProvider } from './AppIntlProvider';
|
import { AppIntlProvider } from './AppIntlProvider';
|
||||||
|
import { useSplashLoading } from '../hooks/state';
|
||||||
|
|
||||||
|
import { useWatch } from '../hooks';
|
||||||
import withDashboardActions from '../containers/Dashboard/withDashboardActions';
|
import withDashboardActions from '../containers/Dashboard/withDashboardActions';
|
||||||
import withDashboard from '../containers/Dashboard/withDashboard';
|
|
||||||
|
|
||||||
const SUPPORTED_LOCALES = [
|
const SUPPORTED_LOCALES = [
|
||||||
{ name: 'English', value: 'en' },
|
{ name: 'English', value: 'en' },
|
||||||
@@ -63,20 +64,13 @@ function transformMomentLocale(currentLocale) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application Intl loader.
|
* Loads application locales of the given current locale.
|
||||||
|
* @param {string} currentLocale
|
||||||
|
* @returns {{ isLoading: boolean }}
|
||||||
*/
|
*/
|
||||||
function AppIntlLoader({ appIntlIsLoading, setAppIntlIsLoading, children }) {
|
function useAppLoadLocales(currentLocale) {
|
||||||
const [isLocalsLoading, setIsLocalsLoading] = React.useState(true);
|
const [startLoading, stopLoading] = useSplashLoading();
|
||||||
const [isYupLoading, setIsYupLoading] = React.useState(true);
|
const [isLoading, setIsLoading] = React.useState(true);
|
||||||
|
|
||||||
// Retrieve the current locale.
|
|
||||||
const currentLocale = getCurrentLocal();
|
|
||||||
|
|
||||||
// Detarmines the document direction based on the given locale.
|
|
||||||
const isRTL = rtlDetect.isRtlLang(currentLocale);
|
|
||||||
|
|
||||||
// Modifies the html document direction
|
|
||||||
useDocumentDirectionModifier(currentLocale, isRTL);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// Lodas the locales data file.
|
// Lodas the locales data file.
|
||||||
@@ -91,33 +85,72 @@ function AppIntlLoader({ appIntlIsLoading, setAppIntlIsLoading, children }) {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
moment.locale(transformMomentLocale(currentLocale));
|
moment.locale(transformMomentLocale(currentLocale));
|
||||||
setIsLocalsLoading(false);
|
setIsLoading(false);
|
||||||
});
|
});
|
||||||
}, [currentLocale, setIsLocalsLoading]);
|
}, [currentLocale, stopLoading]);
|
||||||
|
|
||||||
|
// Watches the value to start/stop splash screen.
|
||||||
|
useWatch(isLoading, (value) => (value ? startLoading() : stopLoading()), {
|
||||||
|
immediate: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { isLoading };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads application yup locales based on the given current locale.
|
||||||
|
* @param {string} currentLocale
|
||||||
|
* @returns {{ isLoading: boolean }}
|
||||||
|
*/
|
||||||
|
function useAppYupLoadLocales(currentLocale) {
|
||||||
|
const [startLoading, stopLoading] = useSplashLoading();
|
||||||
|
const [isLoading, setIsLoading] = React.useState(true);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
loadYupLocales(currentLocale)
|
loadYupLocales(currentLocale)
|
||||||
.then(({ locale }) => {
|
.then(({ locale }) => {
|
||||||
setLocale(locale);
|
setLocale(locale);
|
||||||
setIsYupLoading(false);
|
setIsLoading(false);
|
||||||
})
|
})
|
||||||
.then(() => {});
|
.then(() => {});
|
||||||
}, [currentLocale]);
|
}, [currentLocale, stopLoading]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
// Watches the valiue to start/stop splash screen.
|
||||||
if (!isLocalsLoading && !isYupLoading) {
|
useWatch(isLoading, (value) => (value ? startLoading() : stopLoading()), {
|
||||||
setAppIntlIsLoading(false);
|
immediate: true,
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return { isLoading };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application Intl loader.
|
||||||
|
*/
|
||||||
|
function AppIntlLoader({ children }) {
|
||||||
|
// Retrieve the current locale.
|
||||||
|
const currentLocale = getCurrentLocal();
|
||||||
|
|
||||||
|
// Detarmines the document direction based on the given locale.
|
||||||
|
const isRTL = rtlDetect.isRtlLang(currentLocale);
|
||||||
|
|
||||||
|
// Modifies the html document direction
|
||||||
|
useDocumentDirectionModifier(currentLocale, isRTL);
|
||||||
|
|
||||||
|
// Loads yup localization of the given locale.
|
||||||
|
const { isLoading: isAppYupLocalesLoading } =
|
||||||
|
useAppYupLoadLocales(currentLocale);
|
||||||
|
|
||||||
|
// Loads application locales of the given locale.
|
||||||
|
const { isLoading: isAppLocalesLoading } = useAppLoadLocales(currentLocale);
|
||||||
|
|
||||||
|
// Detarmines whether the app locales loading.
|
||||||
|
const isLoading = isAppYupLocalesLoading && isAppLocalesLoading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppIntlProvider currentLocale={currentLocale} isRTL={isRTL}>
|
<AppIntlProvider currentLocale={currentLocale} isRTL={isRTL}>
|
||||||
{appIntlIsLoading ? null : children}
|
{isLoading ? null : children}
|
||||||
</AppIntlProvider>
|
</AppIntlProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default R.compose(
|
export default R.compose(withDashboardActions)(AppIntlLoader);
|
||||||
withDashboardActions,
|
|
||||||
withDashboard(({ appIntlIsLoading }) => ({ appIntlIsLoading })),
|
|
||||||
)(AppIntlLoader);
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ function AppIntlProvider({ currentLocale, isRTL, children }) {
|
|||||||
currentLocale,
|
currentLocale,
|
||||||
isRTL,
|
isRTL,
|
||||||
isLTR: !isRTL,
|
isLTR: !isRTL,
|
||||||
|
direction: isRTL ? 'rtl' : 'ltr',
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import authenticationRoutes from 'routes/authentication';
|
|||||||
import { FormattedMessage as T } from 'components';
|
import { FormattedMessage as T } from 'components';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import { useIsAuthenticated } from 'hooks/state';
|
import { useIsAuthenticated } from 'hooks/state';
|
||||||
import {AuthenticationBoot} from '../containers/Authentication/AuthenticationBoot';
|
|
||||||
import 'style/pages/Authentication/Auth.scss';
|
import 'style/pages/Authentication/Auth.scss';
|
||||||
|
|
||||||
function PageFade(props) {
|
function PageFade(props) {
|
||||||
@@ -26,7 +25,6 @@ export default function AuthenticationWrapper({ ...rest }) {
|
|||||||
) : (
|
) : (
|
||||||
<BodyClassName className={'authentication'}>
|
<BodyClassName className={'authentication'}>
|
||||||
<div class="authentication-page">
|
<div class="authentication-page">
|
||||||
<AuthenticationBoot />
|
|
||||||
<a
|
<a
|
||||||
href={'http://bigcapital.ly'}
|
href={'http://bigcapital.ly'}
|
||||||
className={'authentication-page__goto-bigcapital'}
|
className={'authentication-page__goto-bigcapital'}
|
||||||
|
|||||||
10
src/components/AvaterCell.js
Normal file
10
src/components/AvaterCell.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { firstLettersArgs } from 'utils';
|
||||||
|
|
||||||
|
export default function AvatarCell({ row: { original }, size }) {
|
||||||
|
return (
|
||||||
|
<span className="avatar" data-size={size}>
|
||||||
|
{firstLettersArgs(original?.display_name)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export default function Card({ className, children }) {
|
export default function Card({ className, children }) {
|
||||||
return <div className={classNames('card', className)}>{children}</div>;
|
return <div className={classNames('card', className)}>{children}</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,30 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
|
|
||||||
import { useUser, useCurrentOrganization } from 'hooks/query';
|
import { useUser, useCurrentOrganization } from '../../hooks/query';
|
||||||
|
import { useSplashLoading } from '../../hooks/state';
|
||||||
|
import { useWatch, useWhen } from '../../hooks';
|
||||||
|
|
||||||
import withAuthentication from '../../containers/Authentication/withAuthentication';
|
import withAuthentication from '../../containers/Authentication/withAuthentication';
|
||||||
import withDashboardActions from '../../containers/Dashboard/withDashboardActions';
|
|
||||||
|
|
||||||
import { setCookie, getCookie } from '../../utils';
|
import { setCookie, getCookie } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dashboard async booting.
|
* Dashboard async booting.
|
||||||
*/
|
*/
|
||||||
function DashboardBootJSX({ setAppIsLoading, authenticatedUserId }) {
|
function DashboardBootJSX({ authenticatedUserId }) {
|
||||||
// Fetches the current user's organization.
|
// Fetches the current user's organization.
|
||||||
const { isSuccess: isCurrentOrganizationSuccess, data: organization } =
|
const {
|
||||||
useCurrentOrganization();
|
isSuccess: isCurrentOrganizationSuccess,
|
||||||
|
isLoading: isOrgLoading,
|
||||||
|
data: organization,
|
||||||
|
} = useCurrentOrganization();
|
||||||
|
|
||||||
// Authenticated user.
|
// Authenticated user.
|
||||||
const { isSuccess: isAuthUserSuccess, data: authUser } =
|
const {
|
||||||
useUser(authenticatedUserId);
|
isSuccess: isAuthUserSuccess,
|
||||||
|
isLoading: isAuthUserLoading,
|
||||||
|
} = useUser(authenticatedUserId);
|
||||||
|
|
||||||
// Initial locale cookie value.
|
// Initial locale cookie value.
|
||||||
const localeCookie = getCookie('locale');
|
const localeCookie = getCookie('locale');
|
||||||
@@ -48,23 +55,39 @@ function DashboardBootJSX({ setAppIsLoading, authenticatedUserId }) {
|
|||||||
}
|
}
|
||||||
}, [localeCookie, organization]);
|
}, [localeCookie, organization]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
const [startLoading, stopLoading] = useSplashLoading();
|
||||||
// Once the all requests complete change the app loading state.
|
|
||||||
if (
|
// Splash loading when organization request loading and
|
||||||
isAuthUserSuccess &&
|
// applicaiton still not booted.
|
||||||
|
useWatch(isOrgLoading, (value) => {
|
||||||
|
value && !isBooted.current && startLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Splash loading when request authenticated user loading and
|
||||||
|
// application still not booted yet.
|
||||||
|
useWatch(isAuthUserLoading, (value) => {
|
||||||
|
value && !isBooted.current && startLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Stop splash loading once organization request success.
|
||||||
|
useWatch(isCurrentOrganizationSuccess, (value) => {
|
||||||
|
value && stopLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Stop splash loading once authenticated user request success.
|
||||||
|
useWatch(isAuthUserSuccess, (value) => {
|
||||||
|
value && stopLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Once the all requests complete change the app loading state.
|
||||||
|
useWhen(
|
||||||
|
isAuthUserSuccess &&
|
||||||
isCurrentOrganizationSuccess &&
|
isCurrentOrganizationSuccess &&
|
||||||
localeCookie === organization?.metadata?.language
|
localeCookie === organization?.metadata?.language,
|
||||||
) {
|
() => {
|
||||||
setAppIsLoading(false);
|
|
||||||
isBooted.current = true;
|
isBooted.current = true;
|
||||||
}
|
},
|
||||||
}, [
|
);
|
||||||
isAuthUserSuccess,
|
|
||||||
isCurrentOrganizationSuccess,
|
|
||||||
organization,
|
|
||||||
setAppIsLoading,
|
|
||||||
localeCookie,
|
|
||||||
]);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,5 +95,4 @@ export const DashboardBoot = R.compose(
|
|||||||
withAuthentication(({ authenticatedUserId }) => ({
|
withAuthentication(({ authenticatedUserId }) => ({
|
||||||
authenticatedUserId,
|
authenticatedUserId,
|
||||||
})),
|
})),
|
||||||
withDashboardActions,
|
|
||||||
)(DashboardBootJSX);
|
)(DashboardBootJSX);
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
PopoverInteractionKind,
|
|
||||||
Popover,
|
|
||||||
Menu,
|
|
||||||
MenuItem,
|
|
||||||
MenuDivider,
|
|
||||||
Classes
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import { Icon } from 'components';
|
|
||||||
|
|
||||||
export function DashboardRowsHeightButton() {
|
|
||||||
return (
|
|
||||||
<Popover
|
|
||||||
minimal={true}
|
|
||||||
content={
|
|
||||||
<Menu>
|
|
||||||
<MenuDivider title={'Rows height'} />
|
|
||||||
<MenuItem text="Compact" />
|
|
||||||
<MenuItem text="Medium" />
|
|
||||||
</Menu>
|
|
||||||
}
|
|
||||||
placement="bottom-start"
|
|
||||||
modifiers={{
|
|
||||||
offset: { offset: '0, 4' },
|
|
||||||
}}
|
|
||||||
interactionKind={PopoverInteractionKind.CLICK}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
className={Classes.MINIMAL}
|
|
||||||
icon={<Icon icon="rows-height" iconSize={16} />}
|
|
||||||
/>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
70
src/components/Dashboard/DashboardRowsHeightButton/index.js
Normal file
70
src/components/Dashboard/DashboardRowsHeightButton/index.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
PopoverInteractionKind,
|
||||||
|
Popover,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
MenuDivider,
|
||||||
|
Classes,
|
||||||
|
Tooltip,
|
||||||
|
Position,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
|
import clsx from 'classnames';
|
||||||
|
import { Icon, T } from 'components';
|
||||||
|
|
||||||
|
import Style from './style.module.scss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dashboard rows height button control.
|
||||||
|
*/
|
||||||
|
export function DashboardRowsHeightButton({ initialValue, value, onChange }) {
|
||||||
|
const [localSize, setLocalSize] = React.useState(initialValue);
|
||||||
|
|
||||||
|
// Handle menu item click.
|
||||||
|
const handleItemClick = (size) => (event) => {
|
||||||
|
setLocalSize(size);
|
||||||
|
onChange && onChange(size, event);
|
||||||
|
};
|
||||||
|
// Button icon name.
|
||||||
|
const btnIcon = `table-row-${localSize}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
minimal={true}
|
||||||
|
content={
|
||||||
|
<Menu className={Style.menu}>
|
||||||
|
<MenuDivider title={<T id={'dashboard.rows_height'} />} />
|
||||||
|
<MenuItem
|
||||||
|
onClick={handleItemClick('small')}
|
||||||
|
text={<T id={'dashboard.row_small'} />}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
onClick={handleItemClick('medium')}
|
||||||
|
text={<T id={'dashboard.row_medium'} />}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
placement="bottom-start"
|
||||||
|
modifiers={{
|
||||||
|
offset: { offset: '0, 4' },
|
||||||
|
}}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
content={<T id={'dashboard.rows_height'} />}
|
||||||
|
minimal={true}
|
||||||
|
position={Position.BOTTOM}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className={clsx(Classes.MINIMAL, Style.button)}
|
||||||
|
icon={<Icon icon={btnIcon} iconSize={16} />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DashboardRowsHeightButton.defaultProps = {
|
||||||
|
initialValue: 'medium',
|
||||||
|
};
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
.menu{
|
||||||
|
:global .bp3-heading{
|
||||||
|
font-weight: 400;
|
||||||
|
opacity: 0.5;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button{
|
||||||
|
min-width: 34px;
|
||||||
|
}
|
||||||
@@ -4,10 +4,9 @@ import { Switch, Route } from 'react-router';
|
|||||||
import Dashboard from 'components/Dashboard/Dashboard';
|
import Dashboard from 'components/Dashboard/Dashboard';
|
||||||
import SetupWizardPage from 'containers/Setup/WizardSetupPage';
|
import SetupWizardPage from 'containers/Setup/WizardSetupPage';
|
||||||
|
|
||||||
import EnsureOrganizationIsReady from 'components/Guards/EnsureOrganizationIsReady';
|
import EnsureOrganizationIsReady from '../../components/Guards/EnsureOrganizationIsReady';
|
||||||
import EnsureOrganizationIsNotReady from 'components/Guards/EnsureOrganizationIsNotReady';
|
import EnsureOrganizationIsNotReady from '../../components/Guards/EnsureOrganizationIsNotReady';
|
||||||
import { PrivatePagesProvider } from './PrivatePagesProvider';
|
import { PrivatePagesProvider } from './PrivatePagesProvider';
|
||||||
import { DashboardBoot } from '../../components';
|
|
||||||
|
|
||||||
import 'style/pages/Dashboard/Dashboard.scss';
|
import 'style/pages/Dashboard/Dashboard.scss';
|
||||||
|
|
||||||
@@ -17,8 +16,6 @@ import 'style/pages/Dashboard/Dashboard.scss';
|
|||||||
export default function DashboardPrivatePages() {
|
export default function DashboardPrivatePages() {
|
||||||
return (
|
return (
|
||||||
<PrivatePagesProvider>
|
<PrivatePagesProvider>
|
||||||
<DashboardBoot />
|
|
||||||
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path={'/setup'}>
|
<Route path={'/setup'}>
|
||||||
<EnsureOrganizationIsNotReady>
|
<EnsureOrganizationIsNotReady>
|
||||||
|
|||||||
@@ -1,9 +1,31 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
|
||||||
import { AuthenticatedUser } from './AuthenticatedUser';
|
import { AuthenticatedUser } from './AuthenticatedUser';
|
||||||
|
import { DashboardBoot } from '../../components';
|
||||||
|
|
||||||
|
import withDashboard from '../../containers/Dashboard/withDashboard';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private pages provider.
|
* Private pages provider.
|
||||||
*/
|
*/
|
||||||
export function PrivatePagesProvider({ children }) {
|
function PrivatePagesProviderComponent({
|
||||||
return <AuthenticatedUser>{children}</AuthenticatedUser>;
|
splashScreenCompleted,
|
||||||
|
|
||||||
|
// #ownProps
|
||||||
|
children,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<AuthenticatedUser>
|
||||||
|
<DashboardBoot />
|
||||||
|
|
||||||
|
{splashScreenCompleted ? children : null}
|
||||||
|
</AuthenticatedUser>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const PrivatePagesProvider = R.compose(
|
||||||
|
withDashboard(({ splashScreenCompleted }) => ({
|
||||||
|
splashScreenCompleted,
|
||||||
|
})),
|
||||||
|
)(PrivatePagesProviderComponent);
|
||||||
|
|||||||
@@ -3,13 +3,12 @@ import * as R from 'ramda';
|
|||||||
import BigcapitalLoading from './BigcapitalLoading';
|
import BigcapitalLoading from './BigcapitalLoading';
|
||||||
import withDashboard from '../../containers/Dashboard/withDashboard';
|
import withDashboard from '../../containers/Dashboard/withDashboard';
|
||||||
|
|
||||||
function SplashScreenComponent({ appIsLoading, appIntlIsLoading }) {
|
function SplashScreenComponent({ splashScreenLoading }) {
|
||||||
return appIsLoading || appIntlIsLoading ? <BigcapitalLoading /> : null;
|
return splashScreenLoading ? <BigcapitalLoading /> : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SplashScreen = R.compose(
|
export const SplashScreen = R.compose(
|
||||||
withDashboard(({ appIsLoading, appIntlIsLoading }) => ({
|
withDashboard(({ splashScreenLoading }) => ({
|
||||||
appIsLoading,
|
splashScreenLoading,
|
||||||
appIntlIsLoading,
|
|
||||||
})),
|
})),
|
||||||
)(SplashScreenComponent);
|
)(SplashScreenComponent);
|
||||||
|
|||||||
@@ -196,6 +196,9 @@ export default function DataTable(props) {
|
|||||||
|
|
||||||
DataTable.defaultProps = {
|
DataTable.defaultProps = {
|
||||||
pagination: false,
|
pagination: false,
|
||||||
|
hidePaginationNoPages: true,
|
||||||
|
|
||||||
|
size: null,
|
||||||
spinnerProps: { size: 30 },
|
spinnerProps: { size: 30 },
|
||||||
|
|
||||||
expandToggleColumn: 1,
|
expandToggleColumn: 1,
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import { If } from 'components';
|
|||||||
import { Skeleton } from 'components';
|
import { Skeleton } from 'components';
|
||||||
import { useAppIntlContext } from 'components/AppIntlProvider';
|
import { useAppIntlContext } from 'components/AppIntlProvider';
|
||||||
import TableContext from './TableContext';
|
import TableContext from './TableContext';
|
||||||
import { saveInvoke } from 'utils';
|
import { saveInvoke, ignoreEventFromSelectors } from 'utils';
|
||||||
import { isCellLoading } from './utils';
|
import { isCellLoading } from './utils';
|
||||||
|
|
||||||
|
const ROW_CLICK_SELECTORS_INGORED = ['.expand-toggle', '.selection-checkbox'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table cell.
|
* Table cell.
|
||||||
*/
|
*/
|
||||||
@@ -50,6 +52,9 @@ export default function TableCell({ cell, row, index }) {
|
|||||||
}
|
}
|
||||||
// Handle cell click action.
|
// Handle cell click action.
|
||||||
const handleCellClick = (event) => {
|
const handleCellClick = (event) => {
|
||||||
|
if (ignoreEventFromSelectors(event, ROW_CLICK_SELECTORS_INGORED)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
saveInvoke(onCellClick, cell, event);
|
saveInvoke(onCellClick, cell, event);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -58,7 +63,7 @@ export default function TableCell({ cell, row, index }) {
|
|||||||
{...cell.getCellProps({
|
{...cell.getCellProps({
|
||||||
className: classNames(cell.column.className, 'td', {
|
className: classNames(cell.column.className, 'td', {
|
||||||
'is-text-overview': cell.column.textOverview,
|
'is-text-overview': cell.column.textOverview,
|
||||||
'clickable': cell.column.clickable,
|
clickable: cell.column.clickable,
|
||||||
'align-right': cell.column.align === 'right',
|
'align-right': cell.column.align === 'right',
|
||||||
}),
|
}),
|
||||||
onClick: handleCellClick,
|
onClick: handleCellClick,
|
||||||
@@ -83,11 +88,15 @@ export default function TableCell({ cell, row, index }) {
|
|||||||
// to build the toggle for expanding a row
|
// to build the toggle for expanding a row
|
||||||
}
|
}
|
||||||
<If condition={cell.row.canExpand && expandable && isExpandColumn}>
|
<If condition={cell.row.canExpand && expandable && isExpandColumn}>
|
||||||
<span {...getToggleRowExpandedProps({ className: 'expand-toggle' })}>
|
<span
|
||||||
|
{...getToggleRowExpandedProps({
|
||||||
|
className: 'expand-toggle',
|
||||||
|
})}
|
||||||
|
style={{}}
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
className={classNames({
|
className={classNames('expand-arrow', {
|
||||||
'arrow-down': isExpanded,
|
'is-expanded': isExpanded,
|
||||||
'arrow-right': !isExpanded,
|
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Checkbox } from '@blueprintjs/core';
|
|||||||
|
|
||||||
export default function TableIndeterminateCheckboxRow({ row }) {
|
export default function TableIndeterminateCheckboxRow({ row }) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class="selection-checkbox">
|
||||||
<Checkbox {...row.getToggleRowSelectedProps()} />
|
<Checkbox {...row.getToggleRowSelectedProps()} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,12 +14,15 @@ export default function TablePagination() {
|
|||||||
pageCount,
|
pageCount,
|
||||||
state: { pageIndex, pageSize },
|
state: { pageIndex, pageSize },
|
||||||
},
|
},
|
||||||
props: { pagination, loading, onPaginationChange },
|
props: { pagination, loading, onPaginationChange, hidePaginationNoPages },
|
||||||
} = useContext(TableContext);
|
} = useContext(TableContext);
|
||||||
|
|
||||||
const triggerOnPaginationChange = useCallback((payload) => {
|
const triggerOnPaginationChange = useCallback(
|
||||||
saveInvoke(onPaginationChange, payload)
|
(payload) => {
|
||||||
}, [onPaginationChange]);
|
saveInvoke(onPaginationChange, payload);
|
||||||
|
},
|
||||||
|
[onPaginationChange],
|
||||||
|
);
|
||||||
|
|
||||||
// Handles the page changing.
|
// Handles the page changing.
|
||||||
const handlePageChange = useCallback(
|
const handlePageChange = useCallback(
|
||||||
@@ -45,8 +48,14 @@ export default function TablePagination() {
|
|||||||
[gotoPage, setPageSize, triggerOnPaginationChange],
|
[gotoPage, setPageSize, triggerOnPaginationChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Detarmines when display the pagination.
|
||||||
|
const showPagination =
|
||||||
|
pagination &&
|
||||||
|
((hidePaginationNoPages && pageCount > 1) || !hidePaginationNoPages) &&
|
||||||
|
!loading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<If condition={pagination && !loading}>
|
showPagination && (
|
||||||
<Pagination
|
<Pagination
|
||||||
currentPage={pageIndex + 1}
|
currentPage={pageIndex + 1}
|
||||||
total={pageSize * pageCount}
|
total={pageSize * pageCount}
|
||||||
@@ -54,6 +63,6 @@ export default function TablePagination() {
|
|||||||
onPageChange={handlePageChange}
|
onPageChange={handlePageChange}
|
||||||
onPageSizeChange={handlePageSizeChange}
|
onPageSizeChange={handlePageSizeChange}
|
||||||
/>
|
/>
|
||||||
</If>
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import classNames from 'classnames';
|
import clsx from 'classnames';
|
||||||
import { ScrollSync } from 'react-scroll-sync';
|
import { ScrollSync } from 'react-scroll-sync';
|
||||||
import TableContext from './TableContext';
|
import TableContext from './TableContext';
|
||||||
|
|
||||||
@@ -9,12 +9,20 @@ import TableContext from './TableContext';
|
|||||||
export default function TableWrapper({ children }) {
|
export default function TableWrapper({ children }) {
|
||||||
const {
|
const {
|
||||||
table: { getTableProps },
|
table: { getTableProps },
|
||||||
props: { sticky, pagination, loading, expandable, virtualizedRows, className },
|
props: {
|
||||||
|
sticky,
|
||||||
|
pagination,
|
||||||
|
loading,
|
||||||
|
expandable,
|
||||||
|
virtualizedRows,
|
||||||
|
className,
|
||||||
|
size,
|
||||||
|
},
|
||||||
} = useContext(TableContext);
|
} = useContext(TableContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames('bigcapital-datatable', className, {
|
className={clsx('bigcapital-datatable', className, {
|
||||||
'has-sticky': sticky,
|
'has-sticky': sticky,
|
||||||
'has-pagination': pagination,
|
'has-pagination': pagination,
|
||||||
'is-expandable': expandable,
|
'is-expandable': expandable,
|
||||||
@@ -25,7 +33,9 @@ export default function TableWrapper({ children }) {
|
|||||||
<ScrollSync>
|
<ScrollSync>
|
||||||
<div
|
<div
|
||||||
{...getTableProps({ style: { minWidth: 'none' } })}
|
{...getTableProps({ style: { minWidth: 'none' } })}
|
||||||
className="table"
|
className={clsx('table', {
|
||||||
|
[`table-size--${size}`]: size,
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { compose } from 'utils';
|
|||||||
import withAuthentication from 'containers/Authentication/withAuthentication';
|
import withAuthentication from 'containers/Authentication/withAuthentication';
|
||||||
import withOrganization from 'containers/Organization/withOrganization';
|
import withOrganization from 'containers/Organization/withOrganization';
|
||||||
|
|
||||||
|
|
||||||
function EnsureOrganizationIsReady({
|
function EnsureOrganizationIsReady({
|
||||||
// #ownProps
|
// #ownProps
|
||||||
children,
|
children,
|
||||||
@@ -15,10 +14,10 @@ function EnsureOrganizationIsReady({
|
|||||||
// #withOrganizationByOrgId
|
// #withOrganizationByOrgId
|
||||||
isOrganizationReady,
|
isOrganizationReady,
|
||||||
}) {
|
}) {
|
||||||
return (isOrganizationReady) ? children : (
|
return isOrganizationReady ? (
|
||||||
<Redirect
|
children
|
||||||
to={{ pathname: redirectTo }}
|
) : (
|
||||||
/>
|
<Redirect to={{ pathname: redirectTo }} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,4 +27,4 @@ export default compose(
|
|||||||
organizationId: props.currentOrganizationId,
|
organizationId: props.currentOrganizationId,
|
||||||
})),
|
})),
|
||||||
withOrganization(({ isOrganizationReady }) => ({ isOrganizationReady })),
|
withOrganization(({ isOrganizationReady }) => ({ isOrganizationReady })),
|
||||||
)(EnsureOrganizationIsReady);
|
)(EnsureOrganizationIsReady);
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ function Pagination({
|
|||||||
currentPage,
|
currentPage,
|
||||||
total,
|
total,
|
||||||
size,
|
size,
|
||||||
pageSizesOptions = [5, 12, 20, 30, 50, 75, 100, 150],
|
pageSizesOptions = [20, 30, 50, 75, 100, 150],
|
||||||
onPageChange,
|
onPageChange,
|
||||||
onPageSizeChange,
|
onPageSizeChange,
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ function UniversalSearchBar({ isOpen, onSearchTypeChange, ...listProps }) {
|
|||||||
{...handlers}
|
{...handlers}
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
autoFocus={true}
|
|
||||||
large={true}
|
large={true}
|
||||||
leftIcon={<Icon icon={'universal-search'} iconSize={20} />}
|
leftIcon={<Icon icon={'universal-search'} iconSize={20} />}
|
||||||
placeholder={intl.get('universal_search.placeholder')}
|
placeholder={intl.get('universal_search.placeholder')}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ import AccountsSuggestField from './AccountsSuggestField';
|
|||||||
import MaterialProgressBar from './MaterialProgressBar';
|
import MaterialProgressBar from './MaterialProgressBar';
|
||||||
import { MoneyFieldCell } from './DataTableCells';
|
import { MoneyFieldCell } from './DataTableCells';
|
||||||
import Card from './Card';
|
import Card from './Card';
|
||||||
|
import AvaterCell from './AvaterCell';
|
||||||
|
|
||||||
import { ItemsMultiSelect } from './Items';
|
import { ItemsMultiSelect } from './Items';
|
||||||
|
|
||||||
@@ -71,13 +72,13 @@ export * from './PdfPreview';
|
|||||||
export * from './Details';
|
export * from './Details';
|
||||||
export * from './Drawer/DrawerInsider';
|
export * from './Drawer/DrawerInsider';
|
||||||
export * from './Drawer/DrawerMainTabs';
|
export * from './Drawer/DrawerMainTabs';
|
||||||
export * from './TotalLines/index'
|
export * from './TotalLines/index';
|
||||||
export * from './Alert';
|
export * from './Alert';
|
||||||
export * from './Subscriptions';
|
export * from './Subscriptions';
|
||||||
export * from './Dashboard';
|
export * from './Dashboard';
|
||||||
export * from './Drawer';
|
export * from './Drawer';
|
||||||
export * from './Forms';
|
export * from './Forms';
|
||||||
export * from './MultiSelectTaggable'
|
export * from './MultiSelectTaggable';
|
||||||
export * from './Utils/FormatNumber';
|
export * from './Utils/FormatNumber';
|
||||||
export * from './Utils/FormatDate';
|
export * from './Utils/FormatDate';
|
||||||
|
|
||||||
@@ -150,4 +151,5 @@ export {
|
|||||||
MoneyFieldCell,
|
MoneyFieldCell,
|
||||||
ItemsMultiSelect,
|
ItemsMultiSelect,
|
||||||
Card,
|
Card,
|
||||||
|
AvaterCell,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import {
|
import {
|
||||||
AdvancedFilterPopover,
|
AdvancedFilterPopover,
|
||||||
DashboardFilterButton,
|
DashboardFilterButton,
|
||||||
|
DashboardRowsHeightButton,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
|
|
||||||
@@ -22,6 +23,8 @@ import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
|||||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||||
import withManualJournalsActions from './withManualJournalsActions';
|
import withManualJournalsActions from './withManualJournalsActions';
|
||||||
import withManualJournals from './withManualJournals';
|
import withManualJournals from './withManualJournals';
|
||||||
|
import withSettingsActions from '../../Settings/withSettingsActions';
|
||||||
|
import withSettings from '../../Settings/withSettings';
|
||||||
|
|
||||||
import { If, DashboardActionViewsList } from 'components';
|
import { If, DashboardActionViewsList } from 'components';
|
||||||
|
|
||||||
@@ -36,6 +39,12 @@ function ManualJournalActionsBar({
|
|||||||
|
|
||||||
// #withManualJournals
|
// #withManualJournals
|
||||||
manualJournalsFilterConditions,
|
manualJournalsFilterConditions,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
manualJournalsTableSize,
|
||||||
|
|
||||||
|
// #withSettingsActions
|
||||||
|
addSetting,
|
||||||
}) {
|
}) {
|
||||||
// History context.
|
// History context.
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -62,6 +71,11 @@ function ManualJournalActionsBar({
|
|||||||
refresh();
|
refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle table row size change.
|
||||||
|
const handleTableRowSizeChange = (size) => {
|
||||||
|
addSetting('manualJournals', 'tableSize', size);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -119,6 +133,12 @@ function ManualJournalActionsBar({
|
|||||||
icon={<Icon icon="file-export-16" iconSize={16} />}
|
icon={<Icon icon="file-export-16" iconSize={16} />}
|
||||||
text={<T id={'export'} />}
|
text={<T id={'export'} />}
|
||||||
/>
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
|
<DashboardRowsHeightButton
|
||||||
|
initialValue={manualJournalsTableSize}
|
||||||
|
onChange={handleTableRowSizeChange}
|
||||||
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
</NavbarGroup>
|
</NavbarGroup>
|
||||||
<NavbarGroup align={Alignment.RIGHT}>
|
<NavbarGroup align={Alignment.RIGHT}>
|
||||||
<Button
|
<Button
|
||||||
@@ -134,7 +154,11 @@ function ManualJournalActionsBar({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withDialogActions,
|
withDialogActions,
|
||||||
withManualJournalsActions,
|
withManualJournalsActions,
|
||||||
|
withSettingsActions,
|
||||||
withManualJournals(({ manualJournalsTableState }) => ({
|
withManualJournals(({ manualJournalsTableState }) => ({
|
||||||
manualJournalsFilterConditions: manualJournalsTableState.filterRoles,
|
manualJournalsFilterConditions: manualJournalsTableState.filterRoles,
|
||||||
})),
|
})),
|
||||||
|
withSettings(({ manualJournalsSettings }) => ({
|
||||||
|
manualJournalsTableSize: manualJournalsSettings?.tableSize,
|
||||||
|
})),
|
||||||
)(ManualJournalActionsBar);
|
)(ManualJournalActionsBar);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import withManualJournals from './withManualJournals';
|
|||||||
import withManualJournalsActions from './withManualJournalsActions';
|
import withManualJournalsActions from './withManualJournalsActions';
|
||||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
import withSettings from '../../Settings/withSettings';
|
||||||
|
|
||||||
import { useManualJournalsContext } from './ManualJournalsListProvider';
|
import { useManualJournalsContext } from './ManualJournalsListProvider';
|
||||||
import { useMemorizedColumnsWidths } from 'hooks';
|
import { useMemorizedColumnsWidths } from 'hooks';
|
||||||
@@ -38,6 +39,9 @@ function ManualJournalsDataTable({
|
|||||||
|
|
||||||
// #ownProps
|
// #ownProps
|
||||||
onSelectedRowsChange,
|
onSelectedRowsChange,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
manualJournalsTableSize,
|
||||||
}) {
|
}) {
|
||||||
// Manual journals context.
|
// Manual journals context.
|
||||||
const {
|
const {
|
||||||
@@ -109,7 +113,6 @@ function ManualJournalsDataTable({
|
|||||||
data={manualJournals}
|
data={manualJournals}
|
||||||
manualSortBy={true}
|
manualSortBy={true}
|
||||||
selectionColumn={true}
|
selectionColumn={true}
|
||||||
expandable={true}
|
|
||||||
sticky={true}
|
sticky={true}
|
||||||
loading={isManualJournalsLoading}
|
loading={isManualJournalsLoading}
|
||||||
headerLoading={isManualJournalsLoading}
|
headerLoading={isManualJournalsLoading}
|
||||||
@@ -125,6 +128,7 @@ function ManualJournalsDataTable({
|
|||||||
onCellClick={handleCellClick}
|
onCellClick={handleCellClick}
|
||||||
initialColumnsWidths={initialColumnsWidths}
|
initialColumnsWidths={initialColumnsWidths}
|
||||||
onColumnResizing={handleColumnResizing}
|
onColumnResizing={handleColumnResizing}
|
||||||
|
size={manualJournalsTableSize}
|
||||||
payload={{
|
payload={{
|
||||||
onDelete: handleDeleteJournal,
|
onDelete: handleDeleteJournal,
|
||||||
onPublish: handlePublishJournal,
|
onPublish: handlePublishJournal,
|
||||||
@@ -143,4 +147,7 @@ export default compose(
|
|||||||
})),
|
})),
|
||||||
withAlertsActions,
|
withAlertsActions,
|
||||||
withDrawerActions,
|
withDrawerActions,
|
||||||
|
withSettings(({ manualJournalsSettings }) => ({
|
||||||
|
manualJournalsTableSize: manualJournalsSettings?.tableSize,
|
||||||
|
})),
|
||||||
)(ManualJournalsDataTable);
|
)(ManualJournalsDataTable);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export const useManualJournalsColumns = () => {
|
|||||||
className: 'journal_number',
|
className: 'journal_number',
|
||||||
width: 100,
|
width: 100,
|
||||||
clickable: true,
|
clickable: true,
|
||||||
|
textOverview: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'journal_type',
|
id: 'journal_type',
|
||||||
@@ -44,6 +45,7 @@ export const useManualJournalsColumns = () => {
|
|||||||
accessor: 'journal_type',
|
accessor: 'journal_type',
|
||||||
width: 110,
|
width: 110,
|
||||||
clickable: true,
|
clickable: true,
|
||||||
|
textOverview: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'status',
|
id: 'status',
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
If,
|
If,
|
||||||
DashboardActionViewsList,
|
DashboardActionViewsList,
|
||||||
DashboardFilterButton,
|
DashboardFilterButton,
|
||||||
|
DashboardRowsHeightButton,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
|
|
||||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||||
@@ -27,7 +28,8 @@ import withDialogActions from 'containers/Dialog/withDialogActions';
|
|||||||
import withAccounts from 'containers/Accounts/withAccounts';
|
import withAccounts from 'containers/Accounts/withAccounts';
|
||||||
import withAlertActions from 'containers/Alert/withAlertActions';
|
import withAlertActions from 'containers/Alert/withAlertActions';
|
||||||
import withAccountsTableActions from './withAccountsTableActions';
|
import withAccountsTableActions from './withAccountsTableActions';
|
||||||
|
import withSettings from '../Settings/withSettings';
|
||||||
|
import withSettingsActions from '../Settings/withSettingsActions';
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,6 +52,12 @@ function AccountsActionsBar({
|
|||||||
|
|
||||||
// #ownProps
|
// #ownProps
|
||||||
onFilterChanged,
|
onFilterChanged,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
accountsTableSize,
|
||||||
|
|
||||||
|
// #withSettingsActions
|
||||||
|
addSetting,
|
||||||
}) {
|
}) {
|
||||||
const { resourceViews, fields } = useAccountsChartContext();
|
const { resourceViews, fields } = useAccountsChartContext();
|
||||||
|
|
||||||
@@ -93,6 +101,10 @@ function AccountsActionsBar({
|
|||||||
refresh();
|
refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle table row size change.
|
||||||
|
const handleTableRowSizeChange = (size) => {
|
||||||
|
addSetting('accounts', 'tableSize', size);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -165,6 +177,12 @@ function AccountsActionsBar({
|
|||||||
icon={<Icon icon="file-import-16" iconSize={16} />}
|
icon={<Icon icon="file-import-16" iconSize={16} />}
|
||||||
text={<T id={'import'} />}
|
text={<T id={'import'} />}
|
||||||
/>
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
|
<DashboardRowsHeightButton
|
||||||
|
initialValue={accountsTableSize}
|
||||||
|
onChange={handleTableRowSizeChange}
|
||||||
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
<Switch
|
<Switch
|
||||||
labelElement={<T id={'inactive'} />}
|
labelElement={<T id={'inactive'} />}
|
||||||
defaultChecked={accountsInactiveMode}
|
defaultChecked={accountsInactiveMode}
|
||||||
@@ -185,10 +203,14 @@ function AccountsActionsBar({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withDialogActions,
|
withDialogActions,
|
||||||
withAlertActions,
|
withAlertActions,
|
||||||
|
withSettingsActions,
|
||||||
withAccounts(({ accountsSelectedRows, accountsTableState }) => ({
|
withAccounts(({ accountsSelectedRows, accountsTableState }) => ({
|
||||||
accountsSelectedRows,
|
accountsSelectedRows,
|
||||||
accountsInactiveMode: accountsTableState.inactiveMode,
|
accountsInactiveMode: accountsTableState.inactiveMode,
|
||||||
accountsFilterConditions: accountsTableState.filterRoles,
|
accountsFilterConditions: accountsTableState.filterRoles,
|
||||||
})),
|
})),
|
||||||
|
withSettings(({ accountsSettings }) => ({
|
||||||
|
accountsTableSize: accountsSettings.tableSize,
|
||||||
|
})),
|
||||||
withAccountsTableActions,
|
withAccountsTableActions,
|
||||||
)(AccountsActionsBar);
|
)(AccountsActionsBar);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { TABLES } from 'common/tables';
|
|||||||
import TableVirtualizedListRows from 'components/Datatable/TableVirtualizedRows';
|
import TableVirtualizedListRows from 'components/Datatable/TableVirtualizedRows';
|
||||||
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
|
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
|
||||||
import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
|
import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
|
||||||
|
import withSettings from '../Settings/withSettings';
|
||||||
|
|
||||||
import { useAccountsChartContext } from './AccountsChartProvider';
|
import { useAccountsChartContext } from './AccountsChartProvider';
|
||||||
import { useMemorizedColumnsWidths } from '../../hooks';
|
import { useMemorizedColumnsWidths } from '../../hooks';
|
||||||
@@ -30,6 +31,9 @@ function AccountsDataTable({
|
|||||||
|
|
||||||
// #withDrawerActions
|
// #withDrawerActions
|
||||||
openDrawer,
|
openDrawer,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
accountsTableSize,
|
||||||
}) {
|
}) {
|
||||||
const { isAccountsLoading, isAccountsFetching, accounts } =
|
const { isAccountsLoading, isAccountsFetching, accounts } =
|
||||||
useAccountsChartContext();
|
useAccountsChartContext();
|
||||||
@@ -102,11 +106,12 @@ function AccountsDataTable({
|
|||||||
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
||||||
ContextMenu={ActionsMenu}
|
ContextMenu={ActionsMenu}
|
||||||
// #TableVirtualizedListRows props.
|
// #TableVirtualizedListRows props.
|
||||||
vListrowHeight={42}
|
vListrowHeight={accountsTableSize == 'small' ? 40 : 42}
|
||||||
vListOverscanRowCount={0}
|
vListOverscanRowCount={0}
|
||||||
onCellClick={handleCellClick}
|
onCellClick={handleCellClick}
|
||||||
initialColumnsWidths={initialColumnsWidths}
|
initialColumnsWidths={initialColumnsWidths}
|
||||||
onColumnResizing={handleColumnResizing}
|
onColumnResizing={handleColumnResizing}
|
||||||
|
size={accountsTableSize}
|
||||||
payload={{
|
payload={{
|
||||||
onEdit: handleEditAccount,
|
onEdit: handleEditAccount,
|
||||||
onDelete: handleDeleteAccount,
|
onDelete: handleDeleteAccount,
|
||||||
@@ -123,4 +128,7 @@ export default compose(
|
|||||||
withAlertsActions,
|
withAlertsActions,
|
||||||
withDrawerActions,
|
withDrawerActions,
|
||||||
withDialogActions,
|
withDialogActions,
|
||||||
|
withSettings(({ accountsSettings }) => ({
|
||||||
|
accountsTableSize: accountsSettings.tableSize,
|
||||||
|
})),
|
||||||
)(AccountsDataTable);
|
)(AccountsDataTable);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function BillTransactionDeleteAlert({
|
|||||||
deleteLandedCostMutate(BillId)
|
deleteLandedCostMutate(BillId)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: intl.get('bill.action.delete_successfully.landed_cost'),
|
message: intl.get('landed_cost.action.delete.success_message'),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
closeAlert(name);
|
closeAlert(name);
|
||||||
@@ -56,7 +56,11 @@ function BillTransactionDeleteAlert({
|
|||||||
onConfirm={handleConfirmLandedCostDelete}
|
onConfirm={handleConfirmLandedCostDelete}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
>
|
>
|
||||||
<p><T id={`Once your delete this located landed cost, you won't be able to restore it later, Are your sure you want to delete this transaction?`}/></p>
|
<p>
|
||||||
|
<T
|
||||||
|
id={`Once your delete this located landed cost, you won't be able to restore it later, Are your sure you want to delete this transaction?`}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function CustomerBulkDeleteAlert({
|
|||||||
closeAlert(name);
|
closeAlert(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(customersIds, 'EE');
|
|
||||||
|
|
||||||
// Handle confirm customers bulk delete.
|
// Handle confirm customers bulk delete.
|
||||||
const handleConfirmBulkDelete = useCallback(() => {
|
const handleConfirmBulkDelete = useCallback(() => {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
|
import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
|
||||||
import { Intent, Alert } from '@blueprintjs/core';
|
import { Intent, Alert } from '@blueprintjs/core';
|
||||||
import { AppToaster } from 'components';
|
import { AppToaster } from 'components';
|
||||||
import { transformErrors } from 'containers/Customers/utils';
|
import { transformErrors } from 'containers/Customers/utils';
|
||||||
|
|
||||||
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
|
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
|
||||||
import withAlertActions from 'containers/Alert/withAlertActions';
|
import withAlertActions from 'containers/Alert/withAlertActions';
|
||||||
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
|
||||||
import { useDeleteCustomer } from 'hooks/query';
|
import { useDeleteCustomer } from 'hooks/query';
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customer delete alert.
|
* Customer delete alert.
|
||||||
*/
|
*/
|
||||||
@@ -24,12 +24,11 @@ function CustomerDeleteAlert({
|
|||||||
|
|
||||||
// #withAlertActions
|
// #withAlertActions
|
||||||
closeAlert,
|
closeAlert,
|
||||||
|
|
||||||
|
// #withDrawerActions
|
||||||
|
closeDrawer,
|
||||||
}) {
|
}) {
|
||||||
|
const { mutateAsync: deleteCustomerMutate, isLoading } = useDeleteCustomer();
|
||||||
const {
|
|
||||||
mutateAsync: deleteCustomerMutate,
|
|
||||||
isLoading
|
|
||||||
} = useDeleteCustomer();
|
|
||||||
|
|
||||||
// handle cancel delete alert.
|
// handle cancel delete alert.
|
||||||
const handleCancelDeleteAlert = () => {
|
const handleCancelDeleteAlert = () => {
|
||||||
@@ -44,10 +43,17 @@ function CustomerDeleteAlert({
|
|||||||
message: intl.get('the_customer_has_been_deleted_successfully'),
|
message: intl.get('the_customer_has_been_deleted_successfully'),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
|
closeDrawer('customer-details-drawer');
|
||||||
})
|
})
|
||||||
.catch(({ response: { data: { errors } } }) => {
|
.catch(
|
||||||
transformErrors(errors);
|
({
|
||||||
})
|
response: {
|
||||||
|
data: { errors },
|
||||||
|
},
|
||||||
|
}) => {
|
||||||
|
transformErrors(errors);
|
||||||
|
},
|
||||||
|
)
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
closeAlert(name);
|
closeAlert(name);
|
||||||
});
|
});
|
||||||
@@ -76,4 +82,5 @@ function CustomerDeleteAlert({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withAlertStoreConnect(),
|
withAlertStoreConnect(),
|
||||||
withAlertActions,
|
withAlertActions,
|
||||||
|
withDrawerActions,
|
||||||
)(CustomerDeleteAlert);
|
)(CustomerDeleteAlert);
|
||||||
|
|||||||
@@ -46,7 +46,24 @@ function EstimateDeleteAlert({
|
|||||||
});
|
});
|
||||||
closeDrawer('estimate-detail-drawer');
|
closeDrawer('estimate-detail-drawer');
|
||||||
})
|
})
|
||||||
.catch(({ errors }) => {})
|
.catch(
|
||||||
|
({
|
||||||
|
response: {
|
||||||
|
data: { errors },
|
||||||
|
},
|
||||||
|
}) => {
|
||||||
|
if (
|
||||||
|
errors.find((e) => e.type === 'SALE_ESTIMATE_CONVERTED_TO_INVOICE')
|
||||||
|
) {
|
||||||
|
AppToaster.show({
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
message: intl.get(
|
||||||
|
'estimate.delete.error.estimate_converted_to_invoice',
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
closeAlert(name);
|
closeAlert(name);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
|
import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
|
||||||
import { Intent, Alert } from '@blueprintjs/core';
|
import { Intent, Alert } from '@blueprintjs/core';
|
||||||
|
|
||||||
import { AppToaster } from 'components';
|
import { AppToaster } from 'components';
|
||||||
@@ -9,6 +9,7 @@ import { useDeleteVendor } from 'hooks/query';
|
|||||||
|
|
||||||
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
|
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
|
||||||
import withAlertActions from 'containers/Alert/withAlertActions';
|
import withAlertActions from 'containers/Alert/withAlertActions';
|
||||||
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
@@ -24,8 +25,10 @@ function VendorDeleteAlert({
|
|||||||
|
|
||||||
// #withAlertActions
|
// #withAlertActions
|
||||||
closeAlert,
|
closeAlert,
|
||||||
|
|
||||||
|
// #withDrawerActions
|
||||||
|
closeDrawer,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const { mutateAsync: deleteVendorMutate, isLoading } = useDeleteVendor();
|
const { mutateAsync: deleteVendorMutate, isLoading } = useDeleteVendor();
|
||||||
|
|
||||||
// Handle cancel delete the vendor.
|
// Handle cancel delete the vendor.
|
||||||
@@ -41,6 +44,7 @@ function VendorDeleteAlert({
|
|||||||
message: intl.get('the_vendor_has_been_deleted_successfully'),
|
message: intl.get('the_vendor_has_been_deleted_successfully'),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
|
closeDrawer('vendor-details-drawer');
|
||||||
})
|
})
|
||||||
.catch(
|
.catch(
|
||||||
({
|
({
|
||||||
@@ -79,4 +83,5 @@ function VendorDeleteAlert({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withAlertStoreConnect(),
|
withAlertStoreConnect(),
|
||||||
withAlertActions,
|
withAlertActions,
|
||||||
|
withDrawerActions,
|
||||||
)(VendorDeleteAlert);
|
)(VendorDeleteAlert);
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import * as R from 'ramda';
|
|
||||||
|
|
||||||
import withDashboardActions from '../../containers/Dashboard/withDashboardActions';
|
|
||||||
|
|
||||||
function AuthenticationBootJSX({ setAppIsLoading }) {
|
|
||||||
React.useEffect(() => {
|
|
||||||
setAppIsLoading(false);
|
|
||||||
}, [setAppIsLoading]);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
export const AuthenticationBoot = R.compose(withDashboardActions)(
|
|
||||||
AuthenticationBootJSX,
|
|
||||||
);
|
|
||||||
@@ -8,16 +8,17 @@ import {
|
|||||||
Switch,
|
Switch,
|
||||||
Alignment,
|
Alignment,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T } from 'components';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||||
import {
|
import {
|
||||||
If,
|
If,
|
||||||
Icon,
|
Icon,
|
||||||
|
FormattedMessage as T,
|
||||||
DashboardActionViewsList,
|
DashboardActionViewsList,
|
||||||
AdvancedFilterPopover,
|
AdvancedFilterPopover,
|
||||||
DashboardFilterButton,
|
DashboardFilterButton,
|
||||||
|
DashboardRowsHeightButton,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
|
|
||||||
import { useCustomersListContext } from './CustomersListProvider';
|
import { useCustomersListContext } from './CustomersListProvider';
|
||||||
@@ -26,6 +27,8 @@ import { useRefreshCustomers } from 'hooks/query/customers';
|
|||||||
import withCustomers from './withCustomers';
|
import withCustomers from './withCustomers';
|
||||||
import withCustomersActions from './withCustomersActions';
|
import withCustomersActions from './withCustomersActions';
|
||||||
import withAlertActions from 'containers/Alert/withAlertActions';
|
import withAlertActions from 'containers/Alert/withAlertActions';
|
||||||
|
import withSettingsActions from '../../Settings/withSettingsActions';
|
||||||
|
import withSettings from '../../Settings/withSettings';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
@@ -43,6 +46,12 @@ function CustomerActionsBar({
|
|||||||
|
|
||||||
// #withAlertActions
|
// #withAlertActions
|
||||||
openAlert,
|
openAlert,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
customersTableSize,
|
||||||
|
|
||||||
|
// #withSettingsActions
|
||||||
|
addSetting,
|
||||||
}) {
|
}) {
|
||||||
// History context.
|
// History context.
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -74,7 +83,14 @@ function CustomerActionsBar({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Handle click a refresh customers
|
// Handle click a refresh customers
|
||||||
const handleRefreshBtnClick = () => { refresh(); };
|
const handleRefreshBtnClick = () => {
|
||||||
|
refresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle table row size change.
|
||||||
|
const handleTableRowSizeChange = (size) => {
|
||||||
|
addSetting('customers', 'tableSize', size);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
@@ -130,6 +146,12 @@ function CustomerActionsBar({
|
|||||||
icon={<Icon icon="file-export-16" iconSize={16} />}
|
icon={<Icon icon="file-export-16" iconSize={16} />}
|
||||||
text={<T id={'export'} />}
|
text={<T id={'export'} />}
|
||||||
/>
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
|
<DashboardRowsHeightButton
|
||||||
|
initialValue={customersTableSize}
|
||||||
|
onChange={handleTableRowSizeChange}
|
||||||
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
<Switch
|
<Switch
|
||||||
labelElement={<T id={'inactive'} />}
|
labelElement={<T id={'inactive'} />}
|
||||||
defaultChecked={accountsInactiveMode}
|
defaultChecked={accountsInactiveMode}
|
||||||
@@ -149,10 +171,14 @@ function CustomerActionsBar({
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withCustomersActions,
|
withCustomersActions,
|
||||||
|
withSettingsActions,
|
||||||
withCustomers(({ customersSelectedRows, customersTableState }) => ({
|
withCustomers(({ customersSelectedRows, customersTableState }) => ({
|
||||||
customersSelectedRows,
|
customersSelectedRows,
|
||||||
accountsInactiveMode: customersTableState.inactiveMode,
|
accountsInactiveMode: customersTableState.inactiveMode,
|
||||||
customersFilterConditions: customersTableState.filterRoles,
|
customersFilterConditions: customersTableState.filterRoles,
|
||||||
})),
|
})),
|
||||||
|
withSettings(({ customersSettings }) => ({
|
||||||
|
customersTableSize: customersSettings?.tableSize,
|
||||||
|
})),
|
||||||
withAlertActions,
|
withAlertActions,
|
||||||
)(CustomerActionsBar);
|
)(CustomerActionsBar);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import withCustomersActions from './withCustomersActions';
|
|||||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
import withSettings from '../../Settings/withSettings';
|
||||||
|
|
||||||
import { useCustomersListContext } from './CustomersListProvider';
|
import { useCustomersListContext } from './CustomersListProvider';
|
||||||
import { useMemorizedColumnsWidths } from 'hooks';
|
import { useMemorizedColumnsWidths } from 'hooks';
|
||||||
@@ -38,6 +39,9 @@ function CustomersTable({
|
|||||||
|
|
||||||
// #withDialogActions
|
// #withDialogActions
|
||||||
openDialog,
|
openDialog,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
customersTableSize,
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
@@ -135,6 +139,7 @@ function CustomersTable({
|
|||||||
onCellClick={handleCellClick}
|
onCellClick={handleCellClick}
|
||||||
initialColumnsWidths={initialColumnsWidths}
|
initialColumnsWidths={initialColumnsWidths}
|
||||||
onColumnResizing={handleColumnResizing}
|
onColumnResizing={handleColumnResizing}
|
||||||
|
size={customersTableSize}
|
||||||
payload={{
|
payload={{
|
||||||
onDelete: handleCustomerDelete,
|
onDelete: handleCustomerDelete,
|
||||||
onEdit: handleCustomerEdit,
|
onEdit: handleCustomerEdit,
|
||||||
@@ -155,4 +160,7 @@ export default compose(
|
|||||||
withCustomersActions,
|
withCustomersActions,
|
||||||
withDrawerActions,
|
withDrawerActions,
|
||||||
withCustomers(({ customersTableState }) => ({ customersTableState })),
|
withCustomers(({ customersTableState }) => ({ customersTableState })),
|
||||||
|
withSettings(({ customersSettings }) => ({
|
||||||
|
customersTableSize: customersSettings?.tableSize,
|
||||||
|
})),
|
||||||
)(CustomersTable);
|
)(CustomersTable);
|
||||||
|
|||||||
@@ -1,17 +1,12 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import {
|
import { Menu, MenuItem, MenuDivider, Intent } from '@blueprintjs/core';
|
||||||
Menu,
|
|
||||||
MenuItem,
|
|
||||||
MenuDivider,
|
|
||||||
Intent,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import clsx from 'classnames';
|
import clsx from 'classnames';
|
||||||
|
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
|
|
||||||
import { CLASSES } from '../../../common/classes';
|
import { Icon, Money, If, AvaterCell } from 'components';
|
||||||
import { Icon, Money, If } from 'components';
|
|
||||||
import { } from 'utils';
|
import { safeCallback } from 'utils';
|
||||||
import { safeCallback, firstLettersArgs } from 'utils';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions menu.
|
* Actions menu.
|
||||||
@@ -69,13 +64,6 @@ export function ActionsMenu({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Avatar cell.
|
|
||||||
*/
|
|
||||||
export function AvatarCell(row) {
|
|
||||||
return <span className="avatar">{firstLettersArgs(row.display_name)}</span>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Phone number accessor.
|
* Phone number accessor.
|
||||||
*/
|
*/
|
||||||
@@ -99,7 +87,7 @@ export function useCustomersTableColumns() {
|
|||||||
{
|
{
|
||||||
id: 'avatar',
|
id: 'avatar',
|
||||||
Header: '',
|
Header: '',
|
||||||
accessor: AvatarCell,
|
Cell: AvaterCell,
|
||||||
className: 'avatar',
|
className: 'avatar',
|
||||||
width: 45,
|
width: 45,
|
||||||
disableResizing: true,
|
disableResizing: true,
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ export default (mapState) => {
|
|||||||
sidebarExpended: state.dashboard.sidebarExpended,
|
sidebarExpended: state.dashboard.sidebarExpended,
|
||||||
preferencesPageTitle: state.dashboard.preferencesPageTitle,
|
preferencesPageTitle: state.dashboard.preferencesPageTitle,
|
||||||
dashboardBackLink: state.dashboard.backLink,
|
dashboardBackLink: state.dashboard.backLink,
|
||||||
appIsLoading: state.dashboard.appIsLoading,
|
splashScreenLoading: state.dashboard.splashScreenLoading > 0,
|
||||||
appIntlIsLoading: state.dashboard.appIntlIsLoading
|
splashScreenCompleted: state.dashboard.splashScreenLoading === 0,
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ import { connect } from 'react-redux';
|
|||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
import {
|
import {
|
||||||
toggleExpendSidebar,
|
toggleExpendSidebar,
|
||||||
appIsLoading,
|
|
||||||
appIntlIsLoading
|
|
||||||
} from 'store/dashboard/dashboard.actions';
|
} from 'store/dashboard/dashboard.actions';
|
||||||
|
import { splashStartLoading, splashStopLoading } from '../../store/dashboard/dashboard.actions';
|
||||||
|
|
||||||
const mapActionsToProps = (dispatch) => ({
|
const mapActionsToProps = (dispatch) => ({
|
||||||
changePageTitle: (pageTitle) =>
|
changePageTitle: (pageTitle) =>
|
||||||
@@ -50,15 +49,17 @@ const mapActionsToProps = (dispatch) => ({
|
|||||||
dispatch({
|
dispatch({
|
||||||
type: 'CHANGE_PREFERENCES_PAGE_TITLE',
|
type: 'CHANGE_PREFERENCES_PAGE_TITLE',
|
||||||
pageTitle,
|
pageTitle,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setDashboardBackLink: (backLink) =>
|
setDashboardBackLink: (backLink) =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.SET_DASHBOARD_BACK_LINK,
|
type: t.SET_DASHBOARD_BACK_LINK,
|
||||||
payload: { backLink },
|
payload: { backLink },
|
||||||
}),
|
}),
|
||||||
setAppIsLoading: (isLoading) => dispatch(appIsLoading(isLoading)),
|
|
||||||
setAppIntlIsLoading: (isLoading) => dispatch(appIntlIsLoading(isLoading)),
|
// Splash screen start/stop loading.
|
||||||
|
splashStartLoading: () => splashStartLoading(),
|
||||||
|
splashStopLoading: () => splashStopLoading(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapActionsToProps);
|
export default connect(null, mapActionsToProps);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export const transformErrors = (errors, { setFieldError }) => {
|
|||||||
intl.get('payment_number_is_not_unique'),
|
intl.get('payment_number_is_not_unique'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (getError('INVALID_PAYMENT_AMOUNT')) {
|
if (getError('INVALID_BILL_PAYMENT_AMOUNT')) {
|
||||||
setFieldError(
|
setFieldError(
|
||||||
'payment_amount',
|
'payment_amount',
|
||||||
intl.get('the_payment_amount_bigger_than_invoice_due_amount'),
|
intl.get('the_payment_amount_bigger_than_invoice_due_amount'),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import withDialogActions from 'containers/Dialog/withDialogActions';
|
|||||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
|
||||||
import { Icon, FormattedMessage as T } from 'components';
|
import { If, Icon, FormattedMessage as T } from 'components';
|
||||||
|
|
||||||
import { safeCallback, compose } from 'utils';
|
import { safeCallback, compose } from 'utils';
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ function BillDetailActionsBar({
|
|||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const { billId } = useBillDrawerContext();
|
const { billId, bill } = useBillDrawerContext();
|
||||||
|
|
||||||
// Handle edit bill.
|
// Handle edit bill.
|
||||||
const onEditBill = () => {
|
const onEditBill = () => {
|
||||||
@@ -45,6 +45,11 @@ function BillDetailActionsBar({
|
|||||||
openAlert('bill-delete', { billId });
|
openAlert('bill-delete', { billId });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle quick bill payment .
|
||||||
|
const handleQuickBillPayment = () => {
|
||||||
|
openDialog('quick-payment-made', { billId });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -55,6 +60,15 @@ function BillDetailActionsBar({
|
|||||||
onClick={safeCallback(onEditBill)}
|
onClick={safeCallback(onEditBill)}
|
||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
<If condition={bill.is_open && !bill.is_fully_paid}>
|
||||||
|
<Button
|
||||||
|
className={Classes.MINIMAL}
|
||||||
|
icon={<Icon icon="quick-payment-16" iconSize={16} />}
|
||||||
|
text={<T id={'add_payment'} />}
|
||||||
|
onClick={handleQuickBillPayment}
|
||||||
|
/>
|
||||||
|
</If>
|
||||||
|
<NavbarDivider />
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon={'trash-16'} iconSize={16} />}
|
icon={<Icon icon={'trash-16'} iconSize={16} />}
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ function CustomerDetailsActionsBar({
|
|||||||
|
|
||||||
const handleDeleteCustomer = () => {
|
const handleDeleteCustomer = () => {
|
||||||
openAlert(`customer-delete`, { contactId: customerId });
|
openAlert(`customer-delete`, { contactId: customerId });
|
||||||
closeDrawer('customer-details-drawer');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEditContact = () => {
|
const handleEditContact = () => {
|
||||||
history.push(`/customers/${customerId}/edit`);
|
history.push(`/customers/${customerId}/edit`);
|
||||||
closeDrawer('customer-details-drawer');
|
closeDrawer('customer-details-drawer');
|
||||||
@@ -108,7 +108,7 @@ function CustomerDetailsActionsBar({
|
|||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon="pen-18" />}
|
icon={<Icon icon="pen-18" />}
|
||||||
text={intl.get('edit_contact', { name: contact?.contact_service })}
|
text={intl.get('customer.drawer.action.edit')}
|
||||||
onClick={handleEditContact}
|
onClick={handleEditContact}
|
||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
|||||||
@@ -19,12 +19,7 @@ function InventoryAdjustmentDetailDrawer({
|
|||||||
payload: { inventoryId },
|
payload: { inventoryId },
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer isOpen={isOpen} name={name} size={'750px'}>
|
||||||
isOpen={isOpen}
|
|
||||||
name={name}
|
|
||||||
style={{ minWidth: '700px', maxWidth: '900px' }}
|
|
||||||
size={'65%'}
|
|
||||||
>
|
|
||||||
<DrawerSuspense>
|
<DrawerSuspense>
|
||||||
<InventoryAdjustmentDrawerContent inventoryId={inventoryId} />
|
<InventoryAdjustmentDrawerContent inventoryId={inventoryId} />
|
||||||
</DrawerSuspense>
|
</DrawerSuspense>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import withDialogActions from 'containers/Dialog/withDialogActions';
|
|||||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
|
||||||
import { Icon, FormattedMessage as T } from 'components';
|
import { If, Icon, FormattedMessage as T } from 'components';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ function InvoiceDetailActionsBar({
|
|||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
// Invoice detail drawer context.
|
// Invoice detail drawer context.
|
||||||
const { invoiceId } = useInvoiceDetailDrawerContext();
|
const { invoiceId, invoice } = useInvoiceDetailDrawerContext();
|
||||||
|
|
||||||
// Handle edit sale invoice.
|
// Handle edit sale invoice.
|
||||||
const handleEditInvoice = () => {
|
const handleEditInvoice = () => {
|
||||||
@@ -54,6 +54,11 @@ function InvoiceDetailActionsBar({
|
|||||||
openDialog('invoice-pdf-preview', { invoiceId });
|
openDialog('invoice-pdf-preview', { invoiceId });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle quick payment invoice.
|
||||||
|
const handleQuickPaymentInvoice = () => {
|
||||||
|
openDialog('quick-payment-receive', { invoiceId });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -64,6 +69,15 @@ function InvoiceDetailActionsBar({
|
|||||||
onClick={handleEditInvoice}
|
onClick={handleEditInvoice}
|
||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
<If condition={invoice.is_delivered && !invoice.is_fully_paid}>
|
||||||
|
<Button
|
||||||
|
className={Classes.MINIMAL}
|
||||||
|
icon={<Icon icon="quick-payment-16" iconSize={16} />}
|
||||||
|
text={<T id={'add_payment'} />}
|
||||||
|
onClick={handleQuickPaymentInvoice}
|
||||||
|
/>
|
||||||
|
</If>
|
||||||
|
<NavbarDivider />
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon="print-16" />}
|
icon={<Icon icon="print-16" />}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useManualJournalDrawerContext } from './ManualJournalDrawerProvider';
|
import { useManualJournalDrawerContext } from './ManualJournalDrawerProvider';
|
||||||
|
|
||||||
import { FormatNumber } from '../../../components';
|
import { T, FormatNumber } from '../../../components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manual journal readonly details footer.
|
* Manual journal readonly details footer.
|
||||||
@@ -15,7 +15,9 @@ export default function ManualJournalDrawerFooter() {
|
|||||||
<div className="journal-drawer__content-footer">
|
<div className="journal-drawer__content-footer">
|
||||||
<div class="total-lines">
|
<div class="total-lines">
|
||||||
<div class="total-lines__line total-lines__line--subtotal">
|
<div class="total-lines__line total-lines__line--subtotal">
|
||||||
<div class="title">Subtotal</div>
|
<div class="title">
|
||||||
|
<T id={'manual_journal.details.subtotal'} />
|
||||||
|
</div>
|
||||||
<div class="debit">
|
<div class="debit">
|
||||||
<FormatNumber value={amount} />
|
<FormatNumber value={amount} />
|
||||||
</div>
|
</div>
|
||||||
@@ -24,7 +26,9 @@ export default function ManualJournalDrawerFooter() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="total-lines__line total-lines__line--total">
|
<div class="total-lines__line total-lines__line--total">
|
||||||
<div class="title">TOTAL</div>
|
<div class="title">
|
||||||
|
<T id={'manual_journal.details.total'} />
|
||||||
|
</div>
|
||||||
<div class="debit">{formatted_amount}</div>
|
<div class="debit">{formatted_amount}</div>
|
||||||
<div class="credit">{formatted_amount}</div>
|
<div class="credit">{formatted_amount}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -43,7 +43,10 @@ export default function ManualJournalDrawerHeader() {
|
|||||||
</DetailsMenu>
|
</DetailsMenu>
|
||||||
|
|
||||||
<div class="journal-drawer__content-description">
|
<div class="journal-drawer__content-description">
|
||||||
<b class="title">Description</b>: {defaultTo(description, '—')}
|
<b class="title">
|
||||||
|
<T id={'manual_journal.details.description'} />
|
||||||
|
</b>
|
||||||
|
: {defaultTo(description, '—')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ function PaymentMadeDetailProvider({ paymentMadeId, ...props }) {
|
|||||||
} = useTransactionsByReference(
|
} = useTransactionsByReference(
|
||||||
{
|
{
|
||||||
reference_id: paymentMadeId,
|
reference_id: paymentMadeId,
|
||||||
reference_type: 'paymentMade',
|
reference_type: 'BillPayment',
|
||||||
},
|
},
|
||||||
{ enabled: !!paymentMadeId },
|
{ enabled: !!paymentMadeId },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ function VendorDetailsActionsBar({
|
|||||||
// Handle delete vendor.
|
// Handle delete vendor.
|
||||||
const onDeleteContact = () => {
|
const onDeleteContact = () => {
|
||||||
openAlert(`vendor-delete`, { contactId: vendorId });
|
openAlert(`vendor-delete`, { contactId: vendorId });
|
||||||
closeDrawer('vendor-details-drawer');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNewInvoiceClick = () => {
|
const handleNewInvoiceClick = () => {
|
||||||
@@ -91,7 +90,7 @@ function VendorDetailsActionsBar({
|
|||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon="pen-18" />}
|
icon={<Icon icon="pen-18" />}
|
||||||
text={<T id={'vendor.drawer.action.edit_vendor'} />}
|
text={<T id={'vendor.drawer.action.edit'} />}
|
||||||
onClick={safeCallback(onEditContact)}
|
onClick={safeCallback(onEditContact)}
|
||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { Formik, Form } from 'formik';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
import * as R from 'ramda';
|
|
||||||
|
|
||||||
import ExpenseFormHeader from './ExpenseFormHeader';
|
import ExpenseFormHeader from './ExpenseFormHeader';
|
||||||
import ExpenseFormBody from './ExpenseFormBody';
|
import ExpenseFormBody from './ExpenseFormBody';
|
||||||
@@ -25,8 +24,13 @@ import {
|
|||||||
CreateExpenseFormSchema,
|
CreateExpenseFormSchema,
|
||||||
EditExpenseFormSchema,
|
EditExpenseFormSchema,
|
||||||
} from './ExpenseForm.schema';
|
} from './ExpenseForm.schema';
|
||||||
import { transformErrors, defaultExpense, transformToEditForm } from './utils';
|
import {
|
||||||
import { compose, orderingLinesIndexes } from 'utils';
|
transformErrors,
|
||||||
|
defaultExpense,
|
||||||
|
transformToEditForm,
|
||||||
|
transformFormValuesToRequest,
|
||||||
|
} from './utils';
|
||||||
|
import { compose } from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expense form.
|
* Expense form.
|
||||||
@@ -79,15 +83,10 @@ function ExpenseForm({
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Filter expense entries that has no amount or expense account.
|
|
||||||
const categories = values.categories.filter(
|
|
||||||
(category) => category.amount && category.expense_account_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
const form = {
|
const form = {
|
||||||
...values,
|
...transformFormValuesToRequest(values),
|
||||||
publish: submitPayload.publish,
|
publish: submitPayload.publish,
|
||||||
categories: R.compose(orderingLinesIndexes)(categories),
|
|
||||||
};
|
};
|
||||||
// Handle request success.
|
// Handle request success.
|
||||||
const handleSuccess = (response) => {
|
const handleSuccess = (response) => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { AppToaster } from 'components';
|
import { AppToaster } from 'components';
|
||||||
|
import { Intent } from '@blueprintjs/core';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
@@ -6,11 +7,14 @@ import {
|
|||||||
defaultFastFieldShouldUpdate,
|
defaultFastFieldShouldUpdate,
|
||||||
transformToForm,
|
transformToForm,
|
||||||
repeatValue,
|
repeatValue,
|
||||||
ensureEntriesHasEmptyLine
|
ensureEntriesHasEmptyLine,
|
||||||
|
orderingLinesIndexes
|
||||||
} from 'utils';
|
} from 'utils';
|
||||||
|
|
||||||
const ERROR = {
|
const ERROR = {
|
||||||
EXPENSE_ALREADY_PUBLISHED: 'EXPENSE.ALREADY.PUBLISHED',
|
EXPENSE_ALREADY_PUBLISHED: 'EXPENSE.ALREADY.PUBLISHED',
|
||||||
|
ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED:
|
||||||
|
'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Transform API errors in toasts messages.
|
// Transform API errors in toasts messages.
|
||||||
@@ -24,6 +28,14 @@ export const transformErrors = (errors, { setErrors }) => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (hasError(ERROR.ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED)) {
|
||||||
|
setErrors(
|
||||||
|
AppToaster.show({
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
message: 'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MIN_LINES_NUMBER = 4;
|
export const MIN_LINES_NUMBER = 4;
|
||||||
@@ -93,3 +105,25 @@ export const accountsFieldShouldUpdate = (newProps, oldProps) => {
|
|||||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter expense entries that has no amount or expense account.
|
||||||
|
*/
|
||||||
|
export const filterNonZeroEntries = (categories) => {
|
||||||
|
return categories.filter(
|
||||||
|
(category) => category.amount && category.expense_account_id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes the form values to request body.
|
||||||
|
*/
|
||||||
|
export const transformFormValuesToRequest = (values) => {
|
||||||
|
const categories = filterNonZeroEntries(values.categories);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...values,
|
||||||
|
categories: R.compose(orderingLinesIndexes)(categories),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,16 +9,17 @@ import {
|
|||||||
Alignment,
|
Alignment,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { FormattedMessage as T } from 'components';
|
|
||||||
|
|
||||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
If,
|
If,
|
||||||
|
DashboardRowsHeightButton,
|
||||||
DashboardActionViewsList,
|
DashboardActionViewsList,
|
||||||
DashboardFilterButton,
|
DashboardFilterButton,
|
||||||
AdvancedFilterPopover,
|
AdvancedFilterPopover,
|
||||||
|
FormattedMessage as T,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
|
|
||||||
import { useRefreshExpenses } from 'hooks/query/expenses';
|
import { useRefreshExpenses } from 'hooks/query/expenses';
|
||||||
@@ -27,6 +28,9 @@ import { useExpensesListContext } from './ExpensesListProvider';
|
|||||||
import withExpensesActions from './withExpensesActions';
|
import withExpensesActions from './withExpensesActions';
|
||||||
import withExpenses from './withExpenses';
|
import withExpenses from './withExpenses';
|
||||||
|
|
||||||
|
import withSettingsActions from '../../Settings/withSettingsActions';
|
||||||
|
import withSettings from '../../Settings/withSettings';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +42,12 @@ function ExpensesActionsBar({
|
|||||||
|
|
||||||
// #withExpenses
|
// #withExpenses
|
||||||
expensesFilterConditions,
|
expensesFilterConditions,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
expensesTableSize,
|
||||||
|
|
||||||
|
// #withSettingsActions
|
||||||
|
addSetting,
|
||||||
}) {
|
}) {
|
||||||
// History context.
|
// History context.
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -67,6 +77,11 @@ function ExpensesActionsBar({
|
|||||||
const handleRefreshBtnClick = () => {
|
const handleRefreshBtnClick = () => {
|
||||||
refresh();
|
refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle table row size change.
|
||||||
|
const handleTableRowSizeChange = (size) => {
|
||||||
|
addSetting('expenses', 'tableSize', size);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -124,6 +139,12 @@ function ExpensesActionsBar({
|
|||||||
icon={<Icon icon="file-export-16" iconSize={16} />}
|
icon={<Icon icon="file-export-16" iconSize={16} />}
|
||||||
text={<T id={'export'} />}
|
text={<T id={'export'} />}
|
||||||
/>
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
|
<DashboardRowsHeightButton
|
||||||
|
initialValue={expensesTableSize}
|
||||||
|
onChange={handleTableRowSizeChange}
|
||||||
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
</NavbarGroup>
|
</NavbarGroup>
|
||||||
<NavbarGroup align={Alignment.RIGHT}>
|
<NavbarGroup align={Alignment.RIGHT}>
|
||||||
<Button
|
<Button
|
||||||
@@ -139,7 +160,11 @@ function ExpensesActionsBar({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withDialogActions,
|
withDialogActions,
|
||||||
withExpensesActions,
|
withExpensesActions,
|
||||||
|
withSettingsActions,
|
||||||
withExpenses(({ expensesTableState }) => ({
|
withExpenses(({ expensesTableState }) => ({
|
||||||
expensesFilterConditions: expensesTableState.filterRoles,
|
expensesFilterConditions: expensesTableState.filterRoles,
|
||||||
})),
|
})),
|
||||||
|
withSettings(({ expenseSettings }) => ({
|
||||||
|
expensesTableSize: expenseSettings?.tableSize,
|
||||||
|
})),
|
||||||
)(ExpensesActionsBar);
|
)(ExpensesActionsBar);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
|||||||
import withExpensesActions from './withExpensesActions';
|
import withExpensesActions from './withExpensesActions';
|
||||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
import withSettings from '../../Settings/withSettings';
|
||||||
|
|
||||||
import { ActionsMenu, useExpensesTableColumns } from './components';
|
import { ActionsMenu, useExpensesTableColumns } from './components';
|
||||||
|
|
||||||
@@ -31,6 +32,9 @@ function ExpensesDataTable({
|
|||||||
|
|
||||||
// #withAlertsActions
|
// #withAlertsActions
|
||||||
openAlert,
|
openAlert,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
expensesTableSize,
|
||||||
}) {
|
}) {
|
||||||
// Expenses list context.
|
// Expenses list context.
|
||||||
const {
|
const {
|
||||||
@@ -119,6 +123,7 @@ function ExpensesDataTable({
|
|||||||
onCellClick={handleCellClick}
|
onCellClick={handleCellClick}
|
||||||
initialColumnsWidths={initialColumnsWidths}
|
initialColumnsWidths={initialColumnsWidths}
|
||||||
onColumnResizing={handleColumnResizing}
|
onColumnResizing={handleColumnResizing}
|
||||||
|
size={expensesTableSize}
|
||||||
payload={{
|
payload={{
|
||||||
onPublish: handlePublishExpense,
|
onPublish: handlePublishExpense,
|
||||||
onDelete: handleDeleteExpense,
|
onDelete: handleDeleteExpense,
|
||||||
@@ -135,4 +140,7 @@ export default compose(
|
|||||||
withAlertsActions,
|
withAlertsActions,
|
||||||
withDrawerActions,
|
withDrawerActions,
|
||||||
withExpensesActions,
|
withExpensesActions,
|
||||||
|
withSettings(({ expenseSettings }) => ({
|
||||||
|
expensesTableSize: expenseSettings?.tableSize,
|
||||||
|
})),
|
||||||
)(ExpensesDataTable);
|
)(ExpensesDataTable);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function BalanceSheet({
|
|||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
basis: 'cash',
|
basis: 'cash',
|
||||||
displayColumnsType: 'total',
|
displayColumnsType: 'total',
|
||||||
accountsFilter: 'without-zero-balance',
|
filterByOption: 'without-zero-balance',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle re-fetch balance sheet after filter change.
|
// Handle re-fetch balance sheet after filter change.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
|
import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
|
||||||
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
||||||
import FinancialAccountsFilter from '../FinancialAccountsFilter';
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Balance sheet header - General panal.
|
* Balance sheet header - General panal.
|
||||||
@@ -12,7 +12,7 @@ export default function BalanceSheetHeaderGeneralTab({}) {
|
|||||||
<div>
|
<div>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
<SelectDisplayColumnsBy />
|
<SelectDisplayColumnsBy />
|
||||||
<FinancialAccountsFilter
|
<FinancialStatementsFilter
|
||||||
initialSelectedItem={'all-accounts'}
|
initialSelectedItem={'all-accounts'}
|
||||||
/>
|
/>
|
||||||
<RadiosAccountingBasis key={'basis'} />
|
<RadiosAccountingBasis key={'basis'} />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import moment from 'moment';
|
|||||||
export const getBalanceSheetHeaderDefaultValues = () => {
|
export const getBalanceSheetHeaderDefaultValues = () => {
|
||||||
return {
|
return {
|
||||||
basic: 'cash',
|
basic: 'cash',
|
||||||
accountsFilter: 'without-zero-balance',
|
filterByOption: 'without-zero-balance',
|
||||||
displayColumnsType: 'total',
|
displayColumnsType: 'total',
|
||||||
fromDate: moment().toDate(),
|
fromDate: moment().toDate(),
|
||||||
toDate: moment().toDate(),
|
toDate: moment().toDate(),
|
||||||
@@ -20,6 +20,6 @@ export const getBalanceSheetHeaderValidationSchema = () =>
|
|||||||
.min(Yup.ref('fromDate'))
|
.min(Yup.ref('fromDate'))
|
||||||
.required()
|
.required()
|
||||||
.label(intl.get('toDate')),
|
.label(intl.get('toDate')),
|
||||||
accountsFilter: Yup.string(),
|
filterByOption: Yup.string(),
|
||||||
displayColumnsType: Yup.string(),
|
displayColumnsType: Yup.string(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ function CashFlowStatement({
|
|||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
basis: 'cash',
|
basis: 'cash',
|
||||||
displayColumnsType: 'total',
|
displayColumnsType: 'total',
|
||||||
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle refetch cash flow after filter change.
|
// Handle refetch cash flow after filter change.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
import FinancialAccountsFilter from '../FinancialAccountsFilter';
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
||||||
import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
|
import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ export default function CashFlowStatementHeaderGeneralPanel() {
|
|||||||
<div>
|
<div>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
<SelectDisplayColumnsBy />
|
<SelectDisplayColumnsBy />
|
||||||
<FinancialAccountsFilter initialSelectedItem={'all-accounts'} />
|
<FinancialStatementsFilter initialSelectedItem={'with-transactions'} />
|
||||||
<RadiosAccountingBasis key={'basis'} />
|
<RadiosAccountingBasis key={'basis'} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ function CustomersBalanceSummary({
|
|||||||
}) {
|
}) {
|
||||||
const [filter, setFilter] = useState({
|
const [filter, setFilter] = useState({
|
||||||
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
||||||
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle re-fetch customers balance summary after filter change.
|
// Handle re-fetch customers balance summary after filter change.
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import { Classes, FormGroup, Position, Checkbox } from '@blueprintjs/core';
|
|||||||
import { ContactsMultiSelect, FormattedMessage as T } from 'components';
|
import { ContactsMultiSelect, FormattedMessage as T } from 'components';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Row, Col, FieldHint } from 'components';
|
import { Row, Col, FieldHint } from 'components';
|
||||||
|
import { filterCustomersOptions } from '../constants';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
@@ -12,6 +14,7 @@ import {
|
|||||||
handleDateChange,
|
handleDateChange,
|
||||||
} from 'utils';
|
} from 'utils';
|
||||||
import { useCustomersBalanceSummaryGeneralContext } from './CustomersBalanceSummaryGeneralProvider';
|
import { useCustomersBalanceSummaryGeneralContext } from './CustomersBalanceSummaryGeneralProvider';
|
||||||
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customers balance header - General panel - Content
|
* Customers balance header - General panel - Content
|
||||||
@@ -65,6 +68,12 @@ export default function CustomersBalanceSummaryGeneralPanelContent() {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
<FinancialStatementsFilter
|
||||||
|
items={filterCustomersOptions}
|
||||||
|
label={<T id={'customers.label_filter_customers'} />}
|
||||||
|
initialSelectedItem={'with-transactions'}
|
||||||
|
/>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
<Field name={'customersIds'}>
|
<Field name={'customersIds'}>
|
||||||
@@ -80,7 +89,7 @@ export default function CustomersBalanceSummaryGeneralPanelContent() {
|
|||||||
<ContactsMultiSelect
|
<ContactsMultiSelect
|
||||||
items={customers}
|
items={customers}
|
||||||
onItemSelect={(contacts) => {
|
onItemSelect={(contacts) => {
|
||||||
const customersIds = contacts.map(contact => contact.id);
|
const customersIds = contacts.map((contact) => contact.id);
|
||||||
setFieldValue('customersIds', customersIds);
|
setFieldValue('customersIds', customersIds);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ function CustomersBalanceSummaryHeader({
|
|||||||
// #withCustomersBalanceSummaryActions
|
// #withCustomersBalanceSummaryActions
|
||||||
toggleCustomerBalanceFilterDrawer,
|
toggleCustomerBalanceFilterDrawer,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
// validation schema.
|
// validation schema.
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
asDate: Yup.date().required().label('asDate'),
|
asDate: Yup.date().required().label('asDate'),
|
||||||
@@ -34,15 +33,20 @@ function CustomersBalanceSummaryHeader({
|
|||||||
|
|
||||||
// Default form values.
|
// Default form values.
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
|
...pageFilter,
|
||||||
asDate: moment().toDate(),
|
asDate: moment().toDate(),
|
||||||
customersIds: [],
|
customersIds: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Filter form initial values.
|
// Filter form initial values.
|
||||||
const initialValues = transformToForm({
|
const initialValues = transformToForm(
|
||||||
...pageFilter,
|
{
|
||||||
asDate: moment(pageFilter.asDate).toDate(),
|
...defaultValues,
|
||||||
}, defaultValues);
|
...pageFilter,
|
||||||
|
asDate: moment(pageFilter.asDate).toDate(),
|
||||||
|
},
|
||||||
|
defaultValues,
|
||||||
|
);
|
||||||
|
|
||||||
// handle form submit.
|
// handle form submit.
|
||||||
const handleSubmit = (values, { setSubmitting }) => {
|
const handleSubmit = (values, { setSubmitting }) => {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ function CustomersTransactions({
|
|||||||
const [filter, setFilter] = useState({
|
const [filter, setFilter] = useState({
|
||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleFilterSubmit = (filter) => {
|
const handleFilterSubmit = (filter) => {
|
||||||
|
|||||||
@@ -30,22 +30,25 @@ function CustomersTransactionsHeader({
|
|||||||
}) {
|
}) {
|
||||||
// Default form values.
|
// Default form values.
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
|
...pageFilter,
|
||||||
fromDate: moment().toDate(),
|
fromDate: moment().toDate(),
|
||||||
toDate: moment().toDate(),
|
toDate: moment().toDate(),
|
||||||
customersIds: [],
|
customersIds: [],
|
||||||
};
|
};
|
||||||
// Initial form values.
|
// Initial form values.
|
||||||
const initialValues = transformToForm({
|
const initialValues = transformToForm(
|
||||||
...pageFilter,
|
{
|
||||||
fromDate: moment(pageFilter.fromDate).toDate(),
|
...defaultValues,
|
||||||
toDate: moment(pageFilter.toDate).toDate(),
|
...pageFilter,
|
||||||
}, defaultValues);
|
fromDate: moment(pageFilter.fromDate).toDate(),
|
||||||
|
toDate: moment(pageFilter.toDate).toDate(),
|
||||||
|
},
|
||||||
|
defaultValues,
|
||||||
|
);
|
||||||
|
|
||||||
// Validation schema.
|
// Validation schema.
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
fromDate: Yup.date()
|
fromDate: Yup.date().required().label(intl.get('fromDate')),
|
||||||
.required()
|
|
||||||
.label(intl.get('fromDate')),
|
|
||||||
toDate: Yup.date()
|
toDate: Yup.date()
|
||||||
.min(Yup.ref('fromDate'))
|
.min(Yup.ref('fromDate'))
|
||||||
.required()
|
.required()
|
||||||
@@ -59,7 +62,9 @@ function CustomersTransactionsHeader({
|
|||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
};
|
};
|
||||||
// Handle drawer close action.
|
// Handle drawer close action.
|
||||||
const handleDrawerClose = () => { toggleFilterDrawer(false); };
|
const handleDrawerClose = () => {
|
||||||
|
toggleFilterDrawer(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader
|
<FinancialStatementHeader
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ import classNames from 'classnames';
|
|||||||
import { Field } from 'formik';
|
import { Field } from 'formik';
|
||||||
import { Classes, FormGroup } from '@blueprintjs/core';
|
import { Classes, FormGroup } from '@blueprintjs/core';
|
||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
import {
|
import {
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
ContactsMultiSelect,
|
ContactsMultiSelect,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
} from '../../../components';
|
} from '../../../components';
|
||||||
|
import { filterCustomersOptions } from '../constants';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CustomersTransactionsGeneralPanelProvider,
|
CustomersTransactionsGeneralPanelProvider,
|
||||||
useCustomersTransactionsGeneralPanelContext,
|
useCustomersTransactionsGeneralPanelContext,
|
||||||
@@ -34,7 +37,11 @@ function CustomersTransactionsHeaderGeneralPanelContent() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
|
<FinancialStatementsFilter
|
||||||
|
items={filterCustomersOptions}
|
||||||
|
label={<T id={'customers.label_filter_customers'} />}
|
||||||
|
initialSelectedItem={'with-transactions'}
|
||||||
|
/>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
<Field name={'customersIds'}>
|
<Field name={'customersIds'}>
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import { Row, Col, Hint } from 'components';
|
|||||||
import { momentFormatter, parseDateRangeQuery } from 'utils';
|
import { momentFormatter, parseDateRangeQuery } from 'utils';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { dateRangeOptions } from 'containers/FinancialStatements/common';
|
import { dateRangeOptions } from './constants';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Financial statement - Date range select.
|
* Financial statement - Date range select.
|
||||||
|
|||||||
@@ -12,17 +12,21 @@ import { FastField } from 'formik';
|
|||||||
|
|
||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
import { Col, Row, ListSelect, MODIFIER } from 'components';
|
import { Col, Row, ListSelect, MODIFIER } from 'components';
|
||||||
import { filterAccountsOptions } from './common';
|
import { filterAccountsOptions } from './constants';
|
||||||
|
|
||||||
|
|
||||||
export default function FinancialAccountsFilter({ ...restProps }) {
|
export default function FinancialStatementsFilter({
|
||||||
|
items = filterAccountsOptions,
|
||||||
|
label = <T id={'filter_accounts'} />,
|
||||||
|
...restProps
|
||||||
|
}) {
|
||||||
const SUBMENU_POPOVER_MODIFIERS = {
|
const SUBMENU_POPOVER_MODIFIERS = {
|
||||||
flip: { boundariesElement: 'viewport', padding: 20 },
|
flip: { boundariesElement: 'viewport', padding: 20 },
|
||||||
offset: { offset: '0, 10' },
|
offset: { offset: '0, 10' },
|
||||||
preventOverflow: { boundariesElement: 'viewport', padding: 40 },
|
preventOverflow: { boundariesElement: 'viewport', padding: 40 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const filterAccountRenderer = (item, { handleClick, modifiers, query }) => {
|
const filterRenderer = (item, { handleClick, modifiers, query }) => {
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
interactionKind={PopoverInteractionKind.HOVER}
|
interactionKind={PopoverInteractionKind.HOVER}
|
||||||
@@ -41,23 +45,23 @@ export default function FinancialAccountsFilter({ ...restProps }) {
|
|||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
<FastField name={'accountsFilter'}>
|
<FastField name={'filterByOption'}>
|
||||||
{({ form: { setFieldValue }, field: { value } }) => (
|
{({ form: { setFieldValue }, field: { value } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'filter_accounts'} />}
|
label={label}
|
||||||
className="form-group--select-list bp3-fill"
|
className="form-group--select-list bp3-fill"
|
||||||
inline={false}
|
inline={false}
|
||||||
>
|
>
|
||||||
<ListSelect
|
<ListSelect
|
||||||
items={filterAccountsOptions}
|
items={items}
|
||||||
itemRenderer={filterAccountRenderer}
|
itemRenderer={filterRenderer}
|
||||||
popoverProps={{ minimal: true }}
|
popoverProps={{ minimal: true }}
|
||||||
filterable={false}
|
filterable={false}
|
||||||
selectedItem={value}
|
selectedItem={value}
|
||||||
selectedItemProp={'key'}
|
selectedItemProp={'key'}
|
||||||
textProp={'name'}
|
textProp={'name'}
|
||||||
onItemSelect={(item) => {
|
onItemSelect={(item) => {
|
||||||
setFieldValue('accountsFilter', item.key);
|
setFieldValue('filterByOption', item.key);
|
||||||
}}
|
}}
|
||||||
className={classNames(CLASSES.SELECT_LIST_FILL_POPOVER)}
|
className={classNames(CLASSES.SELECT_LIST_FILL_POPOVER)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
@@ -34,7 +34,7 @@ function GeneralLedger({
|
|||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
basis: 'accural',
|
basis: 'accural',
|
||||||
accountsFilter: 'with-transactions',
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle financial statement filter change.
|
// Handle financial statement filter change.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { AccountsMultiSelect, Row, Col } from 'components';
|
|||||||
|
|
||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
||||||
import FinancialAccountsFilter from '../FinancialAccountsFilter';
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
import { GLHeaderGeneralPanelProvider } from './GLHeaderGeneralPaneProvider';
|
import { GLHeaderGeneralPanelProvider } from './GLHeaderGeneralPaneProvider';
|
||||||
|
|
||||||
import { filterAccountsOptions } from './common';
|
import { filterAccountsOptions } from './common';
|
||||||
@@ -33,9 +33,9 @@ function GLHeaderGeneralPaneContent() {
|
|||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
<FinancialAccountsFilter
|
<FinancialStatementsFilter
|
||||||
items={filterAccountsOptions}
|
items={filterAccountsOptions}
|
||||||
initialSelectedItem={'all-accounts'}
|
initialSelectedItem={'with-transactions'}
|
||||||
/>
|
/>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ function InventoryValuation({
|
|||||||
}) {
|
}) {
|
||||||
const [filter, setFilter] = useState({
|
const [filter, setFilter] = useState({
|
||||||
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
||||||
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle filter form submit.
|
// Handle filter form submit.
|
||||||
@@ -54,7 +55,6 @@ function InventoryValuation({
|
|||||||
[toggleInventoryValuationFilterDrawer],
|
[toggleInventoryValuationFilterDrawer],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InventoryValuationProvider query={filter}>
|
<InventoryValuationProvider query={filter}>
|
||||||
<InventoryValuationActionsBar
|
<InventoryValuationActionsBar
|
||||||
|
|||||||
@@ -33,12 +33,14 @@ function InventoryValuationHeader({
|
|||||||
|
|
||||||
// Default values.
|
// Default values.
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
|
...pageFilter,
|
||||||
asDate: moment().toDate(),
|
asDate: moment().toDate(),
|
||||||
itemsIds: [],
|
itemsIds: [],
|
||||||
};
|
};
|
||||||
// Initial values.
|
// Initial values.
|
||||||
const initialValues = transformToForm({
|
const initialValues = transformToForm({
|
||||||
...pageFilter,
|
...pageFilter,
|
||||||
|
...defaultValues,
|
||||||
asDate: moment(pageFilter.asDate).toDate(),
|
asDate: moment(pageFilter.asDate).toDate(),
|
||||||
}, defaultValues);
|
}, defaultValues);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import {
|
|||||||
Col,
|
Col,
|
||||||
FieldHint,
|
FieldHint,
|
||||||
} from '../../../components';
|
} from '../../../components';
|
||||||
|
import { filterInventoryValuationOptions } from '../constants';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
@@ -21,6 +23,7 @@ import {
|
|||||||
InventoryValuationGeneralPanelProvider,
|
InventoryValuationGeneralPanelProvider,
|
||||||
useInventoryValuationGeneralPanelContext,
|
useInventoryValuationGeneralPanelContext,
|
||||||
} from './InventoryValuationHeaderGeneralPanelProvider';
|
} from './InventoryValuationHeaderGeneralPanelProvider';
|
||||||
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inventory valuation - Drawer Header - General panel.
|
* Inventory valuation - Drawer Header - General panel.
|
||||||
@@ -42,7 +45,7 @@ function InventoryValuationHeaderGeneralPanelContent() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={5}>
|
<Col xs={4}>
|
||||||
<FastField name={'asDate'}>
|
<FastField name={'asDate'}>
|
||||||
{({ form, field: { value }, meta: { error } }) => (
|
{({ form, field: { value }, meta: { error } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
@@ -66,9 +69,14 @@ function InventoryValuationHeaderGeneralPanelContent() {
|
|||||||
</FastField>
|
</FastField>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<FinancialStatementsFilter
|
||||||
|
items={filterInventoryValuationOptions}
|
||||||
|
label={<T id={'items.label_filter_items'} />}
|
||||||
|
initialSelectedItem={'all-items'}
|
||||||
|
/>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={5}>
|
<Col xs={4}>
|
||||||
<Field name={'itemsIds'}>
|
<Field name={'itemsIds'}>
|
||||||
{({ form: { setFieldValue } }) => (
|
{({ form: { setFieldValue } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ import withCurrentOrganization from '../../Organization/withCurrentOrganization'
|
|||||||
|
|
||||||
import 'style/pages/FinancialStatements/ProfitLossSheet.scss';
|
import 'style/pages/FinancialStatements/ProfitLossSheet.scss';
|
||||||
import { ProfitLossSheetProvider } from './ProfitLossProvider';
|
import { ProfitLossSheetProvider } from './ProfitLossProvider';
|
||||||
import {
|
import { ProfitLossSheetLoadingBar, ProfitLossSheetAlerts } from './components';
|
||||||
ProfitLossSheetLoadingBar,
|
|
||||||
ProfitLossSheetAlerts
|
|
||||||
} from './components';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profit/Loss financial statement sheet.
|
* Profit/Loss financial statement sheet.
|
||||||
@@ -34,7 +31,7 @@ function ProfitLossSheet({
|
|||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
displayColumnsType: 'total',
|
displayColumnsType: 'total',
|
||||||
accountsFilter: 'all-accounts',
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle submit filter.
|
// Handle submit filter.
|
||||||
|
|||||||
@@ -25,18 +25,14 @@ function ProfitLossHeader({
|
|||||||
// #withProfitLossActions
|
// #withProfitLossActions
|
||||||
toggleProfitLossFilterDrawer: toggleFilterDrawer,
|
toggleProfitLossFilterDrawer: toggleFilterDrawer,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
|
||||||
// Validation schema.
|
// Validation schema.
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
fromDate: Yup.date()
|
fromDate: Yup.date().required().label(intl.get('from_date')),
|
||||||
.required()
|
|
||||||
.label(intl.get('from_date')),
|
|
||||||
toDate: Yup.date()
|
toDate: Yup.date()
|
||||||
.min(Yup.ref('fromDate'))
|
.min(Yup.ref('fromDate'))
|
||||||
.required()
|
.required()
|
||||||
.label(intl.get('to_date')),
|
.label(intl.get('to_date')),
|
||||||
accountsFilter: Yup.string(),
|
filterByOption: Yup.string(),
|
||||||
displayColumnsType: Yup.string(),
|
displayColumnsType: Yup.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
|
import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
|
||||||
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
||||||
import FinancialAccountsFilter from '../FinancialAccountsFilter';
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profit/Loss sheet - Drawer header - General panel.
|
* Profit/Loss sheet - Drawer header - General panel.
|
||||||
@@ -13,7 +13,7 @@ export default function ProfitLossSheetHeaderGeneralPane({}) {
|
|||||||
<div>
|
<div>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
<SelectDisplayColumnsBy />
|
<SelectDisplayColumnsBy />
|
||||||
<FinancialAccountsFilter initialSelectedItem={'all-accounts'} />
|
<FinancialStatementsFilter initialSelectedItem={'with-transactions'} />
|
||||||
<RadiosAccountingBasis key={'basis'} />
|
<RadiosAccountingBasis key={'basis'} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ function PurchasesByItems({
|
|||||||
const [filter, setFilter] = useState({
|
const [filter, setFilter] = useState({
|
||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle filter form submit.
|
// Handle filter form submit.
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import {
|
|||||||
} from '../../../components';
|
} from '../../../components';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
|
import { filterItemsOptions } from '../constants';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
PurchasesByItemsGeneralPanelProvider,
|
PurchasesByItemsGeneralPanelProvider,
|
||||||
@@ -35,6 +37,11 @@ function PurchasesByItemsGeneralPanelContent() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
|
<FinancialStatementsFilter
|
||||||
|
items={filterItemsOptions}
|
||||||
|
label={<T id={'items.label_filter_items'} />}
|
||||||
|
initialSelectedItem={'with-transactions'}
|
||||||
|
/>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ function PurchasesByItemsHeader({
|
|||||||
// Initial form values.
|
// Initial form values.
|
||||||
const initialValues = transformToForm(
|
const initialValues = transformToForm(
|
||||||
{
|
{
|
||||||
|
...defaultValues,
|
||||||
...pageFilter,
|
...pageFilter,
|
||||||
fromDate: moment(pageFilter.fromDate).toDate(),
|
fromDate: moment(pageFilter.fromDate).toDate(),
|
||||||
toDate: moment(pageFilter.toDate).toDate(),
|
toDate: moment(pageFilter.toDate).toDate(),
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
|
|
||||||
import 'style/pages/FinancialStatements/SalesAndPurchasesSheet.scss';
|
import 'style/pages/FinancialStatements/SalesAndPurchasesSheet.scss';
|
||||||
|
|
||||||
import { SalesByItemProvider } from './SalesByItemProvider';
|
import { SalesByItemProvider } from './SalesByItemProvider';
|
||||||
@@ -30,6 +29,7 @@ function SalesByItems({
|
|||||||
const [filter, setFilter] = useState({
|
const [filter, setFilter] = useState({
|
||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle filter form submit.
|
// Handle filter form submit.
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import React from 'react';
|
|||||||
import { FormGroup, Classes } from '@blueprintjs/core';
|
import { FormGroup, Classes } from '@blueprintjs/core';
|
||||||
import { Field } from 'formik';
|
import { Field } from 'formik';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { get } from 'lodash';
|
import { filterItemsOptions } from '../constants';
|
||||||
|
|
||||||
import { Row, Col, ItemsMultiSelect, FormattedMessage as T } from 'components';
|
import { Row, Col, ItemsMultiSelect, FormattedMessage as T } from 'components';
|
||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
import {
|
import {
|
||||||
SalesByItemGeneralPanelProvider,
|
SalesByItemGeneralPanelProvider,
|
||||||
useSalesByItemsGeneralPanelContext,
|
useSalesByItemsGeneralPanelContext,
|
||||||
@@ -32,6 +33,12 @@ function SalesByItemsHeaderGeneralPanelContent() {
|
|||||||
<div>
|
<div>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
|
|
||||||
|
<FinancialStatementsFilter
|
||||||
|
items={filterItemsOptions}
|
||||||
|
label={<T id={'items.label_filter_items'} />}
|
||||||
|
initialSelectedItem={'with-transactions'}
|
||||||
|
/>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
<Field name={'itemsIds'}>
|
<Field name={'itemsIds'}>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { FormGroup } from '@blueprintjs/core';
|
|||||||
import { FastField } from 'formik';
|
import { FastField } from 'formik';
|
||||||
import { FormattedMessage as T } from 'components';
|
import { FormattedMessage as T } from 'components';
|
||||||
import { Row, Col, ListSelect } from 'components';
|
import { Row, Col, ListSelect } from 'components';
|
||||||
import { displayColumnsByOptions } from 'containers/FinancialStatements/common';
|
import { displayColumnsByOptions } from './constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Financial statement - Display columns by and type select.
|
* Financial statement - Display columns by and type select.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ function TrialBalanceSheet({
|
|||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
basis: 'accural',
|
basis: 'accural',
|
||||||
accountsFilter: 'all-accounts',
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle filter form submit.
|
// Handle filter form submit.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
||||||
import FinancialAccountsFilter from '../FinancialAccountsFilter';
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trial balance sheet - Drawer header - General panel.
|
* Trial balance sheet - Drawer header - General panel.
|
||||||
@@ -12,7 +12,7 @@ export default function TrialBalanceSheetHeaderGeneralPanel({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
<FinancialAccountsFilter initialSelectedItem={'all-accounts'} />
|
<FinancialStatementsFilter initialSelectedItem={'with-transactions'} />
|
||||||
<RadiosAccountingBasis />
|
<RadiosAccountingBasis />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ function VendorsBalanceSummary({
|
|||||||
}) {
|
}) {
|
||||||
const [filter, setFilter] = useState({
|
const [filter, setFilter] = useState({
|
||||||
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
||||||
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle refetch vendors balance summary.
|
// Handle refetch vendors balance summary.
|
||||||
|
|||||||
@@ -33,14 +33,20 @@ function VendorsBalanceSummaryHeader({
|
|||||||
|
|
||||||
// filter form initial values.
|
// filter form initial values.
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
|
...pageFilter,
|
||||||
asDate: moment().toDate(),
|
asDate: moment().toDate(),
|
||||||
vendorsIds: [],
|
vendorsIds: [],
|
||||||
};
|
};
|
||||||
// Initial form values.
|
// Initial form values.
|
||||||
const initialValues = transformToForm({
|
const initialValues = transformToForm(
|
||||||
...pageFilter,
|
{
|
||||||
asDate: moment(pageFilter.asDate).toDate(),
|
...defaultValues,
|
||||||
}, defaultValues);
|
|
||||||
|
...pageFilter,
|
||||||
|
asDate: moment(pageFilter.asDate).toDate(),
|
||||||
|
},
|
||||||
|
defaultValues,
|
||||||
|
);
|
||||||
|
|
||||||
// handle form submit.
|
// handle form submit.
|
||||||
const handleSubmit = (values, { setSubmitting }) => {
|
const handleSubmit = (values, { setSubmitting }) => {
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import {
|
|||||||
FieldHint,
|
FieldHint,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
} from '../../../components';
|
} from '../../../components';
|
||||||
|
import { filterVendorsOptions } from '../constants';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
@@ -18,6 +20,7 @@ import {
|
|||||||
handleDateChange,
|
handleDateChange,
|
||||||
} from 'utils';
|
} from 'utils';
|
||||||
import { useVendorsBalanceSummaryGeneralPanelContext } from './VendorsBalanceSummaryHeaderGeneralProvider';
|
import { useVendorsBalanceSummaryGeneralPanelContext } from './VendorsBalanceSummaryHeaderGeneralProvider';
|
||||||
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vendors balance header - General panel - Content.
|
* Vendors balance header - General panel - Content.
|
||||||
@@ -71,6 +74,12 @@ export default function VendorsBalanceSummaryHeaderGeneralContent() {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
<FinancialStatementsFilter
|
||||||
|
items={filterVendorsOptions}
|
||||||
|
label={<T id={'vendors.label_filter_vendors'} />}
|
||||||
|
initialSelectedItem={'with-transactions'}
|
||||||
|
/>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
<Field name={'vendorsIds'}>
|
<Field name={'vendorsIds'}>
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ function VendorsTransactions({
|
|||||||
const [filter, setFilter] = useState({
|
const [filter, setFilter] = useState({
|
||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
|
filterByOption: 'with-transactions',
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleFilterSubmit = (filter) => {
|
const handleFilterSubmit = (filter) => {
|
||||||
|
|||||||
@@ -31,23 +31,26 @@ function VendorsTransactionsHeader({
|
|||||||
}) {
|
}) {
|
||||||
// Default form values.
|
// Default form values.
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
|
...pageFilter,
|
||||||
fromDate: moment().toDate(),
|
fromDate: moment().toDate(),
|
||||||
toDate: moment().toDate(),
|
toDate: moment().toDate(),
|
||||||
vendorsIds: [],
|
vendorsIds: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initial form values.
|
// Initial form values.
|
||||||
const initialValues = transformToForm({
|
const initialValues = transformToForm(
|
||||||
...pageFilter,
|
{
|
||||||
fromDate: moment(pageFilter.fromDate).toDate(),
|
...defaultValues,
|
||||||
toDate: moment(pageFilter.toDate).toDate(),
|
...pageFilter,
|
||||||
}, defaultValues);
|
fromDate: moment(pageFilter.fromDate).toDate(),
|
||||||
|
toDate: moment(pageFilter.toDate).toDate(),
|
||||||
|
},
|
||||||
|
defaultValues,
|
||||||
|
);
|
||||||
|
|
||||||
// Validation schema.
|
// Validation schema.
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
fromDate: Yup.date()
|
fromDate: Yup.date().required().label(intl.get('fromDate')),
|
||||||
.required()
|
|
||||||
.label(intl.get('fromDate')),
|
|
||||||
toDate: Yup.date()
|
toDate: Yup.date()
|
||||||
.min(Yup.ref('fromDate'))
|
.min(Yup.ref('fromDate'))
|
||||||
.required()
|
.required()
|
||||||
@@ -62,7 +65,9 @@ function VendorsTransactionsHeader({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Handle drawer close action.
|
// Handle drawer close action.
|
||||||
const handleDrawerClose = () => { toggleFilterDrawer(false); };
|
const handleDrawerClose = () => {
|
||||||
|
toggleFilterDrawer(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader
|
<FinancialStatementHeader
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ import classNames from 'classnames';
|
|||||||
import { Classes, FormGroup } from '@blueprintjs/core';
|
import { Classes, FormGroup } from '@blueprintjs/core';
|
||||||
|
|
||||||
import FinancialStatementDateRange from '../FinancialStatementDateRange';
|
import FinancialStatementDateRange from '../FinancialStatementDateRange';
|
||||||
|
import FinancialStatementsFilter from '../FinancialStatementsFilter';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
ContactsMultiSelect,
|
ContactsMultiSelect,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
} from '../../../components';
|
} from '../../../components';
|
||||||
|
import { filterVendorsOptions } from '../constants';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
VendorsTransactionsGeneralPanelProvider,
|
VendorsTransactionsGeneralPanelProvider,
|
||||||
useVendorsTransactionsGeneralPanelContext,
|
useVendorsTransactionsGeneralPanelContext,
|
||||||
@@ -35,7 +39,11 @@ function VendorsTransactionsHeaderGeneralPanelContent() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FinancialStatementDateRange />
|
<FinancialStatementDateRange />
|
||||||
|
<FinancialStatementsFilter
|
||||||
|
items={filterVendorsOptions}
|
||||||
|
label={<T id={'vendors.label_filter_vendors'} />}
|
||||||
|
initialSelectedItem={'all-vendors'}
|
||||||
|
/>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
<Field name={'vendorsIds'}>
|
<Field name={'vendorsIds'}>
|
||||||
|
|||||||
@@ -1,72 +1,9 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import intl from 'react-intl-universal';
|
import { displayColumnsByOptions } from './constants';
|
||||||
import { transfromToSnakeCase, flatten } from 'utils';
|
import { transfromToSnakeCase, flatten } from 'utils';
|
||||||
|
|
||||||
export const displayColumnsByOptions = [
|
|
||||||
{ key: 'total', name: intl.get('total'), type: 'total', by: '' },
|
|
||||||
{
|
|
||||||
key: 'year',
|
|
||||||
name: intl.get('date_year'),
|
|
||||||
type: 'date_periods',
|
|
||||||
by: 'year',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'month',
|
|
||||||
name: intl.get('date_month'),
|
|
||||||
type: 'date_periods',
|
|
||||||
by: 'month',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'week',
|
|
||||||
name: intl.get('date_week'),
|
|
||||||
type: 'date_periods',
|
|
||||||
by: 'month',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'day',
|
|
||||||
name: intl.get('date_day'),
|
|
||||||
type: 'date_periods',
|
|
||||||
by: 'day',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'quarter',
|
|
||||||
name: intl.get('date_quarter'),
|
|
||||||
type: 'date_periods',
|
|
||||||
by: 'quarter',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const dateRangeOptions = [
|
|
||||||
{ value: 'today', label: intl.get('today') },
|
|
||||||
{ value: 'this_week', label: intl.get('this_week') },
|
|
||||||
{ value: 'this_month', label: intl.get('this_month') },
|
|
||||||
{ value: 'this_quarter', label: intl.get('this_quarter') },
|
|
||||||
{ value: 'this_year', label: intl.get('this_year') },
|
|
||||||
{ value: 'custom', label: intl.get('custom_range') },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const filterAccountsOptions = [
|
|
||||||
{
|
|
||||||
key: 'all-accounts',
|
|
||||||
name: intl.get('all_accounts'),
|
|
||||||
hint: intl.get('all_accounts_including_with_zero_balance'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'without-zero-balance',
|
|
||||||
name: intl.get('accounts_without_zero_balance'),
|
|
||||||
hint: intl.get('include_accounts_and_exclude_zero_balance'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'with-transactions',
|
|
||||||
name: intl.get('accounts_with_transactions'),
|
|
||||||
hint: intl.get(
|
|
||||||
'include_accounts_once_has_transactions_on_given_date_period',
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associate display columns by and type properties to query object.
|
* Associate display columns by and type properties to query object.
|
||||||
*/
|
*/
|
||||||
export const transformDisplayColumnsType = (form) => {
|
export const transformDisplayColumnsType = (form) => {
|
||||||
const columnType = displayColumnsByOptions.find(
|
const columnType = displayColumnsByOptions.find(
|
||||||
@@ -85,17 +22,15 @@ export const transformDisplayColumnsType = (form) => {
|
|||||||
const setNoneZeroTransactions = (form) => {
|
const setNoneZeroTransactions = (form) => {
|
||||||
return {
|
return {
|
||||||
...form,
|
...form,
|
||||||
noneZero: form.accountsFilter === 'without-zero-balance',
|
noneZero: form.filterByOption === 'without-zero-balance',
|
||||||
noneTransactions: form.accountsFilter === 'with-transactions',
|
noneTransactions: form.filterByOption === 'with-transactions',
|
||||||
|
onlyActive: form.filterByOption === 'with-only-active',
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
// filterByOption
|
||||||
export const transformAccountsFilter = (form) => {
|
export const transformAccountsFilter = (form) => {
|
||||||
return R.compose(
|
return R.compose(R.omit(['filterByOption']), setNoneZeroTransactions)(form);
|
||||||
R.omit(['accountsFilter']),
|
};
|
||||||
setNoneZeroTransactions,
|
|
||||||
)(form)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform filter form to http query.
|
* Transform filter form to http query.
|
||||||
|
|||||||
141
src/containers/FinancialStatements/constants.js
Normal file
141
src/containers/FinancialStatements/constants.js
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
|
||||||
|
import intl from 'react-intl-universal';
|
||||||
|
|
||||||
|
|
||||||
|
export const displayColumnsByOptions = [
|
||||||
|
{ key: 'total', name: intl.get('total'), type: 'total', by: '' },
|
||||||
|
{
|
||||||
|
key: 'year',
|
||||||
|
name: intl.get('date_year'),
|
||||||
|
type: 'date_periods',
|
||||||
|
by: 'year',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'month',
|
||||||
|
name: intl.get('date_month'),
|
||||||
|
type: 'date_periods',
|
||||||
|
by: 'month',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'week',
|
||||||
|
name: intl.get('date_week'),
|
||||||
|
type: 'date_periods',
|
||||||
|
by: 'month',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'day',
|
||||||
|
name: intl.get('date_day'),
|
||||||
|
type: 'date_periods',
|
||||||
|
by: 'day',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'quarter',
|
||||||
|
name: intl.get('date_quarter'),
|
||||||
|
type: 'date_periods',
|
||||||
|
by: 'quarter',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const dateRangeOptions = [
|
||||||
|
{ value: 'today', label: intl.get('today') },
|
||||||
|
{ value: 'this_week', label: intl.get('this_week') },
|
||||||
|
{ value: 'this_month', label: intl.get('this_month') },
|
||||||
|
{ value: 'this_quarter', label: intl.get('this_quarter') },
|
||||||
|
{ value: 'this_year', label: intl.get('this_year') },
|
||||||
|
{ value: 'custom', label: intl.get('custom_range') },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const filterAccountsOptions = [
|
||||||
|
{
|
||||||
|
key: 'all-accounts',
|
||||||
|
name: intl.get('all_accounts'),
|
||||||
|
hint: intl.get('all_accounts_including_with_zero_balance'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'without-zero-balance',
|
||||||
|
name: intl.get('accounts_without_zero_balance'),
|
||||||
|
hint: intl.get('include_accounts_and_exclude_zero_balance'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'with-transactions',
|
||||||
|
name: intl.get('accounts_with_transactions'),
|
||||||
|
hint: intl.get(
|
||||||
|
'include_accounts_once_has_transactions_on_given_date_period',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const filterItemsOptions = [
|
||||||
|
{
|
||||||
|
key: 'all-items',
|
||||||
|
name: intl.get('all_items'),
|
||||||
|
hint: intl.get('items.option_all_items.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'with-transactions',
|
||||||
|
name: intl.get('items.option_with_transactions'),
|
||||||
|
hint: intl.get('items.option_with_transactions.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'with-only-active',
|
||||||
|
name: intl.get('items.option.only_active'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const filterCustomersOptions = [
|
||||||
|
{
|
||||||
|
key: 'all-customers',
|
||||||
|
name: intl.get('all_customers'),
|
||||||
|
hint: intl.get('customers.option_all_customers.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'without-zero-balance',
|
||||||
|
name: intl.get('customers.option_without_zero_balance'),
|
||||||
|
hint: intl.get('customers.option_without_zero_balance.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'with-transactions',
|
||||||
|
name: intl.get('customers.option_with_transactions'),
|
||||||
|
hint: intl.get('customers.option_with_transactions.hint'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const filterVendorsOptions = [
|
||||||
|
{
|
||||||
|
key: 'all-vendors',
|
||||||
|
name: intl.get('all_vendors'),
|
||||||
|
hint: intl.get('vendors.option_all_vendors.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'without-zero-balance',
|
||||||
|
name: intl.get('vendors.option_without_zero_balance'),
|
||||||
|
hint: intl.get('vendors.option_without_zero_balance.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'with-transactions',
|
||||||
|
name: intl.get('vendors.option_with_transactions'),
|
||||||
|
hint: intl.get('vendors.option_with_transactions.hint'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const filterInventoryValuationOptions = [
|
||||||
|
{
|
||||||
|
key: 'all-items',
|
||||||
|
name: intl.get('all_items'),
|
||||||
|
hint: intl.get('items.option_all_items.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'with-transactions',
|
||||||
|
name: intl.get('items.option_with_transactions'),
|
||||||
|
hint: intl.get('items.option_with_transactions.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'without-zero-balance',
|
||||||
|
name: intl.get('items.option_without_zero_balance'),
|
||||||
|
hint: intl.get('items.option_without_zero_balance.hint'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'with-only-active',
|
||||||
|
name: intl.get('items.option.only_active'),
|
||||||
|
},
|
||||||
|
]
|
||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
Switch,
|
Switch,
|
||||||
Alignment,
|
Alignment,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T } from 'components';
|
import { DashboardRowsHeightButton, FormattedMessage as T } from 'components';
|
||||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import {
|
import {
|
||||||
@@ -25,8 +25,10 @@ import { useRefreshItems } from 'hooks/query/items';
|
|||||||
import withItems from 'containers/Items/withItems';
|
import withItems from 'containers/Items/withItems';
|
||||||
import withItemsActions from './withItemsActions';
|
import withItemsActions from './withItemsActions';
|
||||||
import withAlertActions from 'containers/Alert/withAlertActions';
|
import withAlertActions from 'containers/Alert/withAlertActions';
|
||||||
|
import withSettings from '../Settings/withSettings';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
import withSettingsActions from '../Settings/withSettingsActions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Items actions bar.
|
* Items actions bar.
|
||||||
@@ -42,6 +44,12 @@ function ItemsActionsBar({
|
|||||||
|
|
||||||
// #withAlertActions
|
// #withAlertActions
|
||||||
openAlert,
|
openAlert,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
itemsTableSize,
|
||||||
|
|
||||||
|
// #withSettingsActions
|
||||||
|
addSetting,
|
||||||
}) {
|
}) {
|
||||||
// Items list context.
|
// Items list context.
|
||||||
const { itemsViews, fields } = useItemsListContext();
|
const { itemsViews, fields } = useItemsListContext();
|
||||||
@@ -72,10 +80,14 @@ function ItemsActionsBar({
|
|||||||
const checked = event.target.checked;
|
const checked = event.target.checked;
|
||||||
setItemsTableState({ inactiveMode: checked });
|
setItemsTableState({ inactiveMode: checked });
|
||||||
};
|
};
|
||||||
|
// Handle refresh button click.
|
||||||
const handleRefreshBtnClick = () => {
|
const handleRefreshBtnClick = () => {
|
||||||
refresh();
|
refresh();
|
||||||
};
|
};
|
||||||
|
// Handle table row size change.
|
||||||
|
const handleTableRowSizeChange = (size) => {
|
||||||
|
addSetting('items', 'tableSize', size);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
@@ -131,6 +143,12 @@ function ItemsActionsBar({
|
|||||||
icon={<Icon icon="file-export-16" iconSize={16} />}
|
icon={<Icon icon="file-export-16" iconSize={16} />}
|
||||||
text={<T id={'export'} />}
|
text={<T id={'export'} />}
|
||||||
/>
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
|
<DashboardRowsHeightButton
|
||||||
|
initialValue={itemsTableSize}
|
||||||
|
onChange={handleTableRowSizeChange}
|
||||||
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
<Switch
|
<Switch
|
||||||
labelElement={<T id={'inactive'} />}
|
labelElement={<T id={'inactive'} />}
|
||||||
defaultChecked={itemsInactiveMode}
|
defaultChecked={itemsInactiveMode}
|
||||||
@@ -150,11 +168,15 @@ function ItemsActionsBar({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
|
withSettingsActions,
|
||||||
withItems(({ itemsSelectedRows, itemsTableState }) => ({
|
withItems(({ itemsSelectedRows, itemsTableState }) => ({
|
||||||
itemsSelectedRows,
|
itemsSelectedRows,
|
||||||
itemsInactiveMode: itemsTableState.inactiveMode,
|
itemsInactiveMode: itemsTableState.inactiveMode,
|
||||||
itemsFilterRoles: itemsTableState.filterRoles,
|
itemsFilterRoles: itemsTableState.filterRoles,
|
||||||
})),
|
})),
|
||||||
|
withSettings(({ itemsSettings }) => ({
|
||||||
|
itemsTableSize: itemsSettings.tableSize,
|
||||||
|
})),
|
||||||
withItemsActions,
|
withItemsActions,
|
||||||
withAlertActions,
|
withAlertActions,
|
||||||
)(ItemsActionsBar);
|
)(ItemsActionsBar);
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
|
|||||||
|
|
||||||
import { TABLES } from 'common/tables';
|
import { TABLES } from 'common/tables';
|
||||||
|
|
||||||
import withItems from 'containers/Items/withItems';
|
|
||||||
import withItemsActions from 'containers/Items/withItemsActions';
|
import withItemsActions from 'containers/Items/withItemsActions';
|
||||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
import withSettings from '../Settings/withSettings';
|
||||||
|
|
||||||
import { useItemsListContext } from './ItemsListProvider';
|
import { useItemsListContext } from './ItemsListProvider';
|
||||||
import { useItemsTableColumns, ItemsActionMenuList } from './components';
|
import { useItemsTableColumns, ItemsActionMenuList } from './components';
|
||||||
@@ -37,8 +37,8 @@ function ItemsDataTable({
|
|||||||
// #withDrawerActions
|
// #withDrawerActions
|
||||||
openDrawer,
|
openDrawer,
|
||||||
|
|
||||||
// #withItems
|
// #withSettings
|
||||||
itemsTableState,
|
itemsTableSize,
|
||||||
|
|
||||||
// #ownProps
|
// #ownProps
|
||||||
tableProps,
|
tableProps,
|
||||||
@@ -146,6 +146,7 @@ function ItemsDataTable({
|
|||||||
onCellClick={handleCellClick}
|
onCellClick={handleCellClick}
|
||||||
initialColumnsWidths={initialColumnsWidths}
|
initialColumnsWidths={initialColumnsWidths}
|
||||||
onColumnResizing={handleColumnResizing}
|
onColumnResizing={handleColumnResizing}
|
||||||
|
size={itemsTableSize}
|
||||||
payload={{
|
payload={{
|
||||||
onDeleteItem: handleDeleteItem,
|
onDeleteItem: handleDeleteItem,
|
||||||
onEditItem: handleEditItem,
|
onEditItem: handleEditItem,
|
||||||
@@ -167,5 +168,7 @@ export default compose(
|
|||||||
withAlertsActions,
|
withAlertsActions,
|
||||||
withDrawerActions,
|
withDrawerActions,
|
||||||
withDialogActions,
|
withDialogActions,
|
||||||
withItems(({ itemsTableState }) => ({ itemsTableState })),
|
withSettings(({ itemsSettings }) => ({
|
||||||
|
itemsTableSize: itemsSettings.tableSize,
|
||||||
|
})),
|
||||||
)(ItemsDataTable);
|
)(ItemsDataTable);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const transfromItemsToSearch = (item) => ({
|
|||||||
id: item.id,
|
id: item.id,
|
||||||
text: item.name,
|
text: item.name,
|
||||||
subText: item.code,
|
subText: item.code,
|
||||||
label: item.type,
|
label: item.type_formatted,
|
||||||
reference: item,
|
reference: item,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function ItemsCategoryActionsBar({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(fields, categoriesFilterConditions, 'XXXX');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import React, { useMemo } from 'react';
|
|||||||
import { Formik, Form } from 'formik';
|
import { Formik, Form } from 'formik';
|
||||||
import { Intent } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import * as R from 'ramda';
|
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
@@ -16,13 +15,14 @@ import BillItemsEntriesEditor from './BillItemsEntriesEditor';
|
|||||||
|
|
||||||
import { AppToaster } from 'components';
|
import { AppToaster } from 'components';
|
||||||
|
|
||||||
import { ERROR } from 'common/errors';
|
|
||||||
import { useBillFormContext } from './BillFormProvider';
|
import { useBillFormContext } from './BillFormProvider';
|
||||||
import { compose, safeSumBy } from 'utils';
|
import { compose, safeSumBy } from 'utils';
|
||||||
import {
|
import {
|
||||||
defaultBill,
|
defaultBill,
|
||||||
|
filterNonZeroEntries,
|
||||||
transformToEditForm,
|
transformToEditForm,
|
||||||
transformEntriesToSubmit,
|
transformFormValuesToRequest,
|
||||||
|
handleErrors,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
||||||
|
|
||||||
@@ -55,23 +55,12 @@ function BillForm({
|
|||||||
[bill, base_currency],
|
[bill, base_currency],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Transform response error to fields.
|
|
||||||
const handleErrors = (errors, { setErrors }) => {
|
|
||||||
if (errors.some((e) => e.type === ERROR.BILL_NUMBER_EXISTS)) {
|
|
||||||
setErrors({
|
|
||||||
bill_number: intl.get('bill_number_exists'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handles form submit.
|
// Handles form submit.
|
||||||
const handleFormSubmit = (
|
const handleFormSubmit = (
|
||||||
values,
|
values,
|
||||||
{ setSubmitting, setErrors, resetForm },
|
{ setSubmitting, setErrors, resetForm },
|
||||||
) => {
|
) => {
|
||||||
const entries = values.entries.filter(
|
const entries = filterNonZeroEntries(values.entries);
|
||||||
(item) => item.item_id && item.quantity,
|
|
||||||
);
|
|
||||||
const totalQuantity = safeSumBy(entries, 'quantity');
|
const totalQuantity = safeSumBy(entries, 'quantity');
|
||||||
|
|
||||||
if (totalQuantity === 0) {
|
if (totalQuantity === 0) {
|
||||||
@@ -83,9 +72,8 @@ function BillForm({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const form = {
|
const form = {
|
||||||
...values,
|
...transformFormValuesToRequest(values),
|
||||||
open: submitPayload.status,
|
open: submitPayload.status,
|
||||||
entries: transformEntriesToSubmit(entries),
|
|
||||||
};
|
};
|
||||||
// Handle the request success.
|
// Handle the request success.
|
||||||
const onSuccess = (response) => {
|
const onSuccess = (response) => {
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ export const defaultBill = {
|
|||||||
entries: [...repeatValue(defaultBillEntry, MIN_LINES_NUMBER)],
|
entries: [...repeatValue(defaultBillEntry, MIN_LINES_NUMBER)],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ERRORS = {
|
||||||
|
// Bills
|
||||||
|
BILL_NUMBER_EXISTS: 'BILL.NUMBER.EXISTS',
|
||||||
|
ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED:
|
||||||
|
'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Transformes the bill to initial values of edit form.
|
* Transformes the bill to initial values of edit form.
|
||||||
*/
|
*/
|
||||||
@@ -70,11 +76,33 @@ export const transformToEditForm = (bill) => {
|
|||||||
* Transformes bill entries to submit request.
|
* Transformes bill entries to submit request.
|
||||||
*/
|
*/
|
||||||
export const transformEntriesToSubmit = (entries) => {
|
export const transformEntriesToSubmit = (entries) => {
|
||||||
const transformBillEntry = R.curry(transformToForm)(R.__, defaultBillEntry);
|
const transformBillEntry = R.compose(
|
||||||
|
R.omit(['amount']),
|
||||||
|
R.curry(transformToForm)(R.__, defaultBillEntry),
|
||||||
|
);
|
||||||
return R.compose(orderingLinesIndexes, R.map(transformBillEntry))(entries);
|
return R.compose(orderingLinesIndexes, R.map(transformBillEntry))(entries);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the givne non-zero entries.
|
||||||
|
*/
|
||||||
|
export const filterNonZeroEntries = (entries) => {
|
||||||
|
return entries.filter((item) => item.item_id && item.quantity);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes form values to request body.
|
||||||
|
*/
|
||||||
|
export const transformFormValuesToRequest = (values) => {
|
||||||
|
const entries = filterNonZeroEntries(values.entries);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...values,
|
||||||
|
entries: transformEntriesToSubmit(entries),
|
||||||
|
open: false,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle delete errors.
|
* Handle delete errors.
|
||||||
*/
|
*/
|
||||||
@@ -118,3 +146,24 @@ export const entriesFieldShouldUpdate = (newProps, oldProps) => {
|
|||||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Transform response error to fields.
|
||||||
|
export const handleErrors = (errors, { setErrors }) => {
|
||||||
|
if (errors.some((e) => e.type === ERRORS.BILL_NUMBER_EXISTS)) {
|
||||||
|
setErrors({
|
||||||
|
bill_number: intl.get('bill_number_exists'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
errors.some(
|
||||||
|
(e) => e.type === ERRORS.ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
setErrors(
|
||||||
|
AppToaster.show({
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
message: 'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user