diff --git a/src/components/AllocationManager/AllocationManager.jsx b/src/components/AllocationManager/AllocationManager.jsx
index ec2b320..c506b6b 100755
--- a/src/components/AllocationManager/AllocationManager.jsx
+++ b/src/components/AllocationManager/AllocationManager.jsx
@@ -6,13 +6,13 @@ import TransferList from 'components/MDTransferList';
import './AllocationManager.component.scss';
const AllocationManager = props => {
- const {boxStyleOverride, component, gridStyleOverride, initlist, list, matchProp, md, onChange, title, variant, xs} = props;
+ const {allDisabled, boxStyleOverride, component, gridStyleOverride, allocatedList, list, matchProp, md, onChange, title, variant, xs} = props;
// eslint-disable-next-line no-unused-vars
const [allocationStatus, setAllocationStatus] = useState();
const handleAllocationChange = state => {
setAllocationStatus(state);
- onChange && onChange(state.assigned?.map(obj => obj._id).join(','));
+ onChange && onChange(state.assigned);
};
return
@@ -29,16 +29,17 @@ const AllocationManager = props => {
{title}
-
+
;
};
AllocationManager.propTypes = {
+ allDisabled: PropTypes.bool,
boxStyleOverride: PropTypes.object,
component: PropTypes.string,
gridStyleOverride: PropTypes.object,
- initlist: PropTypes.oneOfType([
+ allocatedList: PropTypes.oneOfType([
PropTypes.string,
PropTypes.array
]),
diff --git a/src/components/MDTransferList/index.js b/src/components/MDTransferList/index.js
index 3767b7d..025d05c 100644
--- a/src/components/MDTransferList/index.js
+++ b/src/components/MDTransferList/index.js
@@ -43,7 +43,7 @@ const useStyles = makeStyles({
}
});
-export default function TransferList({list, initlist, matchProp, onChange}) {
+export default function TransferList({allDisabled, list, allocatedList, matchProp, onChange}) {
const classes = useStyles();
const [checked, setChecked] = useState([]);
const [left, setLeft] = useState(list || []);
@@ -53,14 +53,14 @@ export default function TransferList({list, initlist, matchProp, onChange}) {
const rightChecked = intersection(checked, right);
useEffect(() => {
- if (initlist) {
- const initlistClone = typeof initlist === 'object' ? initlist : initlist.split(',');
- const left = notBy(matchProp, list, initlistClone);
- const right = intersectionBy(matchProp, list, initlistClone);
+ if (typeof allocatedList === 'string') {
+ const allocatedListClone = typeof allocatedList === 'object' ? allocatedList : allocatedList.split(',');
+ const left = notBy(matchProp, list, allocatedListClone);
+ const right = intersectionBy(matchProp, list, allocatedListClone);
setLeft(left);
setRight(right);
}
- }, []);
+ }, [allocatedList]);
const handleToggle = (value) => () => {
const currentIndex = checked.indexOf(value);
@@ -116,7 +116,7 @@ export default function TransferList({list, initlist, matchProp, onChange}) {
const labelId = `transfer-list-item-${value}-label`;
return (
-
+
{
- const {backgroundColor, classes, color, headCells, id, index, navUrl, records, table, value} = props;
+ const { backgroundColor, classes, color, headCells, id, loader, index, navUrl, records, table, value } = props;
const navigate = useNavigate();
const StyledTableRow = styled(TableRow)(({ theme }) => ({
@@ -18,7 +18,7 @@ const PwTablePanel = props => {
}
}));
- const rowRenders = ({records, headers, navUrl, table}) => {
+ const rowRenders = ({ records, headers, navUrl, table }) => {
return records && records.map((record, keyouter) => {
return
{headers.map((columnConfig, key) => {
@@ -26,15 +26,15 @@ const PwTablePanel = props => {
const isAfter = columnConfig.placement && columnConfig.placement === 'after';
const limitWidth = columnConfig.limitWidth;
return canEdit && navigate(navUrl, {state: {[table]: record}})}>
+ onClick={() => canEdit && navigate(navUrl, { state: { [table]: record } })}>
{canEdit
? isAfter
?
{columnConfig.value(record)}
-
+
:
-
+
{columnConfig.value(record)}
: {columnConfig.value(record)}}
@@ -52,13 +52,13 @@ const PwTablePanel = props => {
backgroundColor={backgroundColor || '#007AFF'}
color={color || '#fff'}
>
-
- {records && records.length > 0 && rowRenders({records, headers: headCells, navUrl, table})}
-
+ {records && records.length > 0 &&
+ {rowRenders({ records, headers: headCells, navUrl, table })}
+ }
{(!records || records.length === 0)
- && No Records to Display
}
-
+ && No Records to Display
}
+ ;
};
PwTablePanel.propTypes = {
@@ -68,10 +68,11 @@ PwTablePanel.propTypes = {
headCells: PropTypes.array,
id: PropTypes.string,
index: PropTypes.number,
+ loader: PropTypes.bool,
navUrl: PropTypes.string,
records: PropTypes.array,
table: PropTypes.string,
value: PropTypes.number
};
-export default PwTablePanel;
\ No newline at end of file
+export default PwTablePanel;
diff --git a/src/components/Switch/index.js b/src/components/Switch/index.js
index 3b8e6cd..4eea27e 100644
--- a/src/components/Switch/index.js
+++ b/src/components/Switch/index.js
@@ -56,12 +56,13 @@ const IOSSwitch = styled((props) => (
}
}));
-export default function Switch({ checked, onChange, name }) {
- return ;
+export default function Switch({ disabled, checked, onChange, name }) {
+ return ;
}
Switch.propTypes = {
checked: PropTypes.any,
+ disabled: PropTypes.bool,
name: PropTypes.any,
onChange: PropTypes.any
};
diff --git a/src/components/Toggles/Toggles.jsx b/src/components/Toggles/Toggles.jsx
index 26436cd..8dec58d 100755
--- a/src/components/Toggles/Toggles.jsx
+++ b/src/components/Toggles/Toggles.jsx
@@ -25,22 +25,22 @@ const useStyles = makeStyles(() => ({
}));
const Toggles = props => {
- const {boxSx, gridStyleOverride, inittoggles, md, onChange, title, toggles, typoComponent, typoSx, typoVariant, xs} = props;
+ const {allDisabled, boxSx, gridStyleOverride, selectedToggles, md, onChange, title, toggles, typoComponent, typoSx, typoVariant, xs} = props;
const [toggleState, updateToggleState] = useState({});
const classes = useStyles();
useEffect(() => {
- if (inittoggles && typeof inittoggles === 'string') {
- const initToggleState = {};
- inittoggles.split(',').forEach(iToggle => initToggleState[iToggle] = true);
- updateToggleState(initToggleState);
+ if (typeof selectedToggles === 'string') {
+ const selectedToggleState = {};
+ selectedToggles.split(',').forEach(iToggle => selectedToggleState[iToggle] = true);
+ updateToggleState(selectedToggleState);
}
- }, []);
+ }, [selectedToggles]);
const handleToggle = (e, toggle) => {
const toggleStateClone = {...toggleState, [toggle]: e.target.checked};
updateToggleState(toggleStateClone);
- onChange && onChange(Object.keys(toggleStateClone).join(','));
+ onChange && onChange(toggleStateClone);
};
const switchRenders = toggles => toggles && toggles.map((toggle, key) => {
@@ -49,7 +49,7 @@ const Toggles = props => {
return
{toggle}
- handleToggle(e, toggle)} />
+ handleToggle(e, toggle)} />
;
});
@@ -65,9 +65,10 @@ const Toggles = props => {
};
Toggles.propTypes = {
+ allDisabled: PropTypes.bool,
boxSx: PropTypes.object,
gridStyleOverride: PropTypes.object,
- inittoggles: PropTypes.string,
+ selectedToggles: PropTypes.string,
md: PropTypes.number,
onChange: PropTypes.func,
title: PropTypes.string,
diff --git a/src/index.js b/src/index.js
index ff5fab3..1c0fb01 100644
--- a/src/index.js
+++ b/src/index.js
@@ -17,7 +17,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
-import './main.scss';
+import './main.css';
import App from 'App';
// Soft UI Context Provider
diff --git a/src/main.css b/src/main.css
new file mode 100644
index 0000000..1e20463
--- /dev/null
+++ b/src/main.css
@@ -0,0 +1,67 @@
+fieldset legend {
+ width: 0;
+}
+
+.loader {
+ position: relative;
+}
+
+.loader:before {
+ display: block;
+ content: "";
+ position: absolute;
+ background-color: transparent;
+ background-image: url("./assets/images/favicon.png");
+ background-size: 3rem;
+ background-repeat: no-repeat;
+ background-position: center;
+ height: 100%;
+ width: 100%;
+ -webkit-animation: rotating 2s linear infinite;
+ -moz-animation: rotating 2s linear infinite;
+ -ms-animation: rotating 2s linear infinite;
+ -o-animation: rotating 2s linear infinite;
+ animation: rotating 2s linear infinite;
+ z-index: 1050;
+}
+
+.loader:after {
+ content: "";
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ background: rgba(255, 255, 255, 0.7);
+ position: absolute;
+ z-index: 1040;
+}
+
+@-webkit-keyframes rotating {
+ from {
+ -webkit-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ to {
+ -webkit-transform: rotateY(360deg);
+ -o-transform: rotateY(360deg);
+ transform: rotateY(360deg);
+ }
+}
+
+@keyframes rotating {
+ from {
+ -ms-transform: rotate(0deg);
+ -moz-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ to {
+ -ms-transform: rotateY(360deg);
+ -moz-transform: rotateY(360deg);
+ -webkit-transform: rotateY(360deg);
+ -o-transform: rotateY(360deg);
+ transform: rotateY(360deg);
+ }
+}
\ No newline at end of file
diff --git a/src/main.scss b/src/main.scss
deleted file mode 100644
index d1b797e..0000000
--- a/src/main.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-fieldset {
- legend {
- width: 0;
- }
-}
diff --git a/src/pages/createEditUser/index.js b/src/pages/createEditUser/index.js
index bee2327..73ea169 100644
--- a/src/pages/createEditUser/index.js
+++ b/src/pages/createEditUser/index.js
@@ -14,7 +14,7 @@ import WarehouseActions, { WarehouseSelectors } from 'redux/WarehouseRedux';
import InventoryActions, { InventorySelectors } from 'redux/InventoryRedux';
import RolesActions, { RolesSelectors } from 'redux/RolesRedux';
import PermissionsActions, { PermissionsSelectors } from 'redux/PermissionsRedux';
-import { AuthSelectors } from 'redux/AuthRedux';
+// import { AuthSelectors } from 'redux/AuthRedux';
import UsersActions from 'redux/UsersRedux';
import schema from 'services/ValidationServices';
@@ -73,12 +73,13 @@ function CreateEditUser(props) {
const warehouses = useSelector(WarehouseSelectors.getWarehouseDetail);
const inventories = useSelector(InventorySelectors.getInventoryDetail);
const actions = useSelector(PermissionsSelectors.getActionsDetail);
- const permissions = useSelector(PermissionsSelectors.getPermissionsDetail);
- const currentUser = useSelector(AuthSelectors.getUser);
+ const visibilities = useSelector(PermissionsSelectors.getPermissionsDetail);
+ // const currentUser = useSelector(AuthSelectors.getUser);
const location = useLocation();
const [editedUser, setEditedUser] = useState(location?.state?.user);
const [selectedRoles, setSelectedRoles] = useState([]);
const [uploadedImg, setUploadedImg] = useState();
+ // const [selectedPermissions, setSelectedPermissions] = useState({});
useEffect(() => {
if (context === 'edit') {
@@ -118,7 +119,7 @@ function CreateEditUser(props) {
method: 'get'
})
);
- (!permissions || permissions.length === 0) &&
+ (!visibilities || visibilities.length === 0) &&
dispatch(
PermissionsActions.getPermissionsAction({
loader: 'loading-request',
@@ -149,10 +150,10 @@ function CreateEditUser(props) {
visibilities: '',
isActive: true,
image: '',
- createdBy: currentUser ? currentUser.fullName : '',
- createdAt: new Date(),
- updatedBy: currentUser ? currentUser.fullName : '',
- updatedAt: new Date()
+ createdBy: '',
+ createdAt: '',
+ updatedBy: '',
+ updatedAt: ''
} : {
fullName: editedUser ? editedUser.fullName : '',
phoneNumber: editedUser ? editedUser.phoneNumber : '',
@@ -233,9 +234,31 @@ function CreateEditUser(props) {
}
});
formik.handleChange('roles')(uniqueRoles.map((role) => role.name).join());
+ aggregatePermissions(uniqueRoles);
setSelectedRoles(uniqueRoles);
};
+ const aggregatePermissions = roles => {
+ const actions = [], visibilities = [], warehouses = [], inventories = [];
+ roles.forEach(role => {
+ if (role.permissions) {
+ const currActions = role.permissions.actions;
+ const currVisibilities = role.permissions.allowedUIModules;
+ const currWarehouseScopes = role.permissions.warehouseScopes;
+ const currInventoryScopes = role.permissions.inventoryScopes;
+ currActions.forEach(ac => actions.indexOf(ac) === -1 && actions.push(ac));
+ currVisibilities.forEach(vi => visibilities.indexOf(vi) === -1 && visibilities.push(vi));
+ currWarehouseScopes.forEach(currWh => warehouses.findIndex(wh => wh.id === currWh.id) === -1 && warehouses.push(currWh));
+ currInventoryScopes.forEach(currInv => inventories.findIndex(inv => inv.id === currInv.id) === -1 && inventories.push(currInv));
+ // setSelectedPermissions({...selectedPermissions, actions});
+ }
+ });
+ formik.handleChange('actions')(actions.join(','));
+ formik.handleChange('visibilities')(visibilities.join(','));
+ formik.handleChange('warehouses')(warehouses.map(wh => wh.id).join(','));
+ formik.handleChange('inventories')(inventories.map(inv => inv.id).join(','));
+ };
+
const handleFileChange = e => {
const [file] = e.target.files;
if (file) {
@@ -456,40 +479,60 @@ function CreateEditUser(props) {
0}
name="warehouses"
gridStyleOverride={{ paddingLeft: '4rem !important' }}
- initlist={formik.values.warehouses}
+ allocatedList={formik.values.warehouses}
list={warehouses}
matchProp={{ a: '_id' }}
title="Warehouse"
- onChange={(val) => formik.handleChange('warehouses')(val)}
+ onChange={val => {
+ val = val?.map(obj => obj._id).join(',');
+ // setSelectedPermissions({...selectedPermissions, warehouses: val});
+ formik.handleChange('warehouses')(val);
+ }}
/>
0}
name="inventories"
gridStyleOverride={{ paddingRight: '2rem' }}
- initlist={formik.values.inventories}
+ allocatedList={formik.values.inventories}
list={inventories}
matchProp={{ a: '_id' }}
title="Inventory"
- onChange={(val) => formik.handleChange('inventories')(val)}
+ onChange={val => {
+ val = val?.map(obj => obj._id).join(',');
+ // setSelectedPermissions({...selectedPermissions, inventories: val});
+ formik.handleChange('inventories')(val);
+ }}
/>
0}
name="actions"
gridStyleOverride={{ paddingLeft: '4rem !important' }}
title="Actions"
toggles={actions}
- inittoggles={formik.values.actions}
- onChange={(val) => formik.handleChange('actions')(val)}
+ selectedToggles={formik.values.actions}
+ onChange={val => {
+ val = Object.keys(val).join(',');
+ // setSelectedPermissions({...selectedPermissions, actions: val});
+ formik.handleChange('actions')(val);
+ }}
/>
0}
name="visibilities"
gridStyleOverride={{ paddingRight: '2rem' }}
title="Application"
- toggles={permissions}
- inittoggles={formik.values.visibilities}
- onChange={(val) => formik.handleChange('visibilities')(val)}
+ toggles={visibilities}
+ selectedToggles={formik.values.visibilities}
+ onChange={val => {
+ val = Object.keys(val).join(',');
+ // setSelectedPermissions({...selectedPermissions, visibilities: val});
+ formik.handleChange('visibilities')(val);
+ }}
/>
record.name },
- { id: 'warehouse', label: 'Warehouse', limitWidth: true, value: record => warehouses && record.permissions?.warehouseScopes && record.permissions?.warehouseScopes?.length === warehouses?.length ? 'All' : record.permissions?.warehouseScopes ? record.permissions?.warehouseScopes.map(sc => sc.name).join(', ') : ''},
- { id: 'inventory', label: 'Inventories', limitWidth: true, value: record => inventories && record.permissions?.inventoryScopes && record.permissions?.inventoryScopes?.length === inventories?.length ? 'All' : record.permissions?.inventoryScopes ? record.permissions?.inventoryScopes.map(sc => sc.name).join(', ') : ''},
- { id: 'actions', label: 'Actions', limitWidth: true, value: record => actions && record.permissions?.actions && record.permissions?.actions?.length === actions?.length ? 'All' : record.permissions?.actions ? record.permissions?.actions.join(', ') : ''},
- { id: 'visibilities', label: 'App Modules', limitWidth: true, value: record => permissions && record.permissions?.allowedUIModules && record.permissions?.allowedUIModules?.length === permissions?.length ? 'All' : record.permissions?.allowedUIModules ? record.permissions?.allowedUIModules.join(', ') : ''},
+ { id: 'warehouse', label: 'Warehouse', limitWidth: true, value: record => {
+ const roleWh = record.permissions?.warehouseScopes;
+ return warehouses && roleWh && roleWh.length === warehouses.length ? 'All' : roleWh
+ ? warehouses.filter(wh => roleWh.findIndex(whCurr => whCurr.id === wh._id) > -1).map(wh => wh.name).join(', ') : '';
+ }
+ },
+ { id: 'inventory', label: 'Inventories', limitWidth: true, value: record => {
+ const roleIn = record.permissions?.inventoryScopes;
+ return inventories && roleIn && roleIn.length === inventories.length ? 'All' : roleIn
+ ? inventories.filter(inv => roleIn.findIndex(inCurr => inCurr.id === inv._id) > -1).map(inv => inv.name).join(', ') : '';
+ }
+ },
+ { id: 'actions', label: 'Actions', limitWidth: true, value: record => actions && record.permissions?.actions
+ && record.permissions?.actions?.length === actions?.length ? 'All' : record.permissions?.actions
+ ? record.permissions?.actions.join(', ') : ''},
+ { id: 'visibilities', label: 'App Modules', limitWidth: true, value: record => permissions && record.permissions?.allowedUIModules
+ && record.permissions?.allowedUIModules?.length === permissions?.length ? 'All' : record.permissions?.allowedUIModules
+ ? record.permissions?.allowedUIModules.join(', ') : ''},
{ id: 'status', label: 'Status', value: record => record.status === 'ACTIVE' ? Active
: Inactive }
];
const usersHandler = () => {
+ setUserLoader(true);
dispatch(
UsersActions.getUsersAction({
loader: 'loading-request',
slug: API.GET_USERS_DATA,
- method: 'get'
+ method: 'get',
+ callback: setUserLoader
})
);
};
const rolesHandler = () => {
+ setRoleLoader(true);
dispatch(
RolesActions.getRolesAction({
loader: 'loading-request',
slug: API.GET_ROLES_DATA,
- method: 'get'
+ method: 'get',
+ callback: setRoleLoader
})
);
};
useMemo(() => rolesHandler(), []);
+ useMemo(() => usersHandler(), []);
useEffect(() => {
if (usersData.length) {
@@ -188,7 +209,7 @@ function UserAccessScreen() {
let roles = JSON.parse(JSON.stringify(rolesData));
roles = roles.map((item) => {
item.name = item.name.split('-').join(' ').toUpperCase();
- item.permissions = item.permissions?.allowedUIModules?.join(',');
+ // item.permissions = item.permissions?.allowedUIModules?.join(',');
if (!item.permissions) {
item.permissions = 'NA';
}
@@ -209,7 +230,7 @@ function UserAccessScreen() {
let records = currentTab === 0 ? originalUserRecords : originalRolesRecords;
records = JSON.parse(JSON.stringify(records));
records.forEach(record => record.status = record.status ? 'ACTIVE' : 'INACTIVE');
- let searchList = currentTab === 0 ? ['fullName', 'phoneNumber', 'role_name', 'status'] : ['name', 'permissions', 'status']
+ let searchList = currentTab === 0 ? ['fullName', 'phoneNumber', 'role_name', 'status'] : ['name', 'permissions', 'status'];
const setter = currentTab === 0 ? setUserRecords : setRoleRecords;
searchList = searchList.concat(['createdBy.fullName', 'createdAt', 'updatedBy.fullName', 'updatedAt']);
const filteredRecords = records.filter(record => searchList.some(field => {
@@ -220,7 +241,7 @@ function UserAccessScreen() {
field = field[1];
}
return recordInner && recordInner[field] !== undefined && typeof recordInner[field] === 'string'
- && recordInner[field].toLowerCase().indexOf(value?.toLowerCase()) > -1
+ && recordInner[field].toLowerCase().indexOf(value?.toLowerCase()) > -1;
}));
records.forEach(record => record.status = record.status === 'ACTIVE');
setter(filteredRecords);
@@ -238,7 +259,7 @@ function UserAccessScreen() {
]}
/>
-
+
usersHandler()} />
@@ -275,10 +296,10 @@ function UserAccessScreen() {
-
-
+
+
diff --git a/src/routes/index.js b/src/routes/index.js
index afa9251..8850780 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -187,11 +187,18 @@ const protectedRoutes = [
component:
},
{
- name: 'Edot User',
+ name: 'Edit User',
key: 'edit-user',
route: '/setup/users-access/edit-user',
hide: true,
component:
+ },
+ {
+ name: 'Edit Role',
+ key: 'edit-role',
+ route: '/setup/users-access/edit-role',
+ hide: true,
+ component:
}
]
}
diff --git a/src/sagas/Roles.js b/src/sagas/Roles.js
index b2527cd..e18d162 100644
--- a/src/sagas/Roles.js
+++ b/src/sagas/Roles.js
@@ -1,5 +1,6 @@
import { AuthorizedAPI } from 'config';
import { takeLatest, call, put } from 'redux-saga/effects';
+import { toast } from 'react-toastify';
import RolesActions, { RolesTypes } from '../redux/RolesRedux';
import ApiServices from 'services/API/ApiServices';
@@ -10,6 +11,7 @@ export function* onRequestRolesData({ payload }) {
payload?.slug,
payload?.data
);
+ payload?.callback && payload?.callback(false);
if (response?.status === 200) {
yield put(
RolesActions.getRolesSuccess({
@@ -18,6 +20,7 @@ export function* onRequestRolesData({ payload }) {
})
);
} else {
+ toast('Failed to fetch roles');
payload.onFailedRolesData(response.data.error);
yield put(
RolesActions.getRolesFailure({
diff --git a/src/sagas/Users.js b/src/sagas/Users.js
index d7eb7b4..533cc86 100644
--- a/src/sagas/Users.js
+++ b/src/sagas/Users.js
@@ -11,6 +11,7 @@ export function* onRequestUsersData({ payload }) {
payload?.slug,
payload?.data
);
+ payload?.callback && payload?.callback(false);
if (response?.status === 200) {
yield put(
UsersActions.getUsersSuccess({
@@ -19,6 +20,7 @@ export function* onRequestUsersData({ payload }) {
})
);
} else {
+ toast('Failed to fetch user list');
payload.onFailedUsersData(response.data.error);
yield put(
UsersActions.getUsersFailure({
@@ -40,6 +42,7 @@ export function* onCreateUserData({ payload }) {
contentType: false
}
);
+ payload?.callback && payload?.callback(false);
if (response?.status === 200) {
const data = response.data?.data;
const msg = payload.toastMessage.replace('__placeholder__', data && data.fullName ? '"' + data.fullName + '" ' : '');