diff --git a/src/static/json/icons.js b/src/static/json/icons.js
index fc6ffe780..45bbfb4e6 100644
--- a/src/static/json/icons.js
+++ b/src/static/json/icons.js
@@ -509,11 +509,17 @@ export default {
],
viewBox: '0 0 24 24',
},
- "sms-message-preview": {
+ 'sms-message-preview': {
path: [
'M8.341,375.3573H399.3271v-.0015l-390.9861-.07ZM363.2382,0H44.43A44.4508,44.4508,0,0,0,0,44.371V375.284l8.341.0016V44.371A36.0651,36.0651,0,0,1,44.43,8.33H90.7089a4.6454,4.6454,0,0,1,4.6482,4.6423v1.9718a23.8588,23.8588,0,0,0,23.8742,23.843H288.9146a23.8586,23.8586,0,0,0,23.8741-23.843V12.972A4.6456,4.6456,0,0,1,317.4372,8.33h45.801A36.0651,36.0651,0,0,1,399.3271,44.371V375.3558l8.341.0015V44.371A44.4508,44.4508,0,0,0,363.2382,0Z',
- "M1199.9485,803.1623"
+ 'M1199.9485,803.1623',
],
- viewBox: "0 0 407.6681 375.3573",
- }
+ viewBox: '0 0 407.6681 375.3573',
+ },
+ lock: {
+ path: [
+ 'M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z',
+ ],
+ viewBox: '0 0 24 24',
+ },
};
From c139e129bf8a1e8e8c944480361a30f3efca5fdc Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 21 Nov 2021 01:13:41 +0200
Subject: [PATCH 06/46] feat: roles permission & style & component.
---
src/common/classes.js | 1 +
.../Users/Roles/RolesForm/RolesForm.js | 94 +++++++++++
.../Users/Roles/RolesForm/RolesForm.schema.js | 17 ++
.../Users/Roles/RolesForm/RolesFormContent.js | 72 +++++++++
.../Users/Roles/RolesForm/RolesFormPage.js | 15 ++
.../Roles/RolesForm/RolesFormProvider.js | 60 +++++++
.../Users/Roles/RolesForm/components.js | 150 ++++++++++++++++++
.../Roles/RolesLanding/RolesDataTable.js | 28 ++++
.../Users/Roles/RolesLanding/RolesList.js | 18 +++
.../Roles/RolesLanding/RolesListProvider.js | 28 ++++
.../Users/Roles/RolesLanding/components.js | 54 +++++++
src/containers/Preferences/Users/RolesList.js | 0
src/containers/Preferences/Users/Users.js | 13 +-
.../Preferences/Users/UsersActions.js | 33 ++--
src/hooks/query/index.js | 1 +
src/hooks/query/roles.js | 77 +++++++++
src/hooks/query/types.js | 7 +
src/routes/preferences.js | 8 +-
src/routes/preferencesTabs.js | 22 +--
src/style/pages/Preferences/Roles/Form.scss | 58 +++++++
src/style/pages/Preferences/Users.scss | 18 ++-
21 files changed, 730 insertions(+), 44 deletions(-)
create mode 100644 src/containers/Preferences/Users/Roles/RolesForm/RolesForm.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesForm/RolesForm.schema.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesForm/RolesFormContent.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesForm/RolesFormPage.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesForm/RolesFormProvider.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesForm/components.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesLanding/RolesDataTable.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesLanding/RolesList.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesLanding/RolesListProvider.js
create mode 100644 src/containers/Preferences/Users/Roles/RolesLanding/components.js
delete mode 100644 src/containers/Preferences/Users/RolesList.js
create mode 100644 src/hooks/query/roles.js
create mode 100644 src/style/pages/Preferences/Roles/Form.scss
diff --git a/src/common/classes.js b/src/common/classes.js
index bea33a718..e1df0b33f 100644
--- a/src/common/classes.js
+++ b/src/common/classes.js
@@ -67,6 +67,7 @@ const CLASSES = {
PREFERENCES_PAGE_INSIDE_CONTENT_CURRENCIES: 'preferences-page__inside-content--currencies',
PREFERENCES_PAGE_INSIDE_CONTENT_ACCOUNTANT: 'preferences-page__inside-content--accountant',
PREFERENCES_PAGE_INSIDE_CONTENT_SMS_INTEGRATION: 'preferences-page__inside-content--sms-integration',
+ PREFERENCES_PAGE_INSIDE_CONTENT_ROLES_FORM: 'preferences-page__inside-content--roles-form',
FINANCIAL_REPORT_INSIDER: 'dashboard__insider--financial-report',
diff --git a/src/containers/Preferences/Users/Roles/RolesForm/RolesForm.js b/src/containers/Preferences/Users/Roles/RolesForm/RolesForm.js
new file mode 100644
index 000000000..fbbd63d51
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesForm/RolesForm.js
@@ -0,0 +1,94 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { Formik } from 'formik';
+
+import 'style/pages/Preferences/Roles/Form.scss';
+
+import { Intent } from '@blueprintjs/core';
+
+import { AppToaster, FormattedMessage as T } from 'components';
+
+import { CreateRolesFormSchema, EditRolesFormSchema } from './RolesForm.schema';
+
+import { useRolesFormContext } from './RolesFormProvider';
+
+import RolesFormContent from './RolesFormContent';
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+
+import { compose } from 'utils';
+
+const defaultValues = {
+ role_name: 'Default',
+ role_description: '',
+ permissions: {},
+};
+
+/**
+ * Preferences - Roles Form.
+ */
+function RolesForm({
+ // #withDashboardActions
+ changePreferencesPageTitle,
+}) {
+ const { createRoleMutate, editRoleMutate, permissions } =
+ useRolesFormContext();
+
+ // Initial values.
+ const initialValues = {
+ ...defaultValues,
+ };
+
+ const MapperPermissionSchema = (data) => {
+ return data.map(({ role_name, role_description, permissions }) => {
+ const permission = _.mapKeys(permissions, (value, key) => {
+ return value;
+ });
+ return {
+ role_name: role_name,
+ role_description: role_description,
+ permissions: [permission],
+ };
+ });
+ };
+
+ React.useEffect(() => {
+ changePreferencesPageTitle(
);
+ }, [changePreferencesPageTitle]);
+
+ const handleFormSubmit = (values, { setSubmitting, resetForm }) => {
+ const form = {
+ ...values,
+ };
+
+ // Handle the request success.
+ const onSuccess = () => {
+ AppToaster.show({
+ message: '',
+ intent: Intent.SUCCESS,
+ });
+ };
+ // Handle the request error.
+ const onError = (
+ {
+ // response: {
+ // data: { errors },
+ // },
+ },
+ ) => {
+ setSubmitting(false);
+ };
+
+ createRoleMutate(form).then(onSuccess).catch(onError);
+ };
+
+ return (
+
+ );
+}
+
+export default compose(withDashboardActions)(RolesForm);
diff --git a/src/containers/Preferences/Users/Roles/RolesForm/RolesForm.schema.js b/src/containers/Preferences/Users/Roles/RolesForm/RolesForm.schema.js
new file mode 100644
index 000000000..dce8eb3cc
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesForm/RolesForm.schema.js
@@ -0,0 +1,17 @@
+import * as Yup from 'yup';
+import intl from 'react-intl-universal';
+import { DATATYPES_LENGTH } from 'common/dataTypes';
+
+const Schema = Yup.object().shape({
+ role_name: Yup.string().label(intl.get('name')).required(),
+ role_description: Yup.string().nullable().max(DATATYPES_LENGTH.TEXT),
+
+ permissions: Yup.object().shape({
+ subject: Yup.string(),
+ ability: Yup.string(),
+ value: Yup.boolean(),
+ }),
+});
+
+export const CreateRolesFormSchema = Schema;
+export const EditRolesFormSchema = Schema;
diff --git a/src/containers/Preferences/Users/Roles/RolesForm/RolesFormContent.js b/src/containers/Preferences/Users/Roles/RolesForm/RolesFormContent.js
new file mode 100644
index 000000000..539989c6a
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesForm/RolesFormContent.js
@@ -0,0 +1,72 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import { ErrorMessage, FastField, Form, useFormikContext } from 'formik';
+import {
+ Button,
+ FormGroup,
+ InputGroup,
+ Intent,
+ TextArea,
+} from '@blueprintjs/core';
+import { inputIntent } from 'utils';
+import { FormattedMessage as T, FieldRequiredHint } from 'components';
+
+import { RolesPermissionList } from './components';
+
+/**
+ * Preferences - Roles Form content.
+ */
+export default function RolesFormContent() {
+ const history = useHistory();
+
+ const { isSubmitting } = useFormikContext();
+
+ const handleCloseClick = () => {
+ history.go(-1);
+ };
+
+ return (
+
+ );
+}
diff --git a/src/containers/Preferences/Users/Roles/RolesForm/RolesFormPage.js b/src/containers/Preferences/Users/Roles/RolesForm/RolesFormPage.js
new file mode 100644
index 000000000..a263d2942
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesForm/RolesFormPage.js
@@ -0,0 +1,15 @@
+import React from 'react';
+
+import RolesForm from './RolesForm';
+import { RolesFormProvider } from './RolesFormProvider';
+
+/**
+ * Roles Form page.
+ */
+export default function RolesFormPage() {
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/Preferences/Users/Roles/RolesForm/RolesFormProvider.js b/src/containers/Preferences/Users/Roles/RolesForm/RolesFormProvider.js
new file mode 100644
index 000000000..73f416b51
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesForm/RolesFormProvider.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import { flatMap, map } from 'lodash';
+import classNames from 'classnames';
+import { CLASSES } from 'common/classes';
+
+import {
+ useCreateRolePermissionSchema,
+ useEditRole,
+ usePermissionsSchema,
+} from 'hooks/query';
+import PreferencesPageLoader from '../../../PreferencesPageLoader';
+
+const RolesFormContext = React.createContext();
+
+/**
+ * Roles Form page provider.
+ */
+function RolesFormProvider({ ...props }) {
+ // Create and edit roles mutations.
+ const { mutateAsync: createRolePermissionMutate } =
+ useCreateRolePermissionSchema();
+ const { mutateAsync: editRolePermissionMutate } =
+ useEditRolePermissionSchema();
+
+ const {
+ data: permissionsSchema,
+ isLoading: isPermissionsSchemaLoading,
+ isFetching: isPermissionsSchemaFetching,
+ } = usePermissionsSchema();
+
+ // Provider state.
+ const provider = {
+ permissionsSchema,
+ isPermissionsSchemaLoading,
+ isPermissionsSchemaFetching,
+ createRolePermissionMutate,
+ editRolePermissionMutate,
+ };
+
+ return (
+
+
+ {isPermissionsSchemaLoading ? (
+
+ ) : (
+
+ )}
+
+
+ );
+}
+
+const useRolesFormContext = () => React.useContext(RolesFormContext);
+
+export { RolesFormProvider, useRolesFormContext };
diff --git a/src/containers/Preferences/Users/Roles/RolesForm/components.js b/src/containers/Preferences/Users/Roles/RolesForm/components.js
new file mode 100644
index 000000000..f7ef4bbd6
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesForm/components.js
@@ -0,0 +1,150 @@
+import React from 'react';
+import { Checkbox } from '@blueprintjs/core';
+import styled from 'styled-components';
+import { castArray } from 'lodash';
+
+import { FastField, useFormikContext } from 'formik';
+import { whenRtl, whenLtr } from 'utils/styled-components';
+import { Icon, Hint, If, Choose } from 'components';
+import { useRolesFormContext } from './RolesFormProvider';
+
+const RoleLabelCheckbox = ({ subject, label, description }) => (
+ <>
+
+ {/*------------- subject checbox ------------- */}
+
+ {({ form: { setFieldValue, values }, field }) => (
+
+ )}
+
+ {description}
+
+ >
+);
+
+const AbilitiesList = ({ subject, abilities }) => {
+ return (
+
+ {abilities?.map(({ key, label }) => (
+
+ {({ form: { setFieldValue, values }, field }) => (
+
+ )}
+
+ ))}
+
+ );
+};
+
+const ExtraAbilitiesList = ({ subject, extraAbilities }) => {
+ return extraAbilities?.map(({ key, label }) => (
+
+
+ {({ form: { setFieldValue, values }, field }) => (
+
+ )}
+
+
+ ));
+};
+
+export const RolesPermissionList = () => {
+ const { permissionsSchema } = useRolesFormContext();
+
+ return (
+
+
+ {permissionsSchema.map(
+ ({
+ subject,
+ subject_label,
+ description,
+ abilities,
+ extra_abilities,
+ }) => {
+ const extraAbilitiesList = Array.isArray(extra_abilities)
+ ? extra_abilities
+ : [];
+
+ const abilitiesList = castArray(abilities) ? abilities : [];
+
+ return (
+
+
+
+
+
+
+
+
+ );
+ },
+ )}
+
+
+ );
+};
+
+const GroupList = styled.div`
+ list-style: none;
+ border: 1px solid #d2dce2;
+ border-radius: 6px;
+ font-size: 13px;
+
+ ul:first-child > li:last-child {
+ border-bottom: 0;
+ border-top: 0;
+ }
+`;
+
+const BoxedGroupList = styled.ul`
+ margin: 0;
+ list-style: none;
+`;
+
+const RoleList = styled.li`
+ display: block;
+ padding: 5px 10px;
+ margin: 0;
+ line-height: 20px;
+ border-bottom: 1px solid #e0e0e0;
+`;
+
+const LabelCheckbox = styled.label`
+ > * {
+ display: inline-block;
+ }
+ .block {
+ width: 220px;
+ padding: 2px 0;
+ font-weight: 500;
+ }
+`;
+
+const AbilitieList = styled.ul`
+ list-style: none;
+ /* margin-left: 12px; // 10px */
+ margin: 0px 10px 0px;
+
+ > li {
+ display: inline-block;
+ margin-top: 3px;
+ }
+`;
+
+const AbilitiesChildList = styled.li`
+ display: inline-block;
+ margin-top: 3px;
+`;
diff --git a/src/containers/Preferences/Users/Roles/RolesLanding/RolesDataTable.js b/src/containers/Preferences/Users/Roles/RolesLanding/RolesDataTable.js
new file mode 100644
index 000000000..775f98970
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesLanding/RolesDataTable.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import { DataTable } from 'components';
+import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
+
+import { useRolesTableColumns, ActionsMenu } from './components';
+
+import { compose } from 'utils';
+
+/**
+ * Roles data table.
+ */
+export default function RolesDataTable() {
+ const columns = useRolesTableColumns();
+
+ return (
+
+ );
+}
diff --git a/src/containers/Preferences/Users/Roles/RolesLanding/RolesList.js b/src/containers/Preferences/Users/Roles/RolesLanding/RolesList.js
new file mode 100644
index 000000000..436adb6e5
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesLanding/RolesList.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import { RolesListProvider } from './RolesListProvider';
+import RolesDataTable from './RolesDataTable';
+
+/**
+ * Roles list.
+ */
+function RolesListPrefernces() {
+ return (
+
+
+
+ );
+}
+
+export default RolesListPrefernces;
diff --git a/src/containers/Preferences/Users/Roles/RolesLanding/RolesListProvider.js b/src/containers/Preferences/Users/Roles/RolesLanding/RolesListProvider.js
new file mode 100644
index 000000000..248b47260
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesLanding/RolesListProvider.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import classNames from 'classnames';
+import { CLASSES } from 'common/classes';
+// import {} from 'hooks/query';
+
+const RolesListContext = React.createContext();
+
+/**
+ * Roles list provider.
+ */
+function RolesListProvider({ ...props }) {
+ // Provider state.
+ const provider = {};
+ return (
+
+
+
+ );
+}
+
+const useRolesContext = () => React.useContext(RolesListContext);
+
+export { RolesListProvider, useRolesContext };
diff --git a/src/containers/Preferences/Users/Roles/RolesLanding/components.js b/src/containers/Preferences/Users/Roles/RolesLanding/components.js
new file mode 100644
index 000000000..350cfa34b
--- /dev/null
+++ b/src/containers/Preferences/Users/Roles/RolesLanding/components.js
@@ -0,0 +1,54 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+
+import { Intent, Button, Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
+import { safeInvoke } from 'utils';
+import { Icon, If } from 'components';
+
+/**
+ * Context menu of roles.
+ */
+export function ActionsMenu({ payload: {}, row: { original } }) {
+ return (
+
+ );
+}
+
+/**
+ * Retrieve Roles table columns.
+ * @returns
+ */
+export function useRolesTableColumns() {
+ return React.useMemo(
+ () => [
+ {
+ id: 'name',
+ Header: intl.get('roles.column.name'),
+ // accessor: ,
+ className: 'name',
+ width: '100',
+ disableSortBy: true,
+ },
+ {
+ id: 'description',
+ Header: intl.get('roles.column.description'),
+ // accessor: ,
+ className: 'description',
+ width: '120',
+ disableSortBy: true,
+ },
+ ],
+ [],
+ );
+}
diff --git a/src/containers/Preferences/Users/RolesList.js b/src/containers/Preferences/Users/RolesList.js
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/containers/Preferences/Users/Users.js b/src/containers/Preferences/Users/Users.js
index ed5e9a806..4f453d0b6 100644
--- a/src/containers/Preferences/Users/Users.js
+++ b/src/containers/Preferences/Users/Users.js
@@ -26,11 +26,18 @@ function UsersPreferences({ openDialog }) {
);
diff --git a/src/containers/Preferences/Users/UsersActions.js b/src/containers/Preferences/Users/UsersActions.js
index ada5c76af..3575b6ee9 100644
--- a/src/containers/Preferences/Users/UsersActions.js
+++ b/src/containers/Preferences/Users/UsersActions.js
@@ -1,40 +1,41 @@
import React from 'react';
-import {
- Button,
- Intent,
-} from '@blueprintjs/core';
+import { useHistory } from 'react-router-dom';
+
+import { Button, Intent } from '@blueprintjs/core';
import { FormattedMessage as T } from 'components';
import Icon from 'components/Icon';
import withDialogActions from 'containers/Dialog/withDialogActions';
-import {compose} from 'utils';
+import { compose } from 'utils';
-function UsersActions({
- openDialog,
- closeDialog,
-}) {
+function UsersActions({ openDialog, closeDialog }) {
+ const history = useHistory();
const onClickNewUser = () => {
openDialog('invite-user');
};
+ const onClickNewRole = () => {
+ history.push('/preferences/roles');
+ };
+
return (