mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
Merge remote-tracking branch 'origin/feature/general'
This commit is contained in:
@@ -70,6 +70,7 @@
|
|||||||
"react-loadable": "^5.5.0",
|
"react-loadable": "^5.5.0",
|
||||||
"react-redux": "^7.1.3",
|
"react-redux": "^7.1.3",
|
||||||
"react-router-dom": "^5.1.2",
|
"react-router-dom": "^5.1.2",
|
||||||
|
"react-scrollbars-custom": "^4.0.21",
|
||||||
"react-sortablejs": "^2.0.11",
|
"react-sortablejs": "^2.0.11",
|
||||||
"react-table": "^7.0.0",
|
"react-table": "^7.0.0",
|
||||||
"react-use": "^13.26.1",
|
"react-use": "^13.26.1",
|
||||||
|
|||||||
@@ -5,25 +5,34 @@ import DialogConnect from 'connectors/Dialog.connector';
|
|||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import LoadingIndicator from 'components/LoadingIndicator';
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
import DataTable from 'components/DataTable';
|
import DataTable from 'components/DataTable';
|
||||||
import { Button, Popover, Menu, MenuItem, Position } from '@blueprintjs/core';
|
import {
|
||||||
|
Button,
|
||||||
|
Popover,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
Position,
|
||||||
|
Classes,
|
||||||
|
Tooltip,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
|
|
||||||
const ItemsCategoryList = ({
|
const ItemsCategoryList = ({
|
||||||
categories,
|
categories,
|
||||||
onFetchData,
|
onFetchData,
|
||||||
onDeleteCategory,
|
onDeleteCategory,
|
||||||
onEditCategory,
|
onEditCategory,
|
||||||
openDialog
|
openDialog,
|
||||||
|
count,
|
||||||
}) => {
|
}) => {
|
||||||
const handelEditCategory = category => () => {
|
const handelEditCategory = (category) => () => {
|
||||||
openDialog('item-form', { action: 'edit', id: category.id });
|
openDialog('item-form', { action: 'edit', id: category.id });
|
||||||
onEditCategory(category.id);
|
onEditCategory(category.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteCategory = category => () => {
|
const handleDeleteCategory = (category) => () => {
|
||||||
onDeleteCategory(category);
|
onDeleteCategory(category);
|
||||||
};
|
};
|
||||||
|
|
||||||
const actionMenuList = category => (
|
const actionMenuList = (category) => (
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuItem text='Edit Category' onClick={handelEditCategory(category)} />
|
<MenuItem text='Edit Category' onClick={handelEditCategory(category)} />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
@@ -38,17 +47,22 @@ const ItemsCategoryList = ({
|
|||||||
{
|
{
|
||||||
id: 'name',
|
id: 'name',
|
||||||
Header: 'Category Name',
|
Header: 'Category Name',
|
||||||
accessor: 'name'
|
accessor: 'name',
|
||||||
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'description',
|
id: 'description',
|
||||||
Header: 'Description',
|
Header: 'Description',
|
||||||
accessor: 'description'
|
accessor: 'description',
|
||||||
|
className: 'description',
|
||||||
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'count',
|
id: 'count',
|
||||||
Header: 'Count',
|
Header: 'Count',
|
||||||
// accessor: ''
|
accessor: () => <span>{count}</span>,
|
||||||
|
className: 'count',
|
||||||
|
width: 50,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
@@ -62,9 +76,9 @@ const ItemsCategoryList = ({
|
|||||||
</Popover>
|
</Popover>
|
||||||
),
|
),
|
||||||
className: 'actions',
|
className: 'actions',
|
||||||
width: 50
|
width: 50,
|
||||||
// canResize: false
|
// canResize: false
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
@@ -73,6 +87,7 @@ const ItemsCategoryList = ({
|
|||||||
onFetchData && onFetchData();
|
onFetchData && onFetchData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingIndicator spinnerSize={30}>
|
<LoadingIndicator spinnerSize={30}>
|
||||||
<DataTable
|
<DataTable
|
||||||
@@ -81,6 +96,8 @@ const ItemsCategoryList = ({
|
|||||||
onFetchData={handelFetchData}
|
onFetchData={handelFetchData}
|
||||||
manualSortBy={true}
|
manualSortBy={true}
|
||||||
selectionColumn={true}
|
selectionColumn={true}
|
||||||
|
expandable={true}
|
||||||
|
treeGraph={true}
|
||||||
/>
|
/>
|
||||||
</LoadingIndicator>
|
</LoadingIndicator>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import React from 'react';
|
|||||||
import PreferencesTopbar from 'components/Preferences/PreferencesTopbar';
|
import PreferencesTopbar from 'components/Preferences/PreferencesTopbar';
|
||||||
import PreferencesContentRoute from 'components/Preferences/PreferencesContentRoute';
|
import PreferencesContentRoute from 'components/Preferences/PreferencesContentRoute';
|
||||||
|
|
||||||
export default function() {
|
export default function () {
|
||||||
return (
|
return (
|
||||||
<div className="dashboard-content dashboard-content--preferences">
|
<div className='dashboard-content dashboard-content--preferences'>
|
||||||
<PreferencesTopbar pageTitle={"asdad"}/>
|
<PreferencesTopbar pageTitle={'asdad'} />
|
||||||
|
|
||||||
<div class="dashboard__preferences-content">
|
<div className='dashboard__preferences-content'>
|
||||||
<PreferencesContentRoute />
|
<PreferencesContentRoute />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
|
import { Scrollbar } from 'react-scrollbars-custom';
|
||||||
|
|
||||||
export default function SidebarContainer(props) {
|
export default function SidebarContainer(props) {
|
||||||
return (
|
return (
|
||||||
<div className="sidebar" id="sidebar">
|
<div className='sidebar' id='sidebar'>
|
||||||
<div class="sidebar__inner">
|
<Scrollbar noDefaultStyles={true}>
|
||||||
{props.children}
|
<div className='sidebar__inner'>{props.children}</div>
|
||||||
</div>
|
</Scrollbar>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export default function SidebarMenu() {
|
|||||||
dropdownType={item.dropdownType || 'collapse'}
|
dropdownType={item.dropdownType || 'collapse'}
|
||||||
caretIconSize={15}
|
caretIconSize={15}
|
||||||
onClick={handleItemClick}
|
onClick={handleItemClick}
|
||||||
callapseActive={!!isActive}
|
// callapseActive={!!isActive}
|
||||||
className={classNames({ 'is-active': isActive })} />
|
className={classNames({ 'is-active': isActive })} />
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,31 +3,31 @@ import {
|
|||||||
fetchItemCategories,
|
fetchItemCategories,
|
||||||
submitItemCategory,
|
submitItemCategory,
|
||||||
deleteItemCategory,
|
deleteItemCategory,
|
||||||
editItemCategory
|
editItemCategory,
|
||||||
} from 'store/itemCategories/itemsCategory.actions';
|
} from 'store/itemCategories/itemsCategory.actions';
|
||||||
import { getDialogPayload } from 'store/dashboard/dashboard.reducer';
|
import { getDialogPayload } from 'store/dashboard/dashboard.reducer';
|
||||||
import { getCategoryId } from 'store/itemCategories/itemsCategory.reducer';
|
import { getCategoryId } from 'store/itemCategories/itemsCategory.reducer';
|
||||||
|
|
||||||
export const mapStateToProps = (state, props) => {
|
export const mapStateToProps = (state, props) => {
|
||||||
const dialogPayload = getDialogPayload(state, 'item-form');
|
const dialogPayload = getDialogPayload(state, 'item-form');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
categories: state.itemCategories.categories,
|
categories: state.itemCategories.categories,
|
||||||
categoriesList: Object.values(state.itemCategories.categories),
|
count: 1,
|
||||||
name: 'item-form',
|
name: 'item-form',
|
||||||
payload: { action: 'new', id: null },
|
payload: { action: 'new', id: null },
|
||||||
editItemCategory:
|
editItemCategory:
|
||||||
dialogPayload && dialogPayload.action === 'edit'
|
dialogPayload && dialogPayload.action === 'edit'
|
||||||
? state.itemCategories.categories[dialogPayload.id]
|
? state.itemCategories.categories[dialogPayload.id]
|
||||||
: {},
|
: {},
|
||||||
getCategoryId: id => getCategoryId(state, id)
|
getCategoryId: (id) => getCategoryId(state, id),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
export const mapDispatchToProps = dispatch => ({
|
requestSubmitItemCategory: (form) => dispatch(submitItemCategory({ form })),
|
||||||
requestSubmitItemCategory: form => dispatch(submitItemCategory({ form })),
|
|
||||||
requestFetchItemCategories: () => dispatch(fetchItemCategories()),
|
requestFetchItemCategories: () => dispatch(fetchItemCategories()),
|
||||||
requestDeleteItemCategory: id => dispatch(deleteItemCategory(id)),
|
requestDeleteItemCategory: (id) => dispatch(deleteItemCategory(id)),
|
||||||
requestEditItemCategory: (id, form) => dispatch(editItemCategory(id, form))
|
requestEditItemCategory: (id, form) => dispatch(editItemCategory(id, form)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps);
|
export default connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import {
|
||||||
|
FetchOption,
|
||||||
|
FetchOptions,
|
||||||
|
submitOptions,
|
||||||
|
} from 'store/settings/settings.actions';
|
||||||
|
|
||||||
|
|
||||||
export const mapStateToProps = (state, props) => {
|
export const mapStateToProps = (state, props) => {
|
||||||
return {
|
return {
|
||||||
@@ -7,7 +13,8 @@ export const mapStateToProps = (state, props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
|
requestSubmitOptions: (form) => dispatch(submitOptions({ form })),
|
||||||
|
requestFetchOptions: () => dispatch(FetchOptions({})),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps);
|
export default connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import { fetchUsers, fetchUser, deleteUser } from 'store/users/users.actions';
|
||||||
fetchUsers,
|
|
||||||
fetchUser,
|
|
||||||
deleteUser,
|
|
||||||
} from 'store/users/users.actions';
|
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
|
||||||
export const mapStateToProps = (state, props) => ({
|
export const mapStateToProps = (state, props) => ({
|
||||||
usersList: state.users.list
|
usersList: state.users.list.results,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
openDialog: (name, payload) => dispatch({ type: t.OPEN_DIALOG, name, payload }),
|
openDialog: (name, payload) =>
|
||||||
closeDialog: (name, payload) => dispatch({ type: t.CLOSE_DIALOG, name, payload }),
|
dispatch({ type: t.OPEN_DIALOG, name, payload }),
|
||||||
|
closeDialog: (name, payload) =>
|
||||||
|
dispatch({ type: t.CLOSE_DIALOG, name, payload }),
|
||||||
|
|
||||||
fetchUsers: () => dispatch(fetchUsers({ })),
|
fetchUsers: () => dispatch(fetchUsers({})),
|
||||||
fetchUser: (id) => dispatch(fetchUser({ id })),
|
fetchUser: (id) => dispatch(fetchUser({ id })),
|
||||||
deleteUser: (id) => dispatch(deleteUser({ id })),
|
deleteUser: (id) => dispatch(deleteUser({ id })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps);
|
export default connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ function AccountFormDialog({
|
|||||||
requestEditAccount({
|
requestEditAccount({
|
||||||
payload: payload.id,
|
payload: payload.id,
|
||||||
form: { ...omit(values, [...exclude, 'account_type_id']) }
|
form: { ...omit(values, [...exclude, 'account_type_id']) }
|
||||||
}).then(response => {
|
}).then((response) => {
|
||||||
closeDialog(name);
|
closeDialog(name);
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: 'the_account_has_been_edited'
|
message: 'the_account_has_been_edited'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from 'react-intl';
|
||||||
import {useFormik} from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@@ -18,8 +18,12 @@ import UserFormDialogConnect from 'connectors/UserFormDialog.connector';
|
|||||||
import DialogReduxConnect from 'components/DialogReduxConnect';
|
import DialogReduxConnect from 'components/DialogReduxConnect';
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
import useAsync from 'hooks/async';
|
import useAsync from 'hooks/async';
|
||||||
import {objectKeysTransform} from 'utils';
|
import { objectKeysTransform } from 'utils';
|
||||||
import {pick, snakeCase} from 'lodash';
|
import { pick, snakeCase } from 'lodash';
|
||||||
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import Icon from 'components/Icon';
|
||||||
|
import { compose } from 'utils';
|
||||||
|
|
||||||
function UserFormDialog({
|
function UserFormDialog({
|
||||||
fetchUser,
|
fetchUser,
|
||||||
@@ -34,27 +38,21 @@ function UserFormDialog({
|
|||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const fetchHook = useAsync(async () => {
|
const fetchHook = useAsync(async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
...(payload.action === 'edit') ? [
|
...(payload.action === 'edit' ? [fetchUser(payload.user.id)] : []),
|
||||||
fetchUser(payload.user.id),
|
|
||||||
] : [],
|
|
||||||
]);
|
]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
first_name: Yup.string().required(),
|
|
||||||
last_name: Yup.string().required(),
|
|
||||||
email: Yup.string().email().required(),
|
email: Yup.string().email().required(),
|
||||||
phone_number: Yup.string().required(),
|
|
||||||
password: Yup.string().min(5).required(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
status: 1,
|
status: 1,
|
||||||
...payload.action === 'edit' &&
|
...(payload.action === 'edit' &&
|
||||||
pick(
|
pick(
|
||||||
objectKeysTransform(payload.user, snakeCase),
|
objectKeysTransform(payload.user, snakeCase),
|
||||||
Object.keys(validationSchema.fields)
|
Object.keys(validationSchema.fields)
|
||||||
),
|
)),
|
||||||
password: '',
|
password: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,113 +82,76 @@ function UserFormDialog({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const { values, errors, touched } = useMemo(() => formik, [formik]);
|
||||||
|
|
||||||
const statusOptions = [
|
const statusOptions = [
|
||||||
{value: 1, label: 'Active'},
|
{ value: 1, label: 'Active' },
|
||||||
{value: 2, label: 'Inactive'},
|
{ value: 2, label: 'Inactive' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const onDialogOpening = () => { fetchHook.execute(); };
|
const onDialogOpening = () => {
|
||||||
|
fetchHook.execute();
|
||||||
|
};
|
||||||
|
|
||||||
const onDialogClosed = () => {
|
const onDialogClosed = () => {
|
||||||
formik.resetForm();
|
formik.resetForm();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => { closeDialog(name); };
|
const handleClose = () => {
|
||||||
|
closeDialog(name);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
isOpen={isOpen}
|
|
||||||
name={name}
|
name={name}
|
||||||
title={payload.action === 'edit' ? 'Edit User' : 'New User'}
|
title={payload.action === 'edit' ? 'Edit invite' : 'New invite'}
|
||||||
|
className={classNames({
|
||||||
|
'dialog--loading': fetchHook.pending,
|
||||||
|
'dialog--invite-form': true,
|
||||||
|
})}
|
||||||
|
autoFocus={true}
|
||||||
|
canEscapeKeyClose={true}
|
||||||
|
isOpen={isOpen}
|
||||||
isLoading={fetchHook.pending}
|
isLoading={fetchHook.pending}
|
||||||
onClosed={onDialogClosed}
|
onClosed={onDialogClosed}
|
||||||
onOpening={onDialogOpening}>
|
onOpening={onDialogOpening}
|
||||||
|
>
|
||||||
<form onSubmit={formik.handleSubmit}>
|
<form onSubmit={formik.handleSubmit}>
|
||||||
<div className={Classes.DIALOG_BODY}>
|
<div className={Classes.DIALOG_BODY}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={'First Name'}
|
label={'Email'}
|
||||||
className={'form-group--first-name'}
|
className={'form-group--email'}
|
||||||
intent={formik.errors.first_name && Intent.DANGER}
|
intent={errors.email && touched.email && Intent.DANGER}
|
||||||
helperText={formik.errors.first_name && formik.errors.first_name}
|
helperText={<ErrorMessage name='email' {...formik} />}
|
||||||
inline={true}>
|
inline={true}
|
||||||
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
intent={formik.errors.first_name && Intent.DANGER}
|
medium={true}
|
||||||
{...formik.getFieldProps('first_name')} />
|
intent={errors.email && touched.email && Intent.DANGER}
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
|
||||||
label={'Last Name'}
|
|
||||||
className={'form-group--last-name'}
|
|
||||||
intent={formik.errors.last_name && Intent.DANGER}
|
|
||||||
helperText={formik.errors.last_name && formik.errors.last_name}
|
|
||||||
inline={true}>
|
|
||||||
|
|
||||||
<InputGroup
|
|
||||||
intent={formik.errors.last_name && Intent.DANGER}
|
|
||||||
{...formik.getFieldProps('last_name')} />
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={'Email'}
|
label={'Email'}
|
||||||
className={'form-group--email'}
|
className={'form-group--email'}
|
||||||
intent={formik.errors.email && Intent.DANGER}
|
intent={errors.email && touched.email && Intent.DANGER}
|
||||||
helperText={formik.errors.email && formik.errors.email}
|
helperText={<ErrorMessage name='email' {...formik} />}
|
||||||
inline={true}>
|
inline={true}
|
||||||
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
intent={formik.errors.email && Intent.DANGER}
|
medium={true}
|
||||||
{...formik.getFieldProps('email')} />
|
intent={errors.email && touched.email && Intent.DANGER}
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormGroup
|
<div className={Classes.DIALOG_FOOTER}>
|
||||||
label={'Phone Number'}
|
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||||
className={'form-group--phone-number'}
|
<Button onClick={handleClose}>Close</Button>
|
||||||
intent={formik.errors.phone_number && Intent.DANGER}
|
<Button intent={Intent.PRIMARY} type='submit'>
|
||||||
helperText={formik.errors.phone_number && formik.errors.phone_number}
|
{payload.action === 'edit' ? 'Edit' : 'invite'}
|
||||||
inline={true}>
|
</Button>
|
||||||
|
|
||||||
<InputGroup
|
|
||||||
intent={formik.errors.phone_number && Intent.DANGER}
|
|
||||||
{...formik.getFieldProps('phone_number')} />
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup
|
|
||||||
label={'Password'}
|
|
||||||
className={'form-group--password'}
|
|
||||||
intent={formik.errors.password && Intent.DANGER}
|
|
||||||
helperText={formik.errors.password && formik.errors.password}
|
|
||||||
inline={true}>
|
|
||||||
|
|
||||||
<InputGroup
|
|
||||||
intent={formik.errors.password && Intent.DANGER}
|
|
||||||
className={Classes.FILL}
|
|
||||||
{...formik.getFieldProps('password')} />
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup
|
|
||||||
label={'Status'}
|
|
||||||
className={'form-group--status'}
|
|
||||||
intent={formik.errors.status && Intent.DANGER}
|
|
||||||
helperText={formik.errors.status && formik.errors.status}
|
|
||||||
inline={true}>
|
|
||||||
|
|
||||||
<HTMLSelect
|
|
||||||
options={statusOptions}
|
|
||||||
className={Classes.FILL}
|
|
||||||
{...formik.getFieldProps(`status`)} />
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<div className={Classes.DIALOG_FOOTER}>
|
|
||||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
|
||||||
<Button onClick={handleClose}>Close</Button>
|
|
||||||
<Button intent={Intent.PRIMARY} type="submit">
|
|
||||||
{ payload.action === 'edit' ? 'Edit' : 'Submit' }
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -198,4 +159,7 @@ function UserFormDialog({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserFormDialogConnect(DialogReduxConnect(UserFormDialog));
|
export default compose(
|
||||||
|
UserFormDialogConnect,
|
||||||
|
DialogReduxConnect
|
||||||
|
)(UserFormDialog);
|
||||||
|
|||||||
@@ -3,21 +3,45 @@ import {} from 'reselect';
|
|||||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
import { NavbarGroup, Button, Classes, Intent } from '@blueprintjs/core';
|
import {
|
||||||
|
NavbarGroup,
|
||||||
|
Button,
|
||||||
|
Classes,
|
||||||
|
Intent,
|
||||||
|
Popover,
|
||||||
|
Position,
|
||||||
|
PopoverInteractionKind,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
|
import classNames from 'classnames';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import DashboardConnect from 'connectors/Dashboard.connector';
|
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||||
import ItemsCategoryConnect from 'connectors/ItemsCategory.connect';
|
import ItemsCategoryConnect from 'connectors/ItemsCategory.connect';
|
||||||
import DialogConnect from 'connectors/Dialog.connector';
|
import DialogConnect from 'connectors/Dialog.connector';
|
||||||
|
import FilterDropdown from 'components/FilterDropdown';
|
||||||
|
import ResourceConnect from 'connectors/Resource.connector';
|
||||||
|
|
||||||
const ItemsCategoryActionsBar = ({ openDialog, onDeleteCategory }) => {
|
const ItemsCategoryActionsBar = ({
|
||||||
|
openDialog,
|
||||||
|
onDeleteCategory,
|
||||||
|
onFilterChanged,
|
||||||
|
getResourceFields,
|
||||||
|
}) => {
|
||||||
const onClickNewCategory = () => {
|
const onClickNewCategory = () => {
|
||||||
openDialog('item-form', {});
|
openDialog('item-form', {});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteCategory = category => {
|
const handleDeleteCategory = (category) => {
|
||||||
onDeleteCategory(category);
|
onDeleteCategory(category);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const categoriesFields = getResourceFields('itemCategories');
|
||||||
|
|
||||||
|
const filterDropdown = FilterDropdown({
|
||||||
|
fields: categoriesFields,
|
||||||
|
onFilterChange: (filterConditions) => {
|
||||||
|
onFilterChanged && onFilterChanged(filterConditions);
|
||||||
|
},
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -27,6 +51,17 @@ const ItemsCategoryActionsBar = ({ openDialog, onDeleteCategory }) => {
|
|||||||
text='New Category'
|
text='New Category'
|
||||||
onClick={onClickNewCategory}
|
onClick={onClickNewCategory}
|
||||||
/>
|
/>
|
||||||
|
<Popover
|
||||||
|
content={filterDropdown}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className={classNames(Classes.MINIMAL, 'button--filter')}
|
||||||
|
text='Filter'
|
||||||
|
icon={<Icon icon='filter' />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
@@ -54,5 +89,6 @@ const ItemsCategoryActionsBar = ({ openDialog, onDeleteCategory }) => {
|
|||||||
export default compose(
|
export default compose(
|
||||||
DialogConnect,
|
DialogConnect,
|
||||||
DashboardConnect,
|
DashboardConnect,
|
||||||
ItemsCategoryConnect
|
ItemsCategoryConnect,
|
||||||
|
ResourceConnect
|
||||||
)(ItemsCategoryActionsBar);
|
)(ItemsCategoryActionsBar);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useCallback, useMemo } from 'react';
|
import React, { useState, useCallback, useMemo, useEffect } from 'react';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import {
|
import {
|
||||||
@@ -10,16 +10,24 @@ import {
|
|||||||
Classes,
|
Classes,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
|
|
||||||
import { optionsMapToArray, momentFormatter } from 'utils';
|
import { optionsMapToArray, momentFormatter, optionsArrayToMap } from 'utils';
|
||||||
import { TimezonePicker } from '@blueprintjs/timezone';
|
import { TimezonePicker } from '@blueprintjs/timezone';
|
||||||
import { Select } from '@blueprintjs/select';
|
import { Select } from '@blueprintjs/select';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ErrorMessage from 'components/ErrorMessage';
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
|
import { compose } from 'utils';
|
||||||
|
import SettingsConnect from 'connectors/Settings.connect';
|
||||||
|
import AppToaster from 'components/AppToaster';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import useAsync from 'hooks/async';
|
||||||
|
|
||||||
function GeneralPreferences(props) {
|
function GeneralPreferences({
|
||||||
|
organizationSettings,
|
||||||
|
requestSubmitOptions,
|
||||||
|
requestFetchOptions,
|
||||||
|
}) {
|
||||||
const [selectedItems, setSelectedItems] = useState({});
|
const [selectedItems, setSelectedItems] = useState({});
|
||||||
const [disableItems, setDisableItems] = useState(false);
|
|
||||||
const [timeZone, setTimeZone] = useState('');
|
const [timeZone, setTimeZone] = useState('');
|
||||||
|
|
||||||
const businessLocation = [
|
const businessLocation = [
|
||||||
@@ -28,8 +36,8 @@ function GeneralPreferences(props) {
|
|||||||
{ id: 212, name: 'Morocco', code: 'MA' },
|
{ id: 212, name: 'Morocco', code: 'MA' },
|
||||||
];
|
];
|
||||||
const languagesDisplay = [
|
const languagesDisplay = [
|
||||||
{ name: 'EN', label: 'English' },
|
{ id: 0, name: 'EN', label: 'English' },
|
||||||
{ name: 'Arb', label: 'Arabic' },
|
{ id: 1, name: 'Arb', label: 'Arabic' },
|
||||||
];
|
];
|
||||||
const currencies = [
|
const currencies = [
|
||||||
{ id: 0, name: 'US Dollar', code: 'USD' },
|
{ id: 0, name: 'US Dollar', code: 'USD' },
|
||||||
@@ -41,34 +49,59 @@ function GeneralPreferences(props) {
|
|||||||
{ id: 1, name: 'August-December', label: 'August-December' },
|
{ id: 1, name: 'August-December', label: 'August-December' },
|
||||||
];
|
];
|
||||||
const dateFormat = [
|
const dateFormat = [
|
||||||
{ name: '04/11/2020', format: 'MM-DD-YY' },
|
{ id: 1, name: '04/11/2020', format: 'MM-DD-YY' },
|
||||||
{ name: '2020/03/21', format: 'YY/MM/DD' },
|
{ id: 3, name: '2020/03/21', format: 'YY/MM/DD' },
|
||||||
{ name: 'Apr 11, 2020', format: 'MMMM yyyy' },
|
{ id: 4, name: 'Apr 11, 2020', format: 'MMMM yyyy' },
|
||||||
{ name: 'Saturday, Apr 11, 2020', format: 'EEEE, MMM d, yyyy' },
|
{ id: 6, name: 'Saturday, Apr 11, 2020', format: 'EEEE, MMM d, yyyy' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
organization_name: Yup.string().required('required field'),
|
name: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||||
organization_industry: Yup.string().required('required field'),
|
industry: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||||
business_location: Yup.string().required('required field'),
|
location: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||||
base_currency: Yup.string().required('required field'),
|
base_currency: Yup.string().required(
|
||||||
fiscal_year: Yup.string().required('required field'),
|
intl.formatMessage({ id: 'required' })
|
||||||
language: Yup.string().required('required field'),
|
),
|
||||||
time_zone: Yup.date().required('required field'),
|
fiscal_year: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||||
date_format: Yup.date().required('required field'),
|
language: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||||
|
// time_zone: Yup.object().required(intl.formatMessage({ id: 'required' })),
|
||||||
|
date_format: Yup.date().required(intl.formatMessage({ id: 'required' })),
|
||||||
});
|
});
|
||||||
|
console.log(organizationSettings.name);
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
initialValues: {},
|
initialValues: {
|
||||||
|
...organizationSettings,
|
||||||
|
},
|
||||||
validationSchema: validationSchema,
|
validationSchema: validationSchema,
|
||||||
onSubmit: (values) => {
|
|
||||||
|
onSubmit: (values, { setSubmitting }) => {
|
||||||
const options = optionsMapToArray(values).map((option) => {
|
const options = optionsMapToArray(values).map((option) => {
|
||||||
return { ...option, group: 'general' };
|
return { key: option.key, ...option, group: 'organization' };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
requestSubmitOptions({ options })
|
||||||
|
.then((response) => {
|
||||||
|
AppToaster.show({
|
||||||
|
message: 'The_Options_has_been_Submit',
|
||||||
|
});
|
||||||
|
setSubmitting(false);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setSubmitting(false);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { errors, values, touched } = useMemo(() => formik, [formik]);
|
const { errors, values, touched } = useMemo(() => formik, [formik]);
|
||||||
|
|
||||||
|
const fetchHook = useAsync(async () => {
|
||||||
|
await Promise.all([requestFetchOptions()]);
|
||||||
|
});
|
||||||
|
|
||||||
const businessLocationItem = (item, { handleClick }) => (
|
const businessLocationItem = (item, { handleClick }) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
className={'preferences-menu'}
|
className={'preferences-menu'}
|
||||||
@@ -107,7 +140,7 @@ function GeneralPreferences(props) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const data_Format = (item, { handleClick }) => (
|
const date_format = (item, { handleClick }) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
className={'preferences-menu'}
|
className={'preferences-menu'}
|
||||||
key={item.id}
|
key={item.id}
|
||||||
@@ -126,6 +159,7 @@ function GeneralPreferences(props) {
|
|||||||
formik.setFieldValue(filedName, filed.name);
|
formik.setFieldValue(filedName, filed.name);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSelectedItemLabel = (filedName, defaultLabel) => {
|
const getSelectedItemLabel = (filedName, defaultLabel) => {
|
||||||
return typeof selectedItems[filedName] !== 'undefined'
|
return typeof selectedItems[filedName] !== 'undefined'
|
||||||
? selectedItems[filedName].name
|
? selectedItems[filedName].name
|
||||||
@@ -140,42 +174,26 @@ function GeneralPreferences(props) {
|
|||||||
<FormGroup
|
<FormGroup
|
||||||
label={'Organization Name'}
|
label={'Organization Name'}
|
||||||
inline={true}
|
inline={true}
|
||||||
intent={
|
intent={errors.name && touched.name && Intent.DANGER}
|
||||||
errors.organization_name &&
|
helperText={<ErrorMessage name='name' {...formik} />}
|
||||||
touched.organization_name &&
|
|
||||||
Intent.DANGER
|
|
||||||
}
|
|
||||||
helperText={<ErrorMessage name='organization_name' {...formik} />}
|
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
medium={true}
|
medium={'true'}
|
||||||
intent={
|
intent={errors.name && touched.name && Intent.DANGER}
|
||||||
errors.organization_name &&
|
{...formik.getFieldProps('name')}
|
||||||
touched.organization_name &&
|
|
||||||
Intent.DANGER
|
|
||||||
}
|
|
||||||
{...formik.getFieldProps('organization_name')}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={'Organization Industry'}
|
label={'Organization Industry'}
|
||||||
inline={true}
|
inline={true}
|
||||||
intent={
|
intent={errors.industry && touched.industry && Intent.DANGER}
|
||||||
errors.organization_industry &&
|
helperText={<ErrorMessage name='industry' {...formik} />}
|
||||||
touched.organization_industry &&
|
|
||||||
Intent.DANGER
|
|
||||||
}
|
|
||||||
helperText={<ErrorMessage name='organization_industry' {...formik} />}
|
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
medium={true}
|
medium={'true'}
|
||||||
intent={
|
intent={errors.industry && touched.industry && Intent.DANGER}
|
||||||
errors.organization_industry &&
|
{...formik.getFieldProps('industry')}
|
||||||
touched.organization_industry &&
|
|
||||||
Intent.DANGER
|
|
||||||
}
|
|
||||||
{...formik.getFieldProps('organization_industry')}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
@@ -187,26 +205,22 @@ function GeneralPreferences(props) {
|
|||||||
Classes.FILL
|
Classes.FILL
|
||||||
)}
|
)}
|
||||||
inline={true}
|
inline={true}
|
||||||
helperText={<ErrorMessage name='business_location' {...formik} />}
|
helperText={<ErrorMessage name='location' {...formik} />}
|
||||||
intent={
|
intent={errors.location && touched.location && Intent.DANGER}
|
||||||
errors.business_location &&
|
|
||||||
touched.business_location &&
|
|
||||||
Intent.DANGER
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
items={businessLocation}
|
items={businessLocation}
|
||||||
noResults={<MenuItem disabled={true} text='No result.' />}
|
noResults={<MenuItem disabled={true} text='No result.' />}
|
||||||
itemRenderer={businessLocationItem}
|
itemRenderer={businessLocationItem}
|
||||||
popoverProps={{ minimal: true }}
|
popoverProps={{ minimal: true }}
|
||||||
onItemSelect={onItemsSelect('business_location')}
|
onItemSelect={onItemsSelect('location')}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
fill={true}
|
fill={true}
|
||||||
rightIcon='caret-down'
|
rightIcon='caret-down'
|
||||||
text={getSelectedItemLabel(
|
text={getSelectedItemLabel(
|
||||||
'business_location',
|
'location',
|
||||||
'Business Location'
|
organizationSettings.location
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Select>
|
</Select>
|
||||||
@@ -235,7 +249,10 @@ function GeneralPreferences(props) {
|
|||||||
<Button
|
<Button
|
||||||
fill={true}
|
fill={true}
|
||||||
rightIcon='caret-down'
|
rightIcon='caret-down'
|
||||||
text={getSelectedItemLabel('base_currency', 'Base Currency')}
|
text={getSelectedItemLabel(
|
||||||
|
'base_currency',
|
||||||
|
organizationSettings.base_currency
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Select>
|
</Select>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
@@ -261,7 +278,10 @@ function GeneralPreferences(props) {
|
|||||||
<Button
|
<Button
|
||||||
fill={true}
|
fill={true}
|
||||||
rightIcon='caret-down'
|
rightIcon='caret-down'
|
||||||
text={getSelectedItemLabel('fiscal_year', 'Fiscal Year')}
|
text={getSelectedItemLabel(
|
||||||
|
'fiscal_year',
|
||||||
|
organizationSettings.fiscal_year
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Select>
|
</Select>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
@@ -286,11 +306,13 @@ function GeneralPreferences(props) {
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
rightIcon='caret-down'
|
rightIcon='caret-down'
|
||||||
text={getSelectedItemLabel('language', 'English')}
|
text={getSelectedItemLabel(
|
||||||
|
'language',
|
||||||
|
organizationSettings.language
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Select>
|
</Select>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={'Time Zone'}
|
label={'Time Zone'}
|
||||||
inline={true}
|
inline={true}
|
||||||
@@ -309,30 +331,30 @@ function GeneralPreferences(props) {
|
|||||||
valueDisplayFormat='composite'
|
valueDisplayFormat='composite'
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={'Date Format'}
|
label={'Date Format'}
|
||||||
inline={true}
|
inline={true}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'form-group--date-format',
|
'form-group--language',
|
||||||
'form-group--select-list',
|
'form-group--select-list',
|
||||||
Classes.FILL
|
Classes.FILL
|
||||||
)}
|
)}
|
||||||
intent={errors.date_format && touched.data_Format && Intent.DANGER}
|
intent={errors.date_format && touched.date_format && Intent.DANGER}
|
||||||
helperText={<ErrorMessage name='date_format' {...formik} />}
|
helperText={<ErrorMessage name='date_format' {...formik} />}
|
||||||
minimal={true}
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
items={dateFormat}
|
items={dateFormat}
|
||||||
noResults={<MenuItem disabled={true} text='No result.' />}
|
noResults={<MenuItem disabled={true} text='No result.' />}
|
||||||
itemRenderer={data_Format}
|
itemRenderer={date_format}
|
||||||
popoverProps={{ minimal: true }}
|
popoverProp={{ minimal: true }}
|
||||||
onItemSelect={onItemsSelect('date_format')}
|
onItemSelect={onItemsSelect('date_format')}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
fill={true}
|
|
||||||
rightIcon='caret-down'
|
rightIcon='caret-down'
|
||||||
text={getSelectedItemLabel('fiscal_year', 'Fiscal Year')}
|
text={getSelectedItemLabel(
|
||||||
|
'date_format',
|
||||||
|
organizationSettings.date_format
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Select>
|
</Select>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
@@ -352,4 +374,4 @@ function GeneralPreferences(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GeneralPreferences;
|
export default compose(SettingsConnect)(GeneralPreferences);
|
||||||
|
|||||||
@@ -29,17 +29,18 @@ function UsersPreferences({
|
|||||||
onChange={onChangeTabs}>
|
onChange={onChangeTabs}>
|
||||||
<Tab id="users" title="Users" />
|
<Tab id="users" title="Users" />
|
||||||
<Tab id="roles" title="Roles" />
|
<Tab id="roles" title="Roles" />
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
<div class="preferences__tabs-extra-actions">
|
<div class="preferences__tabs-extra-actions">
|
||||||
<Button
|
<Button
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
onClick={onClickNewUser}>New User</Button>
|
onClick={onClickNewUser}>New invite</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
onClick={onClickNewUser}>New Role</Button>
|
onClick={onClickNewUser}>New Role</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
<PreferencesSubContent preferenceTab="users" />
|
<PreferencesSubContent preferenceTab="users" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import React, {useState} from 'react';
|
import React, { useState, useMemo, useCallback } from 'react';
|
||||||
import {useAsync} from 'react-use';
|
import { useAsync } from 'react-use';
|
||||||
import {
|
import DataTable from 'components/DataTable';
|
||||||
GridComponent,
|
|
||||||
ColumnsDirective,
|
|
||||||
ColumnDirective,
|
|
||||||
} from '@syncfusion/ej2-react-grids';
|
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Popover,
|
Popover,
|
||||||
@@ -17,9 +13,12 @@ import {
|
|||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import LoadingIndicator from 'components/LoadingIndicator';
|
||||||
import {snakeCase} from 'lodash';
|
import { snakeCase } from 'lodash';
|
||||||
import connector from 'connectors/UsersList.connector';
|
import UserListConnect from 'connectors/UsersList.connector';
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
|
import { compose } from 'utils';
|
||||||
|
import DialogConnect from 'connectors/Dialog.connector';
|
||||||
|
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||||
|
|
||||||
function UsersListPreferences({
|
function UsersListPreferences({
|
||||||
fetchUsers,
|
fetchUsers,
|
||||||
@@ -27,22 +26,23 @@ function UsersListPreferences({
|
|||||||
openDialog,
|
openDialog,
|
||||||
closeDialog,
|
closeDialog,
|
||||||
deleteUser,
|
deleteUser,
|
||||||
|
onFetchData,
|
||||||
}) {
|
}) {
|
||||||
const [deleteUserState, setDeleteUserState] = useState(false);
|
const [deleteUserState, setDeleteUserState] = useState(false);
|
||||||
const [inactiveUserState, setInactiveUserState] = useState(false);
|
const [inactiveUserState, setInactiveUserState] = useState(false);
|
||||||
|
|
||||||
const asyncHook = useAsync(async () => {
|
const asyncHook = useAsync(async () => {
|
||||||
await Promise.all([
|
await Promise.all([fetchUsers()]);
|
||||||
fetchUsers(),
|
|
||||||
]);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onInactiveUser = (user) => {
|
const onInactiveUser = (user) => {};
|
||||||
|
|
||||||
|
const onDeleteUser = (user) => {
|
||||||
|
setDeleteUserState(user);
|
||||||
|
};
|
||||||
|
const handleCancelUserDelete = () => {
|
||||||
|
setDeleteUserState(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDeleteUser = (user) => { setDeleteUserState(user); };
|
|
||||||
const handleCancelUserDelete = () => { setDeleteUserState(false); };
|
|
||||||
|
|
||||||
const onEditUser = (user) => () => {
|
const onEditUser = (user) => () => {
|
||||||
const form = Object.keys(user).reduce((obj, key) => {
|
const form = Object.keys(user).reduce((obj, key) => {
|
||||||
@@ -51,11 +51,13 @@ function UsersListPreferences({
|
|||||||
return obj;
|
return obj;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
openDialog('user-form', { action: 'edit', user: form, });
|
openDialog('user-form', { action: 'edit', user: form });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleConfirmUserDelete = () => {
|
const handleConfirmUserDelete = () => {
|
||||||
if (!deleteUserState) { return; }
|
if (!deleteUserState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
deleteUser(deleteUserState.id).then((response) => {
|
deleteUser(deleteUserState.id).then((response) => {
|
||||||
setDeleteUserState(false);
|
setDeleteUserState(false);
|
||||||
@@ -65,79 +67,96 @@ function UsersListPreferences({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const actionMenuList = (user) =>
|
const actionMenuList = (user) => (
|
||||||
(<Menu>
|
<Menu>
|
||||||
<MenuItem text="Edit User" onClick={onEditUser(user)} />
|
<MenuItem text='Edit User' onClick={onEditUser(user)} />
|
||||||
<MenuItem text="New Account" />
|
<MenuItem text='New Account' />
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
<MenuItem text="Inactivate User" onClick={() => onInactiveUser(user)} />
|
<MenuItem text='Inactivate User' onClick={() => onInactiveUser(user)} />
|
||||||
<MenuItem text="Delete User" onClick={() => onDeleteUser(user)} />
|
<MenuItem text='Delete User' onClick={() => onDeleteUser(user)} />
|
||||||
</Menu>);
|
</Menu>
|
||||||
|
);
|
||||||
|
console.log(usersList, 'X');
|
||||||
|
|
||||||
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
id: 'full_name',
|
||||||
|
Header: 'Full Name',
|
||||||
|
accessor: 'full_name',
|
||||||
|
width: 170,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'email',
|
||||||
|
Header: 'Email',
|
||||||
|
accessor: 'email',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'phone_number',
|
||||||
|
Header: 'Phone Number',
|
||||||
|
accessor: 'phone_number',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'active',
|
||||||
|
Header: 'Status',
|
||||||
|
accessor: (user) =>
|
||||||
|
user.active ? <span>Active</span> : <span>Inactivate</span>,
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
Header: '',
|
||||||
|
Cell: ({ cell }) => (
|
||||||
|
<Popover
|
||||||
|
content={actionMenuList(cell.row.original)}
|
||||||
|
position={Position.RIGHT_TOP}
|
||||||
|
>
|
||||||
|
<Button icon={<Icon icon='ellipsis-h' />} />
|
||||||
|
</Popover>
|
||||||
|
),
|
||||||
|
className: 'actions',
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[actionMenuList]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handelDataTableFetchData = useCallback(() => {
|
||||||
|
onFetchData && onFetchData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
field: '',
|
|
||||||
headerText: 'Avatar',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'fullName',
|
|
||||||
headerText: 'Full Name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'email',
|
|
||||||
headerText: 'Email',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'phoneNumber',
|
|
||||||
headerText: 'Phone Number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: '',
|
|
||||||
headerText: 'Status',
|
|
||||||
template: (user) => user.active
|
|
||||||
? (<span>Active</span>) : (<span>Inactive</span>)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
template: (user) => (
|
|
||||||
<Popover content={actionMenuList(user)} position={Position.RIGHT_BOTTOM}>
|
|
||||||
<Button icon={<Icon icon="ellipsis-h" />} />
|
|
||||||
</Popover>
|
|
||||||
),
|
|
||||||
}
|
|
||||||
]
|
|
||||||
return (
|
return (
|
||||||
<LoadingIndicator loading={asyncHook.loading}>
|
<LoadingIndicator>
|
||||||
<GridComponent
|
<DataTable
|
||||||
dataSource={{result: usersList.results}}>
|
columns={columns}
|
||||||
|
data={usersList}
|
||||||
<ColumnsDirective>
|
onFetchData={handelDataTableFetchData()}
|
||||||
{columns.map((column) => {
|
manualSortBy={true}
|
||||||
return (<ColumnDirective
|
expandable={false}
|
||||||
field={column.field}
|
/>
|
||||||
headerText={column.headerText}
|
|
||||||
template={column.template}
|
|
||||||
allowSorting={true}
|
|
||||||
customAttributes={column.customAttributes}
|
|
||||||
/>);
|
|
||||||
})}
|
|
||||||
</ColumnsDirective>
|
|
||||||
</GridComponent>
|
|
||||||
|
|
||||||
<Alert
|
<Alert
|
||||||
cancelButtonText="Cancel"
|
cancelButtonText='Cancel'
|
||||||
confirmButtonText="Move to Trash"
|
confirmButtonText='Move to Trash'
|
||||||
icon="trash"
|
icon='trash'
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
isOpen={deleteUserState}
|
isOpen={deleteUserState}
|
||||||
onCancel={handleCancelUserDelete}
|
onCancel={handleCancelUserDelete}
|
||||||
onConfirm={handleConfirmUserDelete}>
|
onConfirm={handleConfirmUserDelete}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
Are you sure you want to move <b>filename</b> to Trash? You will be
|
||||||
but it will become private to you.
|
able to restore it later, but it will become private to you.
|
||||||
</p>
|
</p>
|
||||||
</Alert>
|
</Alert>
|
||||||
</LoadingIndicator>
|
</LoadingIndicator>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connector(UsersListPreferences);
|
export default compose(
|
||||||
|
UserListConnect,
|
||||||
|
DialogConnect,
|
||||||
|
DashboardConnect
|
||||||
|
)(UsersListPreferences);
|
||||||
|
|||||||
@@ -2,5 +2,6 @@ export default {
|
|||||||
ITEMS_CATEGORY_LIST_SET: 'ITEMS_CATEGORY_LIST_SET',
|
ITEMS_CATEGORY_LIST_SET: 'ITEMS_CATEGORY_LIST_SET',
|
||||||
ITEMS_CATEGORY_DATA_TABLE: 'ITEMS_CATEGORY_DATA_TABLE',
|
ITEMS_CATEGORY_DATA_TABLE: 'ITEMS_CATEGORY_DATA_TABLE',
|
||||||
CATEGORY_DELETE: 'CATEGORY_DELETE',
|
CATEGORY_DELETE: 'CATEGORY_DELETE',
|
||||||
CLEAR_CATEGORY_FORM_ERRORS: 'CLEAR_CATEGORY_FORM_ERRORS'
|
CLEAR_CATEGORY_FORM_ERRORS: 'CLEAR_CATEGORY_FORM_ERRORS',
|
||||||
|
CATEGORY_COUNTER:'CATEGORY_COUNTER'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import ApiService from 'services/ApiService';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
|
export const submitOptions = ({ form }) => {
|
||||||
|
return (dispatch) => {
|
||||||
|
return ApiService.post('options', form);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FetchOptions = ({ form }) => {
|
||||||
|
return (dispatch) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
ApiService.get('options')
|
||||||
|
.then((response) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.SETTING_SET,
|
||||||
|
options: response.data.options,
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
import { optionsArrayToMap } from 'utils';
|
||||||
const initialState = {
|
const initialState = {
|
||||||
data: {
|
data: {
|
||||||
organization: {
|
organization: {},
|
||||||
name: 'Bigcapital, Limited Liabilities',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default createReducer(initialState, {
|
export default createReducer(initialState, {
|
||||||
['asdfas']: (state, action) => {
|
[t.SETTING_SET]: (state, action) => {
|
||||||
|
const { options } = action;
|
||||||
|
|
||||||
|
state.data.organization = optionsArrayToMap(options);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
SETTING_LIST_SET: 'SETTING_LIST_SET',
|
||||||
};
|
CLEAR_OPTIONS_FORM_ERRORS: 'CLEAR_OPTIONS_FORM_ERRORS',
|
||||||
|
SETTING_SET: 'SETTING_SET',
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { createReducer } from "@reduxjs/toolkit";
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
list: {},
|
list: {
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
userById: {},
|
userById: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -14,13 +16,13 @@ export default createReducer(initialState, {
|
|||||||
[t.USER_DETAILS_SET]: (state, action) => {
|
[t.USER_DETAILS_SET]: (state, action) => {
|
||||||
state.userById[action.user.id] = action.user;
|
state.userById[action.user.id] = action.user;
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the user details of the given user id,
|
* Retrieve the user details of the given user id,
|
||||||
* @param {Object} state
|
* @param {Object} state
|
||||||
* @param {Numeric} id
|
* @param {Numeric} id
|
||||||
*/
|
*/
|
||||||
export const getUserDetails = (state, id) => {
|
export const getUserDetails = (state, id) => {
|
||||||
return state.users.userById[id];
|
return state.users.userById[id];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
@import './normalize.scss';
|
||||||
|
|
||||||
@import "./normalize.scss";
|
$pt-popover-box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.02),
|
||||||
|
0 2px 4px rgba(16, 22, 26, 0.1), 0 8px 24px rgba(16, 22, 26, 0.1);
|
||||||
|
|
||||||
$pt-popover-box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.02), 0 2px 4px rgba(16, 22, 26, 0.1), 0 8px 24px rgba(16, 22, 26, 0.1);
|
@import '@blueprintjs/core/src/common/_variables.scss';
|
||||||
|
|
||||||
@import "@blueprintjs/core/src/common/_variables.scss";
|
|
||||||
// @import "@blueprintjs/core/src/common/colors.scss";
|
// @import "@blueprintjs/core/src/common/colors.scss";
|
||||||
|
|
||||||
$menu-item-color-hover: $light-gray4;
|
$menu-item-color-hover: $light-gray4;
|
||||||
@@ -12,42 +12,46 @@ $menu-item-color-active: $light-gray3;
|
|||||||
$breadcrumbs-collapsed-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#6B8193' enable-background='new 0 0 16 16' xml:space='preserve'><g><circle cx='2' cy='8.03' r='2'/><circle cx='14' cy='8.03' r='2'/><circle cx='8' cy='8.03' r='2'/></g></svg>");
|
$breadcrumbs-collapsed-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#6B8193' enable-background='new 0 0 16 16' xml:space='preserve'><g><circle cx='2' cy='8.03' r='2'/><circle cx='14' cy='8.03' r='2'/><circle cx='8' cy='8.03' r='2'/></g></svg>");
|
||||||
|
|
||||||
// Blueprint framework.
|
// Blueprint framework.
|
||||||
@import "@blueprintjs/core/src/blueprint.scss";
|
@import '@blueprintjs/core/src/blueprint.scss';
|
||||||
@import "@blueprintjs/datetime/src/blueprint-datetime.scss";
|
@import '@blueprintjs/datetime/src/blueprint-datetime.scss';
|
||||||
|
|
||||||
@import "basscss";
|
@import 'basscss';
|
||||||
|
|
||||||
$pt-font-family: Noto Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, Icons16, sans-serif;
|
$pt-font-family: Noto Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
||||||
|
Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, Icons16, sans-serif;
|
||||||
|
|
||||||
@import "functions";
|
@import 'functions';
|
||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
@import "objects/form";
|
@import 'objects/form';
|
||||||
@import "objects/typography";
|
@import 'objects/typography';
|
||||||
@import "objects/buttons";
|
@import 'objects/buttons';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
@import "components/data-table";
|
@import 'components/data-table';
|
||||||
@import "components/dialog";
|
@import 'components/dialog';
|
||||||
|
@import 'components/custom-scrollbar';
|
||||||
// Pages
|
|
||||||
@import "pages/dashboard";
|
|
||||||
@import "pages/accounts-chart";
|
|
||||||
@import "pages/authentication";
|
|
||||||
@import "pages/expense-form";
|
|
||||||
@import "pages/financial-statements";
|
|
||||||
@import "pages/make-journal-entries";
|
|
||||||
@import "pages/preferences";
|
|
||||||
@import "pages/view-form";
|
|
||||||
@import "pages/manual-journals";
|
|
||||||
@import "pages/item-category";
|
|
||||||
@import "pages/items";
|
|
||||||
@import "pages/currency";
|
|
||||||
// Views
|
|
||||||
@import "views/filter-dropdown";
|
|
||||||
@import "views/sidebar";
|
|
||||||
|
|
||||||
.#{$ns}-tooltip{
|
// Pages
|
||||||
|
@import 'pages/dashboard';
|
||||||
|
@import 'pages/accounts-chart';
|
||||||
|
@import 'pages/authentication';
|
||||||
|
@import 'pages/expense-form';
|
||||||
|
@import 'pages/financial-statements';
|
||||||
|
@import 'pages/make-journal-entries';
|
||||||
|
@import 'pages/preferences';
|
||||||
|
@import 'pages/view-form';
|
||||||
|
@import 'pages/manual-journals';
|
||||||
|
@import 'pages/item-category';
|
||||||
|
@import 'pages/items';
|
||||||
|
@import 'pages/invite-form.scss';
|
||||||
|
@import "pages/currency";
|
||||||
|
|
||||||
|
// Views
|
||||||
|
@import 'views/filter-dropdown';
|
||||||
|
@import 'views/sidebar';
|
||||||
|
|
||||||
|
.#{$ns}-tooltip {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,4 +76,4 @@ $pt-font-family: Noto Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
|||||||
fill: #fff;
|
fill: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
53
client/src/style/components/custom-scrollbar.scss
Normal file
53
client/src/style/components/custom-scrollbar.scss
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
.ScrollbarsCustom {
|
||||||
|
position: 'relative';
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.ScrollbarsCustom-Wrapper {
|
||||||
|
position: 'absolute';
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollbarsCustom-Content {
|
||||||
|
box-sizing: 'border-box';
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollbarsCustom-Track {
|
||||||
|
&.ScrollbarsCustom-TrackY,
|
||||||
|
&.ScrollbarsCustom-TrackX {
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 4px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
&.ScrollbarsCustom-TrackX {
|
||||||
|
height: 10px;
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
bottom: 0;
|
||||||
|
left: 5px;
|
||||||
|
}
|
||||||
|
&.ScrollbarsCustom-TrackY {
|
||||||
|
width: 10px;
|
||||||
|
height: calc(100% - 10px);
|
||||||
|
top: 5px;
|
||||||
|
right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ScrollbarsCustom-Thumb {
|
||||||
|
&.ScrollbarsCustom-ThumbX,
|
||||||
|
&.ScrollbarsCustom-ThumbY {
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
&.ScrollbarsCustom-ThumbX {
|
||||||
|
height: 100%;
|
||||||
|
width: 0px;
|
||||||
|
}
|
||||||
|
&.ScrollbarsCustom-ThumbY {
|
||||||
|
height: 100%;
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
47
client/src/style/pages/invite-form.scss
Normal file
47
client/src/style/pages/invite-form.scss
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// .dialog--invite-form {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
.dialog--invite-form {
|
||||||
|
&.bp3-dialog {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
&:not(.dialog--loading) .bp3-dialog-body {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
.bp3-dialog-body {
|
||||||
|
// margin-right: 50px;
|
||||||
|
.bp3-form-group.bp3-inline {
|
||||||
|
.bp3-label {
|
||||||
|
min-width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.form-group--email {
|
||||||
|
.bp3-form-content {
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bp3-dialog-footer-actions {
|
||||||
|
margin-right: 30px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// .bp3-dialog-body {
|
||||||
|
// .bp3-form-group.bp3-inline {
|
||||||
|
// .bp3-label {
|
||||||
|
// min-width: 100px;
|
||||||
|
// }
|
||||||
|
// .bp3-form-content {
|
||||||
|
// width: 250px;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .bp3-dialog-footer-actions {
|
||||||
|
// display: flex;
|
||||||
|
// justify-content: flex-end;
|
||||||
|
// margin-right: 100px;
|
||||||
|
// }
|
||||||
@@ -90,3 +90,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.preferences__tabs-extra-actions {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,22 +1,37 @@
|
|||||||
|
$sidebar-background: #01194e;
|
||||||
$sidebar-background: #01194E;
|
|
||||||
$sidebar-text-color: #fff;
|
$sidebar-text-color: #fff;
|
||||||
$sidebar-width: 220px;
|
$sidebar-width: 220px;
|
||||||
$sidebar-menu-item-color: #b8c0d5;
|
$sidebar-menu-item-color: #b8c0d5;
|
||||||
|
|
||||||
$sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
$sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
||||||
|
|
||||||
.sidebar{
|
.sidebar {
|
||||||
background: $sidebar-background;
|
background: $sidebar-background;
|
||||||
color: $sidebar-text-color;
|
color: $sidebar-text-color;
|
||||||
width: $sidebar-width;
|
width: $sidebar-width;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
&__inner{
|
.ScrollbarsCustom-Track {
|
||||||
overflow-y: scroll;
|
&.ScrollbarsCustom-TrackY,
|
||||||
overflow-x: hidden;
|
&.ScrollbarsCustom-TrackX{
|
||||||
height: 100%;
|
background: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ScrollbarsCustom-Thumb{
|
||||||
|
&.ScrollbarsCustom-ThumbX,
|
||||||
|
&.ScrollbarsCustom-ThumbY {
|
||||||
|
background: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.ScrollbarsCustom-Thumb{
|
||||||
|
&.ScrollbarsCustom-ThumbX,
|
||||||
|
&.ScrollbarsCustom-ThumbY {
|
||||||
|
background: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__head{
|
&__head{
|
||||||
padding: 16px 12px;
|
padding: 16px 12px;
|
||||||
@@ -30,80 +45,79 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-menu{
|
&-menu {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
min-width: $sidebar-width;
|
min-width: $sidebar-width;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
padding-bottom: 2rem;
|
padding-bottom: 2rem;
|
||||||
|
|
||||||
.#{$ns}-menu-item{
|
.#{$ns}-menu-item {
|
||||||
color: $sidebar-menu-item-color;
|
color: $sidebar-menu-item-color;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
padding: 10px 16px;
|
padding: 10px 16px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&.bp3-active{
|
&.bp3-active {
|
||||||
background: #012470;
|
background: #012470;
|
||||||
color: #c1c9dd;
|
color: #c1c9dd;
|
||||||
}
|
}
|
||||||
&:focus,
|
&:focus,
|
||||||
&:active{
|
&:active {
|
||||||
background: #01143e;
|
background: #01143e;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .#{$ns}-icon{
|
> .#{$ns}-icon {
|
||||||
color: #767b9b;
|
color: #767b9b;
|
||||||
margin-right: 14px;
|
margin-right: 14px;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
> .#{$ns}-icon-caret-right{
|
> .#{$ns}-icon-caret-right {
|
||||||
margin-right: -4px;
|
margin-right: -4px;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
color: #42547b;
|
color: #42547b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}-submenu{
|
.#{$ns}-submenu {
|
||||||
|
.#{$ns}-collapse {
|
||||||
.#{$ns}-collapse{
|
|
||||||
border-left: 2px solid rgba(255, 255, 255, 0.15);
|
border-left: 2px solid rgba(255, 255, 255, 0.15);
|
||||||
|
|
||||||
&-body{
|
&-body {
|
||||||
background-color: rgb(11, 34, 85);
|
background-color: rgb(11, 34, 85);
|
||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}-menu-item{
|
.#{$ns}-menu-item {
|
||||||
padding: 7px 16px 7px 18px;
|
padding: 7px 16px 7px 18px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
color: #8a95b6;
|
color: #8a95b6;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&.bp3-active{
|
&.bp3-active {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #C5CBE3;
|
color: #c5cbe3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.#{$ns}-popover{
|
.#{$ns}-popover {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
&-content{
|
&-content {
|
||||||
box-shadow: 0 0 0;
|
box-shadow: 0 0 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.#{$ns}-popover-target.#{$ns}-popover-open .#{$ns}-menu-item{
|
.#{$ns}-popover-target.#{$ns}-popover-open .#{$ns}-menu-item {
|
||||||
color: $sidebar-menu-item-color;
|
color: $sidebar-menu-item-color;
|
||||||
}
|
}
|
||||||
.#{$ns}-menu-divider{
|
.#{$ns}-menu-divider {
|
||||||
border-top-color: #1D366A;
|
border-top-color: #1d366a;
|
||||||
color: #6B708C;
|
color: #6b708c;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user