diff --git a/src/components/accessories/admin/users/userGroupsTable/UserGroupsTable.module.scss b/src/components/accessories/admin/users/userGroupsTable/UserGroupsTable.module.scss
new file mode 100644
index 000000000..253324402
--- /dev/null
+++ b/src/components/accessories/admin/users/userGroupsTable/UserGroupsTable.module.scss
@@ -0,0 +1,4 @@
+.table {
+ display: grid;
+ margin-top: 50px;
+}
diff --git a/src/components/accessories/admin/users/userGroupsTable/UserGroupsTable.tsx b/src/components/accessories/admin/users/userGroupsTable/UserGroupsTable.tsx
index 8a3080863..ddf558149 100644
--- a/src/components/accessories/admin/users/userGroupsTable/UserGroupsTable.tsx
+++ b/src/components/accessories/admin/users/userGroupsTable/UserGroupsTable.tsx
@@ -1,3 +1,109 @@
-import React from "react";
+import { CircularProgress } from "@mui/material";
+import { useAppDispatch, useAppSelector } from "libraries/hooks/redux";
+import React, { ReactNode, useEffect } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
-export const UserGroupsTable = () => <>UserGroupsTable, coming soon>;
+import { UserGroupDTO } from "../../../../../generated";
+import { usePermission } from "../../../../../libraries/permissionUtils/usePermission";
+import { ApiResponse } from "../../../../../state/types";
+import {
+ deleteUserGroup,
+ deleteUserGroupReset,
+ getUserGroups,
+} from "../../../../../state/usergroups";
+import { IState } from "../../../../../types";
+import InfoBox from "../../../infoBox/InfoBox";
+import Table from "../../../table/Table";
+
+import classes from "./UserGroupsTable.module.scss";
+
+interface IOwnProps {
+ headerActions: ReactNode;
+ onEdit: (row: UserGroupDTO) => void;
+}
+
+export const UserGroupsTable = ({ headerActions, onEdit }: IOwnProps) => {
+ const dispatch = useAppDispatch();
+ const { t } = useTranslation();
+ const canUpdate = usePermission("users.update");
+ const canDelete = usePermission("exams.delete");
+
+ useEffect(() => {
+ dispatch(getUserGroups());
+ return () => {
+ dispatch(deleteUserGroupReset());
+ };
+ }, [dispatch]);
+
+ const handleDelete = (row: UserGroupDTO) => {
+ dispatch(deleteUserGroup(row.code));
+ };
+
+ const header = ["code", "desc"];
+
+ const label = {
+ code: t("user.code"),
+ desc: t("user.description"),
+ };
+ const order = ["code", "desc"];
+
+ const { data, status, error } = useSelector<
+ IState,
+ ApiResponse
+ >((state) => state.usergroups.groupList);
+
+ const deleteGroup = useAppSelector((state) => state.usergroups.delete);
+
+ useEffect(() => {
+ if (deleteGroup.hasSucceeded) dispatch(getUserGroups());
+ }, [deleteGroup.hasSucceeded, dispatch]);
+
+ const formatDataToDisplay = (data: UserGroupDTO[]) => {
+ return data.map((item) => {
+ return {
+ code: item.code,
+ desc: item.desc ?? "",
+ };
+ });
+ };
+
+ return (
+
+ {(() => {
+ switch (status) {
+ case "FAIL":
+ return
;
+ case "LOADING":
+ return (
+
+ );
+
+ case "SUCCESS":
+ return (
+
+ );
+ case "SUCCESS_EMPTY":
+ return
;
+ default:
+ return;
+ }
+ })()}
+
+ );
+};
diff --git a/src/components/activities/adminActivity/AdminActivity.module.scss b/src/components/activities/adminActivity/AdminActivity.module.scss
index 22d4f3937..876abb6a9 100644
--- a/src/components/activities/adminActivity/AdminActivity.module.scss
+++ b/src/components/activities/adminActivity/AdminActivity.module.scss
@@ -14,7 +14,9 @@
border-radius: 8px;
flex-grow: 1;
margin: 30px 160px;
- // align-self: center;
+ @include susy-media($medium) {
+ margin: 20px 20px;
+ }
@include susy-media($medium-down) {
flex-direction: column;
margin: 20px 20px;
@@ -36,7 +38,7 @@
border-radius: 8px 0px 0px 8px;
width: max-content;
padding: 8px 0px;
- min-width: 260px;
+ min-width: 311px;
@include susy-media($medium-down) {
border-radius: 8px;
width: 100%;
diff --git a/src/consts.ts b/src/consts.ts
index e895d8c37..636a66ee8 100644
--- a/src/consts.ts
+++ b/src/consts.ts
@@ -25,6 +25,8 @@ export const PATHS = {
admin_vaccines_types_edit: "/admin/types/vaccines/:code/edit",
admin_users: "/admin/users",
admin_users_new: "/admin/users/new",
+ admin_usergroups_new: "/admin/users/groups/new",
+ admin_usergroups_edit: "/admin/users/groups/edit/:id",
admin_users_edit: "/admin/users/:id/edit",
admin_vaccines: "/admin/vaccines",
admin_vaccines_new: "/admin/vaccines/new",
diff --git a/src/generated/models/AdmissionDTO.ts b/src/generated/models/AdmissionDTO.ts
index 4b933c05e..df700ba52 100644
--- a/src/generated/models/AdmissionDTO.ts
+++ b/src/generated/models/AdmissionDTO.ts
@@ -200,13 +200,13 @@ export interface AdmissionDTO {
*/
deleted: string;
/**
- * @type {number}
+ * @type {string}
* @memberof AdmissionDTO
*/
- yprog?: number;
+ fhu?: string;
/**
- * @type {string}
+ * @type {number}
* @memberof AdmissionDTO
*/
- fhu?: string;
+ yprog?: number;
}
diff --git a/src/generated/models/TherapyRow.ts b/src/generated/models/TherapyRow.ts
index 7f96100ce..33b37f525 100644
--- a/src/generated/models/TherapyRow.ts
+++ b/src/generated/models/TherapyRow.ts
@@ -12,112 +12,112 @@
*/
import {
- Patient,
+ Patient,
} from './';
/**
- * @export
- * @interface TherapyRow
- */
+* @export
+* @interface TherapyRow
+*/
export interface TherapyRow {
- /**
- * @type {string}
- * @memberof TherapyRow
- */
- createdBy?: string;
- /**
- * @type {string}
- * @memberof TherapyRow
- */
- createdDate?: string;
- /**
- * @type {string}
- * @memberof TherapyRow
- */
- lastModifiedBy?: string;
- /**
- * @type {string}
- * @memberof TherapyRow
- */
- lastModifiedDate?: string;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- active?: number;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- therapyID?: number;
- /**
- * @type {Patient}
- * @memberof TherapyRow
- */
- patient: Patient;
- /**
- * @type {string}
- * @memberof TherapyRow
- */
- startDate: string;
- /**
- * @type {string}
- * @memberof TherapyRow
- */
- endDate: string;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- medicalId: number;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- qty: number;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- unitID: number;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- freqInDay: number;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- freqInPeriod: number;
- /**
- * @type {string}
- * @memberof TherapyRow
- */
- note?: string;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- notifyInt: number;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- smsInt: number;
- /**
- * @type {boolean}
- * @memberof TherapyRow
- */
- sms?: boolean;
- /**
- * @type {boolean}
- * @memberof TherapyRow
- */
- notify?: boolean;
- /**
- * @type {number}
- * @memberof TherapyRow
- */
- medical?: number;
+ /**
+ * @type {string}
+ * @memberof TherapyRow
+ */
+ createdBy?: string;
+ /**
+ * @type {string}
+ * @memberof TherapyRow
+ */
+ createdDate?: string;
+ /**
+ * @type {string}
+ * @memberof TherapyRow
+ */
+ lastModifiedBy?: string;
+ /**
+ * @type {string}
+ * @memberof TherapyRow
+ */
+ lastModifiedDate?: string;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ active?: number;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ therapyID?: number;
+ /**
+ * @type {Patient}
+ * @memberof TherapyRow
+ */
+ patient: Patient;
+ /**
+ * @type {string}
+ * @memberof TherapyRow
+ */
+ startDate: string;
+ /**
+ * @type {string}
+ * @memberof TherapyRow
+ */
+ endDate: string;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ medicalId: number;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ qty: number;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ unitID: number;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ freqInDay: number;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ freqInPeriod: number;
+ /**
+ * @type {string}
+ * @memberof TherapyRow
+ */
+ note?: string;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ notifyInt: number;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ smsInt: number;
+ /**
+ * @type {boolean}
+ * @memberof TherapyRow
+ */
+ sms?: boolean;
+ /**
+ * @type {boolean}
+ * @memberof TherapyRow
+ */
+ notify?: boolean;
+ /**
+ * @type {number}
+ * @memberof TherapyRow
+ */
+ medical?: number;
}
diff --git a/src/mockServer/fixtures/permissionDTO.ts b/src/mockServer/fixtures/permissionDTO.ts
new file mode 100644
index 000000000..57f53c3c8
--- /dev/null
+++ b/src/mockServer/fixtures/permissionDTO.ts
@@ -0,0 +1,10 @@
+import { PermissionDTO } from "../../generated";
+import permissionList from "./permissionList";
+
+export const permissionDTO: PermissionDTO[] = Array.from(permissionList).map(
+ (permissionName, i) => ({
+ name: permissionName,
+ id: i,
+ description: "",
+ })
+);
diff --git a/src/mockServer/fixtures/userGroupsDTO.ts b/src/mockServer/fixtures/userGroupsDTO.ts
index 5c39cefd3..f3bd7af6c 100644
--- a/src/mockServer/fixtures/userGroupsDTO.ts
+++ b/src/mockServer/fixtures/userGroupsDTO.ts
@@ -1,8 +1,45 @@
-import { UserGroupDTO } from "../../generated";
+import { UserGroupDTO, PermissionDTO } from "../../generated";
+import { permissionDTO } from "./permissionDTO";
export const userGroupsDTO: UserGroupDTO[] = [
- { code: "adm", desc: "admin" },
- { code: "con", desc: "contributor" },
- { code: "bot" },
+ { code: "adm", desc: "admin", permissions: permissionDTO },
+ {
+ code: "con",
+ desc: "contributor",
+ permissions: permissionDTO.reduce(
+ (acc: PermissionDTO[], curr, i) => (i % 5 === 0 ? [...acc, curr] : acc),
+ []
+ ),
+ },
+ {
+ code: "guest",
+ permissions: permissionDTO.reduce(
+ (acc: PermissionDTO[], curr) =>
+ // only permissions ending with "read"
+ /read$/.test(curr.name ?? "") ? [...acc, curr] : acc,
+ []
+ ),
+ },
+ {
+ code: "bot",
+ permissions: permissionDTO.reduce(
+ (acc: PermissionDTO[], curr) =>
+ // only permissions ending with "update" or "delete"
+ /(update|delete)$/.test(curr.name ?? "") ? [...acc, curr] : acc,
+ []
+ ),
+ },
+ {
+ code: "labo",
+ permissions: permissionDTO.reduce(
+ (acc: PermissionDTO[], curr) =>
+ // only examinations
+ curr.name === "laboratories.access" ||
+ /^examinations/.test(curr.name ?? "")
+ ? [...acc, curr]
+ : acc,
+ []
+ ),
+ },
{ code: "doc" },
];
diff --git a/src/mockServer/routes/permission.js b/src/mockServer/routes/permission.js
new file mode 100644
index 000000000..88cfd3486
--- /dev/null
+++ b/src/mockServer/routes/permission.js
@@ -0,0 +1,12 @@
+import { permissionDTO } from "../fixtures/permissionDTO";
+
+export const permissionRoutes = (server) => {
+ server.namespace("/permissions", () => {
+ server.get("/").intercept((_req, res) => {
+ res.status(200).json(permissionDTO);
+ });
+ server.put(":id").intercept((_req, res) => {
+ res.status(200).json(permissionDTO[0]);
+ });
+ });
+};
diff --git a/src/mockServer/routes/userGroups.js b/src/mockServer/routes/userGroups.js
index cee7fddf6..6ab84b4d4 100644
--- a/src/mockServer/routes/userGroups.js
+++ b/src/mockServer/routes/userGroups.js
@@ -1,9 +1,40 @@
import { userGroupsDTO } from "../fixtures/userGroupsDTO";
export const userGroupRoutes = (server) => {
- server.namespace("/users/groups", () => {
+ server.namespace("/usergroups", () => {
server.get("/").intercept((_req, res) => {
res.status(200).json(userGroupsDTO);
});
+ server.get("/:id").intercept((req, res) => {
+ console.log(req.params.id);
+ const group = userGroupsDTO.find(({ code }) => code === req.params.id);
+ if (!group) {
+ return res.status(404).json({
+ status: "BAD_REQUEST",
+ message: "User group not found.",
+ debugMessage: "User group not found.",
+ timestamp: "2024-09-16T08:02:53.878312662",
+ description: null,
+ });
+ }
+ res.status(200).json(group);
+ });
+
+ server.delete("/:code/permissions/:id").intercept((_req, res) => {
+ res.status(200).json(true);
+ });
+ server.post("/:code/permissions/:id").intercept((_req, res) => {
+ res.status(200).json(true);
+ });
+
+ server.post("/").intercept((_req, res) => {
+ res.status(200).json(userGroupsDTO[0]);
+ });
+ server.put("/").intercept((_req, res) => {
+ res.status(200).json(userGroupsDTO[0]);
+ });
+ server.delete("/:id").intercept((_req, res) => {
+ res.status(200).json(true);
+ });
});
};
diff --git a/src/mockServer/server.js b/src/mockServer/server.js
index 7e20c60e1..ec433cb26 100644
--- a/src/mockServer/server.js
+++ b/src/mockServer/server.js
@@ -24,6 +24,7 @@ import { opdRoutes } from "./routes/opd";
import { operationRoutes } from "./routes/operations";
import { operationTypeRoutes } from "./routes/operationTypes";
import { patientRoutes } from "./routes/patients";
+import { permissionRoutes } from "./routes/permission";
import { pregnantTreatmentTypeRoutes } from "./routes/pregnantTreatmentType";
import { pricesRoutes } from "./routes/prices";
import { suppliersRoutes } from "./routes/suppliers";
@@ -77,6 +78,7 @@ export function makeServer() {
medicalTypesRoutes(server);
pregnantTreatmentTypeRoutes(server);
deliveryResultTypeRoutes(server);
+ permissionRoutes(server);
labExamRequestRoutes(server);
});
return server;
diff --git a/src/resources/i18n/en.json b/src/resources/i18n/en.json
index 39fc5a534..ee5d80ab6 100644
--- a/src/resources/i18n/en.json
+++ b/src/resources/i18n/en.json
@@ -18,15 +18,26 @@
"number": "the value is not a valid number"
},
"user": {
+ "code": "Code",
+ "desc": "Description",
"users": "Users",
"username": "Username",
"group": "Group",
"groups": "Groups",
"password": "Password",
- "passwordRetype": "Re-type Password",
- "lastlogin": "Last login",
- "description": "Description",
+ "addGroup": "New group",
"addUser": "New user",
+ "editGroup": "Edit group",
+ "description": "Description",
+ "lastlogin": "Last login",
+ "groupCreated": "Group created",
+ "groupDeleted": "Group deleted",
+ "groupUpdated": "Group updated",
+ "groupUpdateSuccess": "Group updated successfully",
+ "groupCreateSuccess": "Group created successfully",
+ "groupDeleteSuccess": "Group deleted successfully",
+ "groupPermissionsOnlyOnUpdate": "You can edit a group's permission once you created it.",
+ "passwordRetype": "Re-type Password",
"createdSuccessTitle": "User created",
"createdSuccessMessage": "User has been created successfully!",
"updatedSuccessTitle": "User updated",
@@ -35,6 +46,7 @@
"validatePasswordNeeded": "No password provided.",
"validatePasswordTooShort": "Password is too short - should be 5 chars minimum.",
"validatePasswordTooWeak": "Please create a stronger password: 1 upper case letter, 1 lower case letter, 1 numeric digit",
+ "validateGroupCode": "Invalid group code",
"validatePasswordMustMatch": "Passwords must match",
"validateUserName": "You need to specify a user name",
"validateUserNameRegex": "Allowed characters: lowercase letters(abc), numbers(123), dot(.), dash (-) and underscore (_)"
@@ -555,7 +567,14 @@
"permission": {
"denied": "Permission denied",
"unauthorized": "Unauthorized",
- "accessdenied": "You don't have permission required to access this content"
+ "accessdenied": "You don't have permission required to access this content",
+ "name": "Name",
+ "create": "Create",
+ "read": "Read",
+ "update": "Update",
+ "deleted": "Deleted",
+ "accessarea": "Access area",
+ "accesscontrollist": "Access control list"
},
"therapy": {
"newtherapy": "New Therapy",
diff --git a/src/routes/Admin/AdminRoutes.tsx b/src/routes/Admin/AdminRoutes.tsx
index fb6bdfa8d..9f4ffa162 100644
--- a/src/routes/Admin/AdminRoutes.tsx
+++ b/src/routes/Admin/AdminRoutes.tsx
@@ -22,7 +22,13 @@ import {
NewSupplier,
Suppliers,
} from "../../components/accessories/admin/suppliers";
-import { EditUser, NewUser, Users } from "../../components/accessories/admin/users";
+import {
+ EditGroup,
+ EditUser,
+ NewGroup,
+ NewUser,
+ Users,
+} from "../../components/accessories/admin/users";
import {
EditVaccine,
NewVaccine,
@@ -210,12 +216,37 @@ export const AdminRoutes = () => {
{
path: getPath(PATHS.admin_users_new),
element: (
- } />
+ }
+ />
+ ),
+ },
+ {
+ path: getPath(PATHS.admin_usergroups_new),
+ element: (
+ }
+ />
),
- },{
+ },
+ {
+ path: getPath(PATHS.admin_usergroups_edit),
+ element: (
+ }
+ />
+ ),
+ },
+ {
path: getPath(PATHS.admin_users_edit),
element: (
- } />
+ }
+ />
),
},
{
diff --git a/src/state/permissions/index.ts b/src/state/permissions/index.ts
new file mode 100644
index 000000000..9acb9c91d
--- /dev/null
+++ b/src/state/permissions/index.ts
@@ -0,0 +1,3 @@
+export * from "./slice";
+export * from "./thunk";
+export * from "./types";
diff --git a/src/state/permissions/initial.ts b/src/state/permissions/initial.ts
new file mode 100644
index 000000000..1ffced27d
--- /dev/null
+++ b/src/state/permissions/initial.ts
@@ -0,0 +1,10 @@
+import { PermissionDTO } from "../../generated";
+import { IPermissionsState } from "./types";
+import { ApiResponse } from "../types";
+
+export const initial: IPermissionsState = {
+ getAll: new ApiResponse({
+ status: "IDLE",
+ data: new Array(),
+ }),
+};
diff --git a/src/state/permissions/slice.ts b/src/state/permissions/slice.ts
new file mode 100644
index 000000000..44dc08746
--- /dev/null
+++ b/src/state/permissions/slice.ts
@@ -0,0 +1,25 @@
+import { createSlice } from "@reduxjs/toolkit";
+import { isEmpty } from "lodash";
+import { ApiResponse } from "state/types";
+import { initial } from "./initial";
+import * as thunks from "./thunk";
+
+export const permissionSlice = createSlice({
+ name: "permissions",
+ initialState: initial,
+ reducers: {},
+ extraReducers: (builder) =>
+ builder
+ // Get Permissions
+ .addCase(thunks.getAllPermissions.pending, (state) => {
+ state.getAll = ApiResponse.loading();
+ })
+ .addCase(thunks.getAllPermissions.fulfilled, (state, action) => {
+ state.getAll = isEmpty(action.payload)
+ ? ApiResponse.empty()
+ : ApiResponse.value(action.payload);
+ })
+ .addCase(thunks.getAllPermissions.rejected, (state, action) => {
+ state.getAll = ApiResponse.error(action.payload);
+ }),
+});
diff --git a/src/state/permissions/thunk.ts b/src/state/permissions/thunk.ts
new file mode 100644
index 000000000..5f0547a1c
--- /dev/null
+++ b/src/state/permissions/thunk.ts
@@ -0,0 +1,14 @@
+import { createAsyncThunk } from "@reduxjs/toolkit";
+import { PermissionDTO, PermissionsApi } from "../../generated";
+import { customConfiguration } from "../../libraries/apiUtils/configuration";
+
+const api = new PermissionsApi(customConfiguration());
+
+export const getAllPermissions = createAsyncThunk(
+ "permissions/getPermissions",
+ async (_, thunkApi) =>
+ api
+ .retrieveAllPermissions()
+ .toPromise()
+ .catch((error) => thunkApi.rejectWithValue(error.response))
+);
diff --git a/src/state/permissions/types.ts b/src/state/permissions/types.ts
new file mode 100644
index 000000000..633b58617
--- /dev/null
+++ b/src/state/permissions/types.ts
@@ -0,0 +1,6 @@
+import { PermissionDTO } from "../../generated";
+import { ApiResponse } from "../types";
+
+export type IPermissionsState = {
+ getAll: ApiResponse>;
+};
diff --git a/src/state/store.ts b/src/state/store.ts
index fc45015d8..9e1606814 100644
--- a/src/state/store.ts
+++ b/src/state/store.ts
@@ -14,6 +14,7 @@ import { medicalSlice } from "./medicals";
import { opdSlice } from "./opds";
import { operationSlice } from "./operations";
import { patientSlice } from "./patients";
+import { permissionSlice } from "./permissions";
import { priceSlice } from "./prices";
import { summarySlice } from "./summary";
import { supplierSlice } from "./suppliers";
@@ -42,6 +43,7 @@ const reducer = combineReducers({
exams: examSlice.reducer,
bills: billSlice.reducer,
prices: priceSlice.reducer,
+ permissions: permissionSlice.reducer,
visits: visitSlice.reducer,
operations: operationSlice.reducer,
diseaseTypes: diseaseTypeSlice.reducer,
diff --git a/src/state/usergroups/index.ts b/src/state/usergroups/index.ts
index 4403a13f3..03416f8b9 100644
--- a/src/state/usergroups/index.ts
+++ b/src/state/usergroups/index.ts
@@ -1,3 +1,3 @@
-export * from "./thunk";
export * from "./slice";
+export * from "./thunk";
export * from "./types";
diff --git a/src/state/usergroups/initial.ts b/src/state/usergroups/initial.ts
index 1130e0549..2b128c253 100644
--- a/src/state/usergroups/initial.ts
+++ b/src/state/usergroups/initial.ts
@@ -7,7 +7,12 @@ export const initial: IUserGroupState = {
status: "IDLE",
data: new Array(),
}),
+ currentGroup: new ApiResponse({
+ status: "IDLE",
+ data: {} as UserGroupDTO,
+ }),
create: new ApiResponse({ status: "IDLE" }),
update: new ApiResponse({ status: "IDLE" }),
delete: new ApiResponse({ status: "IDLE" }),
+ setPermission: new ApiResponse({ status: "IDLE" }),
};
diff --git a/src/state/usergroups/slice.ts b/src/state/usergroups/slice.ts
index c8e59ec53..a6a8189a3 100644
--- a/src/state/usergroups/slice.ts
+++ b/src/state/usergroups/slice.ts
@@ -1,8 +1,8 @@
import { createSlice } from "@reduxjs/toolkit";
+import { isEmpty } from "lodash";
+import { ApiResponse } from "state/types";
import { initial } from "./initial";
import * as thunks from "./thunk";
-import { ApiResponse } from "state/types";
-import { isEmpty } from "lodash";
export const userGroupSlice = createSlice({
name: "userGroups",
@@ -26,11 +26,22 @@ export const userGroupSlice = createSlice({
})
.addCase(thunks.getUserGroups.fulfilled, (state, action) => {
state.groupList = isEmpty(action.payload)
- ? ApiResponse.empty() : ApiResponse.value(action.payload);
+ ? ApiResponse.empty()
+ : ApiResponse.value(action.payload);
})
.addCase(thunks.getUserGroups.rejected, (state, action) => {
state.groupList = ApiResponse.error(action.payload);
})
+ // Get User Groups
+ .addCase(thunks.getUserGroup.pending, (state) => {
+ state.groupList = ApiResponse.loading();
+ })
+ .addCase(thunks.getUserGroup.fulfilled, (state, action) => {
+ state.currentGroup = ApiResponse.value(action.payload);
+ })
+ .addCase(thunks.getUserGroup.rejected, (state, action) => {
+ state.groupList = ApiResponse.error(action.payload);
+ })
// Create User Group
.addCase(thunks.createUserGroup.pending, (state) => {
state.create = ApiResponse.loading();
@@ -55,7 +66,7 @@ export const userGroupSlice = createSlice({
.addCase(thunks.deleteUserGroup.pending, (state) => {
state.delete = ApiResponse.loading();
})
- .addCase(thunks.deleteUserGroup.fulfilled, (state, action) => {
+ .addCase(thunks.deleteUserGroup.fulfilled, (state) => {
state.delete.status = "SUCCESS";
})
.addCase(thunks.deleteUserGroup.rejected, (state, action) => {
diff --git a/src/state/usergroups/thunk.ts b/src/state/usergroups/thunk.ts
index eecb2b27a..39dc14647 100644
--- a/src/state/usergroups/thunk.ts
+++ b/src/state/usergroups/thunk.ts
@@ -41,3 +41,37 @@ export const deleteUserGroup = createAsyncThunk(
.toPromise()
.catch((error) => thunkApi.rejectWithValue(error.response))
);
+
+export const getUserGroup = createAsyncThunk(
+ "userGroups/getUserGroup",
+ async (groupCode: string, thunkApi) =>
+ api
+ // GET /users/groups/{group_code}
+ .getUserGroup({ groupCode })
+ .toPromise()
+ .catch((error) => thunkApi.rejectWithValue(error.response))
+);
+
+export const assignPermission = createAsyncThunk(
+ "userGroups/setUserGroupPermission",
+ async (
+ { permissionId, groupCode }: { permissionId: number; groupCode: string },
+ thunkApi
+ ) =>
+ api
+ .assignPermission({ groupCode, id: permissionId })
+ .toPromise()
+ .catch((error) => thunkApi.rejectWithValue(error.response))
+);
+
+export const revokePermission = createAsyncThunk(
+ "userGroups/setUserGroupPermission",
+ async (
+ { permissionId, groupCode }: { permissionId: number; groupCode: string },
+ thunkApi
+ ) =>
+ api
+ .revokePermission({ groupCode, id: permissionId })
+ .toPromise()
+ .catch((error) => thunkApi.rejectWithValue(error.response))
+);
\ No newline at end of file
diff --git a/src/state/usergroups/types.ts b/src/state/usergroups/types.ts
index 8cc643da2..60eb05cee 100644
--- a/src/state/usergroups/types.ts
+++ b/src/state/usergroups/types.ts
@@ -3,7 +3,9 @@ import { ApiResponse } from "../types";
export type IUserGroupState = {
groupList: ApiResponse>;
+ currentGroup: ApiResponse;
create: ApiResponse;
update: ApiResponse;
delete: ApiResponse;
+ setPermission: ApiResponse;
};
diff --git a/src/state/users/slice.ts b/src/state/users/slice.ts
index e3399993e..a79b1dcb4 100644
--- a/src/state/users/slice.ts
+++ b/src/state/users/slice.ts
@@ -77,5 +77,9 @@ export const userSlice = createSlice({
}),
});
-export const { createUserReset, updateUserReset, deleteUserReset } =
- userSlice.actions;
+export const {
+ createUserReset,
+ updateUserReset,
+ deleteUserReset,
+ getUserByIdReset,
+} = userSlice.actions;
diff --git a/src/types.ts b/src/types.ts
index 7b5c6bfff..37bd233f8 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -25,6 +25,7 @@ import { IUserGroupState } from "./state/usergroups/types";
import { IVaccineState } from "./state/vaccines/types";
import { ISupplierState } from "./state/suppliers/types";
import { ITypesState } from "./state/types/types";
+import { IPermissionsState } from "./state/permissions/types";
export interface IState {
main: IMainState;
@@ -54,6 +55,7 @@ export interface IState {
vaccines: IVaccineState;
types: ITypesState;
suppliers: ISupplierState;
+ permissions: IPermissionsState;
}
export enum FIELD_VALIDATION {