From f7d2341483e8c894018f00efd11511e355da53b8 Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Mon, 2 Oct 2023 15:56:26 +0330 Subject: [PATCH 1/9] CFE-4 role management page component --- mocks/handler.js | 33 ++++- public/locales/fa/app.json | 35 +++++ .../Form/CreateForm/CreateContent.jsx | 139 ++++++++++++++++++ .../CreateForm/__test__/CreateContent.test.js | 83 +++++++++++ .../Form/CreateForm/__test__/index.test.js | 30 ++++ .../role-management/Form/CreateForm/index.jsx | 34 +++++ .../role-management/Form/DeleteForm.jsx | 67 +++++++++ .../Form/UpdateForm/UpdateContext.jsx | 138 +++++++++++++++++ .../role-management/Form/UpdateForm/index.jsx | 35 +++++ .../RoleManagementComponent.jsx | 94 ++++++++++++ .../role-management/TableRowActions.jsx | 24 +++ .../role-management/TableToolbar.jsx | 11 ++ .../__test__/RoleManagementComponent.test.js | 17 +++ .../dashboard/role-management/index.jsx | 13 ++ src/core/data/apiRoutes.js | 16 +- src/core/data/sidebarMenu.jsx | 9 ++ src/lib/app/hooks/usePermissions.jsx | 25 ++++ src/pages/dashboard/role-management/index.jsx | 26 ++++ 18 files changed, 822 insertions(+), 7 deletions(-) create mode 100644 src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx create mode 100644 src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js create mode 100644 src/components/dashboard/role-management/Form/CreateForm/__test__/index.test.js create mode 100644 src/components/dashboard/role-management/Form/CreateForm/index.jsx create mode 100644 src/components/dashboard/role-management/Form/DeleteForm.jsx create mode 100644 src/components/dashboard/role-management/Form/UpdateForm/UpdateContext.jsx create mode 100644 src/components/dashboard/role-management/Form/UpdateForm/index.jsx create mode 100644 src/components/dashboard/role-management/RoleManagementComponent.jsx create mode 100644 src/components/dashboard/role-management/TableRowActions.jsx create mode 100644 src/components/dashboard/role-management/TableToolbar.jsx create mode 100644 src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js create mode 100644 src/components/dashboard/role-management/index.jsx create mode 100644 src/lib/app/hooks/usePermissions.jsx create mode 100644 src/pages/dashboard/role-management/index.jsx diff --git a/mocks/handler.js b/mocks/handler.js index 49e0f99..5e67894 100644 --- a/mocks/handler.js +++ b/mocks/handler.js @@ -1,8 +1,29 @@ -import {GET_USER_ROUTE} from "@/core/data/apiRoutes"; +import {GET_PERMISSIONS_LIST, GET_USER_ROUTE} from "@/core/data/apiRoutes"; import {rest} from "msw"; -export const handler = [rest.get(GET_USER_ROUTE, (req, res, ctx) => { - return res(ctx.json({ - id: 10 - })) -})] \ No newline at end of file +export const handler = [ + rest.get(GET_USER_ROUTE, (req, res, ctx) => { + return res(ctx.json({ + id: 10 + })) + }), + rest.get(GET_PERMISSIONS_LIST, (req, res, ctx) => { + return res(ctx.json( + { + data:[ + { + id: 1, + name: "manage_passenger_office_navgan", + name_fa: "مدیریت کارتابل رییس اداره مسافری استان" + }, + { + id: 2, + name: "manage_province_working_group_navgan", + name_fa:"مدیریت کارتابل کارگروه استانی" + } + ] + } + )) + }), + +] \ No newline at end of file diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index e813849..39531c9 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -32,6 +32,7 @@ "dashboard": "داشبورد", "change-password": "تغییر رمز عبور", "edit-profile": "ویرایش پروفایل", + "role-management": "مدیریت دسترسی", "admin": "مدیریت" }, "secondary": { @@ -118,5 +119,39 @@ "upload_file_format": "فرمت قابل قبول : png,jpg,pdf", "delete": "پاک کردن", "uploadfile_error": "حجم فایل بیشتر از 2 مگابایت می باشد" + }, + "RoleManagement": { + "id": "کد یکتا", + "name_fa": "نام فارسی ", + "name": "نام انگلیسی", + "created_at": "تاریخ درخواست", + "updated_at": "تاریخ بروزرسانی" + }, + "AddDialog": { + "add": "افزودن", + "name_en": "نام انگلیسی", + "name_en_error": "وارد کردن نام انگلیسی الزامیست", + "name_fa": "نام فارسی", + "name_fa_error": "وارد کردن نام فارسی الزامیست", + "permission": "دسترسی", + "permission_min_error": "حداقل باید یک دسترسی انتخاب شود", + "phone_number": "شماره تلفن", + "phone_number_positive": "شماره تلفن باید مثبت باشد", + "phone_number_error": "وارد کردن شماره تلفن الزامیست", + "phone_number_number": "شماره تلفن باید شامل اعداد باشد", + "phone_number_max": "شماره تلفن باید شامل 11 رقم باشد", + "national_id_positive": "کد ملی باید مثبت باشد", + "national_id_number": "کد ملی باید شامل اعداد باشد", + "national_id_max": "کد ملی باید شامل 10 رقم باشد", + "national_id": "کد ملی", + "national_id_error": "وارد کردن کد ملی الزامیست", + "type_id_error": "وارد کردن نوع کاربر الزامیست", + "navgan_id_error": "وارد کردن کد ناوگان الزامیست", + "refahi": "رفاهی", + "navgan": "ناوگان", + "type_id": "نوع کاربر", + "navgan_id": "کد ناوگان", + "button-cancel": "انصراف", + "button-add": "ثبت" } } diff --git a/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx b/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx new file mode 100644 index 0000000..117e009 --- /dev/null +++ b/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx @@ -0,0 +1,139 @@ +import { + Button, + Checkbox, + DialogActions, + DialogContent, DialogTitle, + FormControl, + FormControlLabel, + FormHelperText, + FormLabel, + Grid, + Stack, + TextField +} from "@mui/material"; +import {useTranslations} from "next-intl"; +import useRequest from "@/lib/app/hooks/useRequest"; +import * as Yup from "yup"; +import {useFormik} from "formik"; +import {ADD_ROLE_MANAGEMENT} from "@/core/data/apiRoutes"; +import usePermissions from "@/lib/app/hooks/usePermissions"; + +const CreateContent = ({mutate, fetchUrl, setOpenConfirmDialog}) => { + const t = useTranslations(); + const requestServer = useRequest({auth: true}) + const {permissions_list} = usePermissions() + const validationSchema = Yup.object().shape({ + name_en: Yup.string().required(t("AddDialog.name_en_error")), + name_fa: Yup.string().required(t("AddDialog.name_fa_error")), + permissions: Yup.array().min(1, t("AddDialog.permission_min_error")).required(t("AddDialog.permission")), + }); + const formik = useFormik({ + initialValues: { + name_en: "", + name_fa: "", + permissions: [], + }, validationSchema, onSubmit: (values, {setSubmitting}) => { + const formData = new FormData(); + formData.append("name_en", values.name_en); + formData.append("name_fa", values.name_fa); + for (let i = 0; i < values.permissions.length; i++) { + formData.append(`permissions[${i}]`, values.permissions[i]); + } + + requestServer(ADD_ROLE_MANAGEMENT, 'post', { + data: formData, + }).then((response) => { + setOpenConfirmDialog(false) + mutate(fetchUrl) + update_notification() + }).catch(() => { + }).finally(() => { + setSubmitting(false); + }); + }, + }); + + return ( + <> + {t("AddDialog.add")} + + + + + + + + {t("AddDialog.permission")}
+ + {formik.touched.permissions && formik.errors.permissions} + + {permissions_list ? ( + permissions_list.map((permission) => ( + + { + if (e.target.checked) { + formik.setFieldValue("permissions", [...formik.values.permissions, permission.id]) + } else { + formik.setFieldValue("permissions", formik.values.permissions.filter((id) => id !== permission.id)) + } + }} + /> + } + label={permission.name_fa} + /> + + )) + ) : null} + + +
+
+
+
+ + + + + + ) +} +export default CreateContent \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js b/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js new file mode 100644 index 0000000..cd690d2 --- /dev/null +++ b/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js @@ -0,0 +1,83 @@ +import {act, fireEvent, render, screen} from "@testing-library/react"; +import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider"; +import CreateContent from "@/components/dashboard/role-management/Form/CreateForm/CreateContent"; + +describe("Create Content component from Create Form Component in Role Management Component",()=>{ + describe("Rendering", ()=>{ + it('should see AddDialog text in the top ', () => { + render( + + + + ) + const textElement = screen.queryByText("افزودن") + expect(textElement).toBeInTheDocument() + }); + it('should see name_en text', () => { + render( + + + + ) + const textElement = screen.queryByLabelText("نام انگلیسی") + expect(textElement).toBeInTheDocument() + }); + it('should see name_fa text', () => { + render( + + + + ) + const textElement = screen.queryByLabelText("نام فارسی") + expect(textElement).toBeInTheDocument() + }); + }) + + describe("Behavior",()=>{ + it('should see what fill in the name_en input', async () => { + render( + + + + ) + const nameEnglishInput = screen.getByLabelText('نام انگلیسی'); + + fireEvent.change(nameEnglishInput, {target: {value: 'testuser'}}); + await act(()=>{ + // Simulate user input + expect(nameEnglishInput).toHaveValue('testuser'); + }) + }); + it('should see what fill in the name_fa input', async () => { + localStorage.setItem("_token", "token") + render( + + + + ) + const nameFarsiInput = screen.getByLabelText('نام فارسی'); + + fireEvent.change(nameFarsiInput, {target: {value: 'testuser'}}); + await act(()=>{ + // Simulate user input + expect(nameFarsiInput).toHaveValue('testuser'); + }) + }); + + + it('should return permissions_list', async () => { + localStorage.setItem("_token", "token") + render( + + + + ) + const checkboxElement = await screen.findAllByTestId("PermissionList-checkbox") + expect(checkboxElement).toHaveLength(2) + }); + + it('should ', () => { + + }); + }) +}) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/CreateForm/__test__/index.test.js b/src/components/dashboard/role-management/Form/CreateForm/__test__/index.test.js new file mode 100644 index 0000000..b4f0e82 --- /dev/null +++ b/src/components/dashboard/role-management/Form/CreateForm/__test__/index.test.js @@ -0,0 +1,30 @@ +import {fireEvent, queryByText, render, screen} from "@testing-library/react"; +import CreateForm from "@/components/dashboard/role-management/Form/CreateForm"; +import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider"; + +describe("Create Form Component from Role Management Component",()=>{ + describe("Rendering",()=>{ + + it('should see Dialog text', () => { + render( + + + + ) + const textElement = screen.queryByText("افزودن") + expect(textElement).toBeInTheDocument() + }); + + it('should see Tooltip text when mouse over', () => { + render( + + + + ) + const buttonElement = screen.getByText("افزودن"); + fireEvent.mouseOver(buttonElement); + const tooltipTextElement = screen.getByText("افزودن"); + expect(tooltipTextElement).toBeInTheDocument(); + }); + }) +}) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/CreateForm/index.jsx b/src/components/dashboard/role-management/Form/CreateForm/index.jsx new file mode 100644 index 0000000..8cbe859 --- /dev/null +++ b/src/components/dashboard/role-management/Form/CreateForm/index.jsx @@ -0,0 +1,34 @@ +import {Button, Dialog, DialogTitle, Stack, Tooltip} from "@mui/material"; +import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; +import {useTranslations} from "next-intl"; +import {useState} from "react"; +import CreateContent from "./CreateContent"; + +const CreateForm = ({mutate, fetchUrl}) => { + const t = useTranslations(); + const [openConfirmDialog, setOpenConfirmDialog] = useState(false); + + return ( + + + + + + + + + ) +} +export default CreateForm \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/DeleteForm.jsx b/src/components/dashboard/role-management/Form/DeleteForm.jsx new file mode 100644 index 0000000..9c613b1 --- /dev/null +++ b/src/components/dashboard/role-management/Form/DeleteForm.jsx @@ -0,0 +1,67 @@ +import {useTranslations} from "next-intl"; +import {useState} from "react"; +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + IconButton, + Tooltip, + Typography +} from "@mui/material"; +import DeleteIcon from '@mui/icons-material/Delete'; +import useRequest from "@/lib/app/hooks/useRequest"; +import useNotification from "@/lib/app/hooks/useNotification"; +import {DELETE_ROLE_MANAGEMENT} from "@/core/data/apiRoutes"; + +const DeleteForm = ({rowId, fetchUrl, mutate}) => { + const t = useTranslations(); + const [openConfirmDialog, setOpenConfirmDialog] = useState(false); + const [isSubmitting, setIsSubmitting] = useState(false) + const requestServer = useRequest({auth: true}) + const {update_notification} = useNotification() + const handleSubmit = () => { + setIsSubmitting(true) + requestServer(`${DELETE_ROLE_MANAGEMENT}/${rowId}`, 'delete').then((response) => { + mutate(fetchUrl) + update_notification() + }).catch(() => { + }).finally(() => { + setIsSubmitting(false) + }); + } + + return ( + <> + + { + setOpenConfirmDialog(true) + }} + > + + + + + {t("DeleteDialog.delete")} + + {t("DeleteDialog.typography")} + + + + + + + + ); +}; +export default DeleteForm; \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/UpdateForm/UpdateContext.jsx b/src/components/dashboard/role-management/Form/UpdateForm/UpdateContext.jsx new file mode 100644 index 0000000..e2f2980 --- /dev/null +++ b/src/components/dashboard/role-management/Form/UpdateForm/UpdateContext.jsx @@ -0,0 +1,138 @@ +import { + Button, + Checkbox, DialogActions, + DialogContent, + FormControl, + FormControlLabel, + FormHelperText, + FormLabel, + Grid, + Stack, + TextField +} from "@mui/material"; +import {useFormik} from "formik"; +import {UPDATE_ROLE_MANAGEMENT} from "@/core/data/apiRoutes"; +import * as Yup from "yup"; +import usePermissions from "@/lib/app/hooks/usePermissions"; +import useNotification from "@/lib/app/hooks/useNotification"; +import useRequest from "@/lib/app/hooks/useRequest"; +import {useTranslations} from "next-intl"; +import {useState} from "react"; + +const UpdateContent = ({mutate, fetchUrl, setOpenConfirmDialog}) => { + const t = useTranslations(); + const requestServer = useRequest({auth: true}) + const {update_notification} = useNotification() + const {permissions_list} = usePermissions() + const [openConfirmDialog, setOpenConfirmDialog] = useState(false); + + const validationSchema = Yup.object().shape({ + name: Yup.string().required(t("UpdateDialog.name_error")), + name_fa: Yup.string().required(t("UpdateDialog.name_fa_error")), + permissions: Yup.array().min(1, t("UpdateDialog.permission_min_error")).required(t("UpdateDialog.permission")), + }); + + const formik = useFormik({ + initialValues: { + name: row.getValue("name"), + name_fa: row.getValue("name_fa"), + permissions: row.original.permissions.map((obj) => obj.id), + }, validationSchema, onSubmit: (values, {setSubmitting}) => { + const formData = new FormData(); + formData.append("name", values.name); + formData.append("name_fa", values.name_fa); + for (let i = 0; i < values.permissions.length; i++) { + formData.append(`permissions[${i}]`, values.permissions[i]); + } + + requestServer(`${UPDATE_ROLE_MANAGEMENT}/${row.getValue("id")}`, 'post', { + data: formData, + }).then((response) => { + mutate(fetchUrl) + update_notification() + }).catch(() => { + }).finally(() => { + setSubmitting(false); + }); + }, + }); + + return( + <> + + + + + + + + {t("UpdateDialog.permission")}
+ + {formik.touched.permissions && formik.errors.permissions} + + {permissions_list ? ( + permissions_list.map((permission) => ( + + { + if (e.target.checked) { + formik.setFieldValue("permissions", [...formik.values.permissions, permission.id]) + } else { + formik.setFieldValue("permissions", formik.values.permissions.filter((id) => id !== permission.id)) + } + }} + /> + } + label={permission.name_fa} + /> + + )) + ) : null} + + +
+
+
+
+ + + + + + ) +} +export default UpdateContent \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/UpdateForm/index.jsx b/src/components/dashboard/role-management/Form/UpdateForm/index.jsx new file mode 100644 index 0000000..115e284 --- /dev/null +++ b/src/components/dashboard/role-management/Form/UpdateForm/index.jsx @@ -0,0 +1,35 @@ +import {Button, Dialog, DialogTitle, Stack, Tooltip} from "@mui/material"; +import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; +import {useTranslations} from "next-intl"; +import {useState} from "react"; +import CreateContent from "./CreateContent"; + +const UpdateForm = ({mutate, fetchUrl}) => { + const t = useTranslations(); + const [openConfirmDialog, setOpenConfirmDialog] = useState(false); + + return ( + + + + + + {t("UpdateDialog.update ")} + + + + ) +} +export default UpdateForm \ No newline at end of file diff --git a/src/components/dashboard/role-management/RoleManagementComponent.jsx b/src/components/dashboard/role-management/RoleManagementComponent.jsx new file mode 100644 index 0000000..1aea1b7 --- /dev/null +++ b/src/components/dashboard/role-management/RoleManagementComponent.jsx @@ -0,0 +1,94 @@ +import DataTable from "@/core/components/DataTable"; +import {GET_ROLE_MANAGEMENT} from "@/core/data/apiRoutes"; +import TableToolbar from "@/components/dashboard/role-management/TableToolbar"; +import TableRowActions from "@/components/dashboard/role-management/TableRowActions"; +import {Box, Typography} from "@mui/material"; +import {useTranslations} from "next-intl"; +import {useMemo} from "react"; +import moment from "jalali-moment"; +import MuiDatePicker from "@/core/components/MuiDatePicker"; + +const RoleManagementComponent = () => { + const t = useTranslations(); + + const columns = useMemo(() => [{ + accessorFn: (row) => row.id, + id: "id", + sortDescFirst: true, + header: t("RoleManagement.id"), + enableColumnFilter: true, + datatype: "numeric", + filterFn: "equals", + columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "between",], + Cell: ({renderedCellValue}) => ({renderedCellValue}), + }, + { + accessorFn: (row) => row.name_fa, + id: "name_fa", + header: t("RoleManagement.name_fa"), + enableColumnFilter: true, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["contains", "equals", "notEquals"], + Cell: ({renderedCellValue}) => ({renderedCellValue}), + }, + { + accessorFn: (row) => row.name, + id: "name", + header: t("RoleManagement.name"), + enableColumnFilter: true, + datatype: "text", + filterFn: "contains", + columnFilterModeOptions: ["contains"], + Cell: ({renderedCellValue}) => ({renderedCellValue}), + }, + { + accessorFn: (row) => moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"), + id: "created_at", + header: t("RoleManagement.created_at"), + enableColumnFilter: true, + datatype: "date", + filterFn: "lessThan", + columnFilterModeOptions: ["lessThan", "greaterThan"], + Cell: ({renderedCellValue}) => { + return {renderedCellValue}; + }, + Header: ({column}) => <>{column.columnDef.header}, + Filter: ({column}) => { + return (); + }, + }, { + accessorFn: (row) => moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"), + id: "updated_at", + header: t("RoleManagement.updated_at"), + enableColumnFilter: false, + datatype: "numeric", + Cell: ({renderedCellValue}) => ({renderedCellValue}), + }], []); + return( + + + + ) +} +export default RoleManagementComponent \ No newline at end of file diff --git a/src/components/dashboard/role-management/TableRowActions.jsx b/src/components/dashboard/role-management/TableRowActions.jsx new file mode 100644 index 0000000..cd72356 --- /dev/null +++ b/src/components/dashboard/role-management/TableRowActions.jsx @@ -0,0 +1,24 @@ +import {Box} from "@mui/material"; +import DeleteForm from "./Form/DeleteForm" +import UpdateForm from "@/components/dashboard/role-management/Form/UpdateForm"; + + +const TableRowActions = ({row, mutate, fetchUrl}) => { + + return ( + + + + + ); +}; + +export default TableRowActions; diff --git a/src/components/dashboard/role-management/TableToolbar.jsx b/src/components/dashboard/role-management/TableToolbar.jsx new file mode 100644 index 0000000..c4cb13b --- /dev/null +++ b/src/components/dashboard/role-management/TableToolbar.jsx @@ -0,0 +1,11 @@ +import {useTranslations} from "next-intl"; +import CreateForm from "./Form/CreateForm/index"; + +function TableToolbar({mutate, fetchUrl}) { + const t = useTranslations(); + + return + +} + +export default TableToolbar; diff --git a/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js b/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js new file mode 100644 index 0000000..d21081c --- /dev/null +++ b/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js @@ -0,0 +1,17 @@ +import {render} from "@testing-library/react"; +import MockAppWithProviders from "../../../../../mocks/AppWithProvider"; +import RoleManagementComponent from "@/components/dashboard/role-management/RoleManagementComponent"; + +describe("Role Management Component from Role Management page",()=>{ + describe("Rendering",()=>{ + it('should show columns text', () => { + render(( + + + + )) + const textElement = screen.getByText("کد یکتا") + expect(textElement).toBeInTheDocument() + }); + }) +}) \ No newline at end of file diff --git a/src/components/dashboard/role-management/index.jsx b/src/components/dashboard/role-management/index.jsx new file mode 100644 index 0000000..09f15bf --- /dev/null +++ b/src/components/dashboard/role-management/index.jsx @@ -0,0 +1,13 @@ +import DashboardLayouts from "@/layouts/dashboardLayouts"; +import RoleManagementComponent from "@/components/dashboard/role-management/RoleManagementComponent"; + +function DashboardRoleManagementComponent() { + + return ( + + + + ); +} + +export default DashboardRoleManagementComponent; diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index 06dd4e9..31b0f8e 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -10,4 +10,18 @@ export const SET_USER_PASSWORD = BASE_URL + "/dashboard/profile/change_password" //user data export const GET_USER_ROUTE = BASE_URL + "/dashboard/profile/info"; -//user data \ No newline at end of file +//user data + +// role management +export const GET_ROLE_MANAGEMENT = + BASE_URL + "/api/roles" +export const ADD_ROLE_MANAGEMENT = + BASE_URL + "/api/roles" +export const UPDATE_ROLE_MANAGEMENT = + BASE_URL + "/api/roles" +export const DELETE_ROLE_MANAGEMENT = + BASE_URL + "/api/roles" + +export const GET_PERMISSIONS_LIST = + BASE_URL + "/api/roles/list" +//role management \ No newline at end of file diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx index ca946a5..dfc7df7 100644 --- a/src/core/data/sidebarMenu.jsx +++ b/src/core/data/sidebarMenu.jsx @@ -10,6 +10,15 @@ const sidebarMenu = [ selected: false, permission: "all", }, + { + key: "sidebar.role-management", + name : "role_management", + type: "page", + route: "/dashboard/role-management", + icon: , + selected: false, + permission: "all", + }, ], ]; diff --git a/src/lib/app/hooks/usePermissions.jsx b/src/lib/app/hooks/usePermissions.jsx new file mode 100644 index 0000000..0e6aa07 --- /dev/null +++ b/src/lib/app/hooks/usePermissions.jsx @@ -0,0 +1,25 @@ +import useRequest from "@/lib/app/hooks/useRequest"; +import useSWR from "swr"; +import {GET_PERMISSIONS_LIST} from "@/core/data/apiRoutes"; + +const usePermissions = () => { + const requestServer = useRequest({auth: true, notification: false}) + const fetcher = (...args) => { + return requestServer(args, 'get').then((response) => { + return response.data.data; + }).catch(() => { + }) + }; + + const {data} = useSWR(GET_PERMISSIONS_LIST, fetcher, { + revalidateIfStale: false, + revalidateOnFocus: false, + revalidateOnReconnect: false + }) + const permissions_list = data + //swr config + + // render data + return {permissions_list} +} +export default usePermissions; \ No newline at end of file diff --git a/src/pages/dashboard/role-management/index.jsx b/src/pages/dashboard/role-management/index.jsx new file mode 100644 index 0000000..c309729 --- /dev/null +++ b/src/pages/dashboard/role-management/index.jsx @@ -0,0 +1,26 @@ +import RolePermissionMiddleware from "@/middlewares/RolePermission"; +import WithAuthMiddleware from "@/middlewares/WithAuth"; +import {parse} from "next-useragent"; +import DashboardRoleManagementComponent from "@/components/dashboard/role-management"; + +const requiredPermissions = ["manage_roles"]; +export default function RoleManagement() { + return ( + + + + + + ); +} + +export async function getServerSideProps({req, locale}) { + const {isBot} = parse(req.headers["user-agent"]); + return { + props: { + messages: (await import(`&/locales/${locale}/app.json`)).default, + title: "Dashboard.role_management_page", + isBot, + }, + }; +} From f507f38a00d61407ba6b0143cef202263b7e06fc Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Mon, 2 Oct 2023 16:26:24 +0330 Subject: [PATCH 2/9] CFE-4 role management component before git pull --- .../Form/CreateForm/__test__/CreateContent.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js b/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js index cd690d2..1742b12 100644 --- a/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js +++ b/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js @@ -66,7 +66,6 @@ describe("Create Content component from Create Form Component in Role Management it('should return permissions_list', async () => { - localStorage.setItem("_token", "token") render( @@ -76,7 +75,7 @@ describe("Create Content component from Create Form Component in Role Management expect(checkboxElement).toHaveLength(2) }); - it('should ', () => { + it('should get checked if permission list item get clicked', () => { }); }) From e24922918784ff670d1c2b4575c8c4d0dbebf5b9 Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Mon, 9 Oct 2023 11:15:41 +0330 Subject: [PATCH 3/9] CFE-4 role management test --- .env.test | 12 ++ public/locales/fa/app.json | 28 +++ .../CreateForm/__test__/CreateContent.test.js | 86 +++++++- .../role-management/Form/DeleteForm.jsx | 67 ------ .../Form/DeleteForm/DeleteContent.jsx | 42 ++++ .../DeleteForm/__test__/DeleteContent.test.js | 53 +++++ .../Form/DeleteForm/__test__/index.test.js | 29 +++ .../role-management/Form/DeleteForm/index.jsx | 39 ++++ .../{UpdateContext.jsx => UpdateContent.jsx} | 26 +-- .../UpdateForm/__test__/UpdateContent.test.js | 201 ++++++++++++++++++ .../Form/UpdateForm/__test__/index.test.js | 30 +++ .../role-management/Form/UpdateForm/index.jsx | 7 +- .../role-management/TableRowActions.jsx | 2 +- .../__test__/RoleManagementComponent.test.js | 2 +- src/core/components/DataTable.jsx | 1 - src/lib/app/contexts/language.jsx | 6 +- 16 files changed, 535 insertions(+), 96 deletions(-) create mode 100644 .env.test delete mode 100644 src/components/dashboard/role-management/Form/DeleteForm.jsx create mode 100644 src/components/dashboard/role-management/Form/DeleteForm/DeleteContent.jsx create mode 100644 src/components/dashboard/role-management/Form/DeleteForm/__test__/DeleteContent.test.js create mode 100644 src/components/dashboard/role-management/Form/DeleteForm/__test__/index.test.js create mode 100644 src/components/dashboard/role-management/Form/DeleteForm/index.jsx rename src/components/dashboard/role-management/Form/UpdateForm/{UpdateContext.jsx => UpdateContent.jsx} (87%) create mode 100644 src/components/dashboard/role-management/Form/UpdateForm/__test__/UpdateContent.test.js create mode 100644 src/components/dashboard/role-management/Form/UpdateForm/__test__/index.test.js diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..0be16f0 --- /dev/null +++ b/.env.test @@ -0,0 +1,12 @@ +NEXT_PUBLIC_API_NAME = "CRM Dashboard" +NEXT_PUBLIC_API_VERSION = "0.0.1" +NEXT_PUBLIC_DEFAULT_LANGUAGE = "fa" +NEXT_PUBLIC_DEFAULT_DIRECTION = "rtl" + +NEXT_PUBLIC_PRIMARY_MAIN = "#1b4332" +NEXT_PUBLIC_SECONDARY_MAIN = "#800e13" + +NEXT_PUBLIC_BASE_URL = "https://crm.witel.ir" +NEXT_PUBLIC_POWERED_BY_URL = "https://witel.ir" + +NODE_ENV = "development" \ No newline at end of file diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 39531c9..aa32ec4 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -153,5 +153,33 @@ "navgan_id": "کد ناوگان", "button-cancel": "انصراف", "button-add": "ثبت" + }, + "UpdateDialog": { + "update": "ویرایش", + "description": "توضیحات خود را وارد نمائید", + "description_error": "وارد کردن توضیحات الزامی است!", + "next-state-id": "وضعیت", + "next-state-id-error": "وارد کردن وضعیت الزامیست", + "update-tooltip": "ویرایش", + "button-cancel": "بستن", + "refahi": "رفاهی", + "navgan": "ناوگان", + "phone_number": "شماره تلفن", + "national_id": "کد ملی", + "name_en": "نام انگلیسی", + "name_en_error": "وارد کردن نام انگلیسی الزامیست", + "name_fa": "نام فارسی", + "name_fa_error": "وارد کردن نام فارسی الزامیست", + "permission": "دسترسی", + "permission_min_error": "حداقل باید یک دسترسی انتخاب شود", + "type_id": "نوع کاربر", + "navgan_id": "کد ناوگان", + "button-update": "ثبت" + }, + "DeleteDialog": { + "delete": "حذف", + "button-cancel": "انصراف", + "typography": "آیا از حدف این مورد اطمینان دارید ؟", + "button-delete": "حذف کردن" } } diff --git a/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js b/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js index 1742b12..3e31b8f 100644 --- a/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js +++ b/src/components/dashboard/role-management/Form/CreateForm/__test__/CreateContent.test.js @@ -1,4 +1,4 @@ -import {act, fireEvent, render, screen} from "@testing-library/react"; +import {act, fireEvent, render, screen, waitFor} from "@testing-library/react"; import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider"; import CreateContent from "@/components/dashboard/role-management/Form/CreateForm/CreateContent"; @@ -31,6 +31,16 @@ describe("Create Content component from Create Form Component in Role Management const textElement = screen.queryByLabelText("نام فارسی") expect(textElement).toBeInTheDocument() }); + it('should see name_fa text', () => { + render( + + + + ) + const textElement = screen.queryByLabelText("نام فارسی") + expect(textElement).toBeInTheDocument() + }); + }) describe("Behavior",()=>{ @@ -49,7 +59,6 @@ describe("Create Content component from Create Form Component in Role Management }) }); it('should see what fill in the name_fa input', async () => { - localStorage.setItem("_token", "token") render( @@ -63,8 +72,6 @@ describe("Create Content component from Create Form Component in Role Management expect(nameFarsiInput).toHaveValue('testuser'); }) }); - - it('should return permissions_list', async () => { render( @@ -76,7 +83,76 @@ describe("Create Content component from Create Form Component in Role Management }); it('should get checked if permission list item get clicked', () => { - + render( + + + + ) + const checkboxElement = screen.getByLabelText("مدیریت کارتابل رییس اداره مسافری استان") + + expect(checkboxElement).not.toBeChecked(); + + fireEvent.click(checkboxElement); + + expect(checkboxElement).toBeChecked(); + }); + }) + describe("Validation",()=>{ + it('should see error text when name_fa input is empty', async () => { + render( + + + + ) + const name_faInput = screen.getByLabelText("نام فارسی") + expect(screen.queryByText("وارد کردن نام فارسی الزامیست")).not.toBeInTheDocument() + fireEvent.blur(name_faInput); + + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام فارسی الزامیست")).toBeInTheDocument() + }) + fireEvent.change(name_faInput, {target : {value : "نام فارسی"}}) + + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام فارسی الزامیست")).not.toBeInTheDocument() + }) + }) + it('should see error text when name_en input is empty', async () => { + render( + + + + ) + const name_enInput = screen.getByLabelText("نام انگلیسی") + expect(screen.queryByText("وارد کردن نام انگلیسی الزامیست")).not.toBeInTheDocument() + fireEvent.blur(name_enInput); + + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام انگلیسی الزامیست")).toBeInTheDocument() + }) + fireEvent.change(name_enInput, {target : {value : "english name"}}) + + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام انگلیسی الزامیست")).not.toBeInTheDocument() + }) + }) + it('should see errors when click on submit button and field not completed', async () => { + render( + + + + ) + const submitButtonElement = screen.queryByText("ثبت") + fireEvent.click(submitButtonElement) + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام انگلیسی الزامیست")).toBeInTheDocument() + }) + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام فارسی الزامیست")).toBeInTheDocument() + }) + await waitFor(()=>{ + expect(screen.queryByText("حداقل باید یک دسترسی انتخاب شود")).toBeInTheDocument() + }) }); }) }) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/DeleteForm.jsx b/src/components/dashboard/role-management/Form/DeleteForm.jsx deleted file mode 100644 index 9c613b1..0000000 --- a/src/components/dashboard/role-management/Form/DeleteForm.jsx +++ /dev/null @@ -1,67 +0,0 @@ -import {useTranslations} from "next-intl"; -import {useState} from "react"; -import { - Button, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - IconButton, - Tooltip, - Typography -} from "@mui/material"; -import DeleteIcon from '@mui/icons-material/Delete'; -import useRequest from "@/lib/app/hooks/useRequest"; -import useNotification from "@/lib/app/hooks/useNotification"; -import {DELETE_ROLE_MANAGEMENT} from "@/core/data/apiRoutes"; - -const DeleteForm = ({rowId, fetchUrl, mutate}) => { - const t = useTranslations(); - const [openConfirmDialog, setOpenConfirmDialog] = useState(false); - const [isSubmitting, setIsSubmitting] = useState(false) - const requestServer = useRequest({auth: true}) - const {update_notification} = useNotification() - const handleSubmit = () => { - setIsSubmitting(true) - requestServer(`${DELETE_ROLE_MANAGEMENT}/${rowId}`, 'delete').then((response) => { - mutate(fetchUrl) - update_notification() - }).catch(() => { - }).finally(() => { - setIsSubmitting(false) - }); - } - - return ( - <> - - { - setOpenConfirmDialog(true) - }} - > - - - - - {t("DeleteDialog.delete")} - - {t("DeleteDialog.typography")} - - - - - - - - ); -}; -export default DeleteForm; \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/DeleteForm/DeleteContent.jsx b/src/components/dashboard/role-management/Form/DeleteForm/DeleteContent.jsx new file mode 100644 index 0000000..52674a5 --- /dev/null +++ b/src/components/dashboard/role-management/Form/DeleteForm/DeleteContent.jsx @@ -0,0 +1,42 @@ +import {Button, DialogActions, DialogContent, DialogTitle, Typography} from "@mui/material"; +import {DELETE_ROLE_MANAGEMENT} from "@/core/data/apiRoutes"; +import {useState} from "react"; +import useRequest from "@/lib/app/hooks/useRequest"; +import useNotification from "@/lib/app/hooks/useNotification"; +import {useTranslations} from "next-intl"; + +const DeleteContent = ({rowId, fetchUrl, mutate, setOpenConfirmDialog}) => { + const t = useTranslations(); + const [isSubmitting, setIsSubmitting] = useState(false) + const requestServer = useRequest({auth: true}) + const {update_notification} = useNotification() + const handleSubmit = () => { + setIsSubmitting(true) + requestServer(`${DELETE_ROLE_MANAGEMENT}/${rowId}`, 'delete').then((response) => { + mutate(fetchUrl) + update_notification() + }).catch(() => { + }).finally(() => { + setIsSubmitting(false) + }); + } + return( + <> + {t("DeleteDialog.delete")} + + {t("DeleteDialog.typography")} + + + + + + + ) +} +export default DeleteContent \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/DeleteForm/__test__/DeleteContent.test.js b/src/components/dashboard/role-management/Form/DeleteForm/__test__/DeleteContent.test.js new file mode 100644 index 0000000..580dcb9 --- /dev/null +++ b/src/components/dashboard/role-management/Form/DeleteForm/__test__/DeleteContent.test.js @@ -0,0 +1,53 @@ +import {act, render, screen} from "@testing-library/react"; +import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider"; +import DeleteContent from "@/components/dashboard/role-management/Form/DeleteForm/DeleteContent"; +import UpdateContent from "@/components/dashboard/role-management/Form/UpdateForm/UpdateContent"; + +describe("Create Content component from Create Form Component in Role Management Component",()=> { + describe("Rendering", () => { + it('should see DeleteDialog text in the top ', async () => { + render( + + + + ) + const textElement = screen.queryByText("حذف") + act(()=>{ + expect(textElement).toBeInTheDocument() + }) + }) + it('should see DeleteDialog text content ', async () => { + render( + + + + ) + const textElement = screen.queryByText("آیا از حدف این مورد اطمینان دارید ؟") + act(()=>{ + expect(textElement).toBeInTheDocument() + }) + }) + it('should see delete text in the delete button ', () => { + render( + + + + ) + const buttonElement = screen.queryByText("حذف کردن") + act(()=>{ + expect(buttonElement).toBeInTheDocument() + }) + }); + it('should see cancel text in the cancel button ', () => { + render( + + + + ) + const buttonElement = screen.queryByText("انصراف") + act(()=>{ + expect(buttonElement).toBeInTheDocument() + }) + }); + }) +}) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/DeleteForm/__test__/index.test.js b/src/components/dashboard/role-management/Form/DeleteForm/__test__/index.test.js new file mode 100644 index 0000000..6c0c48b --- /dev/null +++ b/src/components/dashboard/role-management/Form/DeleteForm/__test__/index.test.js @@ -0,0 +1,29 @@ +import {fireEvent, render, screen} from "@testing-library/react"; +import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider"; +import DeleteForm from "@/components/dashboard/role-management/Form/DeleteForm"; +import UpdateForm from "@/components/dashboard/role-management/Form/UpdateForm"; + +describe("Create Form Component from Role Management Component",()=> { + describe("Rendering", () => { + it('should see Dialog text', () => { + render( + + + + ) + const textElement = screen.queryByText("ویرایش") + expect(textElement).toBeInTheDocument() + }); + it('should see Dialog text when mouse is over', async () => { + render( + + + + ) + const textElement = screen.queryByText("حذف") + fireEvent.mouseOver(textElement); + const tooltipTextElement = screen.getByText("حذف"); + expect(tooltipTextElement).toBeInTheDocument(); + }); + }) +}) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/DeleteForm/index.jsx b/src/components/dashboard/role-management/Form/DeleteForm/index.jsx new file mode 100644 index 0000000..b2c14fa --- /dev/null +++ b/src/components/dashboard/role-management/Form/DeleteForm/index.jsx @@ -0,0 +1,39 @@ +import {useTranslations} from "next-intl"; +import {useState} from "react"; +import { + Button, + Dialog, + Tooltip, +} from "@mui/material"; +import DeleteIcon from '@mui/icons-material/Delete'; +import DeleteContent from "@/components/dashboard/role-management/Form/DeleteForm/DeleteContent"; + +const DeleteForm = ({rowId, fetchUrl, mutate}) => { + const t = useTranslations(); + const [openConfirmDialog, setOpenConfirmDialog] = useState(false); + + + return ( + <> + + + + + + + + ); +}; +export default DeleteForm; \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/UpdateForm/UpdateContext.jsx b/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx similarity index 87% rename from src/components/dashboard/role-management/Form/UpdateForm/UpdateContext.jsx rename to src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx index e2f2980..23fa4e4 100644 --- a/src/components/dashboard/role-management/Form/UpdateForm/UpdateContext.jsx +++ b/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx @@ -1,7 +1,7 @@ import { Button, Checkbox, DialogActions, - DialogContent, + DialogContent, DialogTitle, FormControl, FormControlLabel, FormHelperText, @@ -17,29 +17,27 @@ import usePermissions from "@/lib/app/hooks/usePermissions"; import useNotification from "@/lib/app/hooks/useNotification"; import useRequest from "@/lib/app/hooks/useRequest"; import {useTranslations} from "next-intl"; -import {useState} from "react"; -const UpdateContent = ({mutate, fetchUrl, setOpenConfirmDialog}) => { +const UpdateContent = ({mutate, row, fetchUrl, setOpenConfirmDialog}) => { const t = useTranslations(); const requestServer = useRequest({auth: true}) const {update_notification} = useNotification() const {permissions_list} = usePermissions() - const [openConfirmDialog, setOpenConfirmDialog] = useState(false); const validationSchema = Yup.object().shape({ - name: Yup.string().required(t("UpdateDialog.name_error")), + name_en: Yup.string().required(t("UpdateDialog.name_en_error")), name_fa: Yup.string().required(t("UpdateDialog.name_fa_error")), permissions: Yup.array().min(1, t("UpdateDialog.permission_min_error")).required(t("UpdateDialog.permission")), }); const formik = useFormik({ initialValues: { - name: row.getValue("name"), + name_en: row.getValue("name"), name_fa: row.getValue("name_fa"), permissions: row.original.permissions.map((obj) => obj.id), }, validationSchema, onSubmit: (values, {setSubmitting}) => { const formData = new FormData(); - formData.append("name", values.name); + formData.append("name", values.name_en); formData.append("name_fa", values.name_fa); for (let i = 0; i < values.permissions.length; i++) { formData.append(`permissions[${i}]`, values.permissions[i]); @@ -59,19 +57,20 @@ const UpdateContent = ({mutate, fetchUrl, setOpenConfirmDialog}) => { return( <> + {t("UpdateDialog.update")} { { if (e.target.checked) { diff --git a/src/components/dashboard/role-management/Form/UpdateForm/__test__/UpdateContent.test.js b/src/components/dashboard/role-management/Form/UpdateForm/__test__/UpdateContent.test.js new file mode 100644 index 0000000..d36fe05 --- /dev/null +++ b/src/components/dashboard/role-management/Form/UpdateForm/__test__/UpdateContent.test.js @@ -0,0 +1,201 @@ +import {act, fireEvent, render, screen, waitFor} from "@testing-library/react"; +import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider"; +import UpdateContent from "@/components/dashboard/role-management/Form/UpdateForm/UpdateContent"; +const row = { + id : 0, + getValue : name => { + if (name === "name") { + return "manage_passenger_office_navgan"; + } + else if (name === "name_fa") { + return "مدیریت کارتابل رییس اداره مسافری استان"; + } + }, + original : { + permissions : [ + { + id: 1, + name: "manage_passenger_office_navgan", + name_fa: "مدیریت کارتابل رییس اداره مسافری استان" + }, + { + id: 2, + name: "manage_passenger_office_navgan", + name_fa: "مدیریت کارتابل رییس اداره مسافری استان" + } + ] + } +} + +describe("Create Content component from Create Form Component in Role Management Component",()=>{ + describe("Rendering", ()=>{ + it('should see AddDialog text in the top ', async () => { + render( + + + + ) + const textElement = screen.queryByText("ویرایش") + act(()=>{ + expect(textElement).toBeInTheDocument() + }) + }); + it('should see name_en text', async () => { + render( + + + + ) + const textElement = screen.queryByLabelText("نام انگلیسی") + act(()=>{ + expect(textElement).toBeInTheDocument() + }) + }); + it('should see name_fa text', async () => { + render( + + + + ) + const textElement = screen.queryByLabelText("نام فارسی") + act(()=>{ + expect(textElement).toBeInTheDocument() + }) + }); + it('should see update text in the submit button ', () => { + render( + + + + ) + const buttonElement = screen.queryByText("ثبت") + act(()=>{ + expect(buttonElement).toBeInTheDocument() + }) + }); + it('should see cancel text in the cancel button ', () => { + render( + + + + ) + const buttonElement = screen.queryByText("بستن") + act(()=>{ + expect(buttonElement).toBeInTheDocument() + }) + }); + }) + + describe("Behavior", ()=>{ + it('should see what fill in the name_en input', async () => { + render( + + + + ) + const nameEnglishInput = screen.getByLabelText('نام انگلیسی'); + + fireEvent.change(nameEnglishInput, {target: {value: 'testuser'}}); + await act(()=>{ + // Simulate user input + expect(nameEnglishInput).toHaveValue('testuser'); + }) + }); + it('should see what fill in the name_fa input', async () => { + render( + + + + ) + const nameFarsiInput = screen.getByLabelText('نام فارسی'); + + fireEvent.change(nameFarsiInput, {target: {value: 'testuser'}}); + await act(()=>{ + // Simulate user input + expect(nameFarsiInput).toHaveValue('testuser'); + }) + }); + it('should return permissions_list', async () => { + render( + + + + ) + const checkboxElement = await screen.findAllByTestId("PermissionList-checkbox") + expect(checkboxElement).toHaveLength(2) + }); + it('should see the value of the name_en that pass to input value', () => { + render( + + + + ) + const name_enElement = screen.getByLabelText("نام انگلیسی") + expect(name_enElement).toHaveValue("manage_passenger_office_navgan") + }); + it('should see the value of the name_fa that pass to input value', () => { + render( + + + + ) + const name_enElement = screen.getByLabelText("نام فارسی") + expect(name_enElement).toHaveValue("مدیریت کارتابل رییس اداره مسافری استان") + }); + it('should get checked if the id exists in permission lists', () => { + render( + + + + ) + const checkboxElement = screen.getByLabelText("مدیریت کارتابل رییس اداره مسافری استان") + + expect(checkboxElement).toBeChecked(); + }); + }) + describe("Validation", ()=>{ + it('should see error text when name_fa input is empty', async () => { + render( + + + + ) + const name_faInput = screen.getByLabelText("نام فارسی") + expect(screen.queryByText("وارد کردن نام فارسی الزامیست")).not.toBeInTheDocument() + fireEvent.change(name_faInput, {target : {value : ''}}); + + fireEvent.blur(name_faInput) + + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام فارسی الزامیست")).toBeInTheDocument() + }) + fireEvent.change(name_faInput, {target : {value : "نام فارسی"}}) + + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام فارسی الزامیست")).not.toBeInTheDocument() + }) + }) + it('should see error text when name_en input is empty', async () => { + render( + + + + ) + const name_enInput = screen.getByLabelText("نام انگلیسی") + expect(screen.queryByText("وارد کردن نام انگلیسی الزامیست")).not.toBeInTheDocument() + + fireEvent.change(name_enInput, {target : {value : null}}); + fireEvent.blur(name_enInput) + + await waitFor(()=>{ + + expect(screen.queryByText("وارد کردن نام انگلیسی الزامیست")).toBeInTheDocument() + }) + fireEvent.change(name_enInput, {target : {value : "english name"}}) + + await waitFor(()=>{ + expect(screen.queryByText("وارد کردن نام انگلیسی الزامیست")).not.toBeInTheDocument() + }) + }) + }) +}) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/UpdateForm/__test__/index.test.js b/src/components/dashboard/role-management/Form/UpdateForm/__test__/index.test.js new file mode 100644 index 0000000..210ce6f --- /dev/null +++ b/src/components/dashboard/role-management/Form/UpdateForm/__test__/index.test.js @@ -0,0 +1,30 @@ +import {fireEvent, render, screen} from "@testing-library/react"; +import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider"; +import UpdateContent from "@/components/dashboard/role-management/Form/UpdateForm/UpdateContent"; +import UpdateForm from "@/components/dashboard/role-management/Form/UpdateForm"; + +describe("Create Form Component from Role Management Component",()=>{ + describe("Rendering",()=>{ + it('should see Dialog text', () => { + render( + + + + ) + const textElement = screen.queryByText("ویرایش") + expect(textElement).toBeInTheDocument() + }); + + it('should see Tooltip text when mouse over', () => { + render( + + + + ) + const buttonElement = screen.getByText("ویرایش"); + fireEvent.mouseOver(buttonElement); + const tooltipTextElement = screen.getByText("ویرایش"); + expect(tooltipTextElement).toBeInTheDocument(); + }); + }) +}) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/UpdateForm/index.jsx b/src/components/dashboard/role-management/Form/UpdateForm/index.jsx index 115e284..a6d05c6 100644 --- a/src/components/dashboard/role-management/Form/UpdateForm/index.jsx +++ b/src/components/dashboard/role-management/Form/UpdateForm/index.jsx @@ -2,9 +2,9 @@ import {Button, Dialog, DialogTitle, Stack, Tooltip} from "@mui/material"; import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; import {useTranslations} from "next-intl"; import {useState} from "react"; -import CreateContent from "./CreateContent"; +import UpdateContent from "@/components/dashboard/role-management/Form/UpdateForm/UpdateContent"; -const UpdateForm = ({mutate, fetchUrl}) => { +const UpdateForm = ({mutate, fetchUrl, row}) => { const t = useTranslations(); const [openConfirmDialog, setOpenConfirmDialog] = useState(false); @@ -26,8 +26,7 @@ const UpdateForm = ({mutate, fetchUrl}) => { - {t("UpdateDialog.update ")} - + ) diff --git a/src/components/dashboard/role-management/TableRowActions.jsx b/src/components/dashboard/role-management/TableRowActions.jsx index cd72356..500aeca 100644 --- a/src/components/dashboard/role-management/TableRowActions.jsx +++ b/src/components/dashboard/role-management/TableRowActions.jsx @@ -1,6 +1,6 @@ import {Box} from "@mui/material"; -import DeleteForm from "./Form/DeleteForm" import UpdateForm from "@/components/dashboard/role-management/Form/UpdateForm"; +import DeleteForm from "@/components/dashboard/role-management/Form/DeleteForm"; const TableRowActions = ({row, mutate, fetchUrl}) => { diff --git a/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js b/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js index d21081c..cf6254f 100644 --- a/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js +++ b/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js @@ -10,7 +10,7 @@ describe("Role Management Component from Role Management page",()=>{ )) - const textElement = screen.getByText("کد یکتا") + const textElement = screen.queryByText("کد یکتا") expect(textElement).toBeInTheDocument() }); }) diff --git a/src/core/components/DataTable.jsx b/src/core/components/DataTable.jsx index b3b0f26..350f37c 100644 --- a/src/core/components/DataTable.jsx +++ b/src/core/components/DataTable.jsx @@ -159,7 +159,6 @@ function DataTable(props) { )} state={{ - isLoading: isValidating, columnFilters, columnFilterFns, pagination, diff --git a/src/lib/app/contexts/language.jsx b/src/lib/app/contexts/language.jsx index e3f41f4..e9e24f7 100644 --- a/src/lib/app/contexts/language.jsx +++ b/src/lib/app/contexts/language.jsx @@ -18,7 +18,7 @@ export const LanguageProvider = ({children}) => { ]; const {user, userChangedLanguage, changeLanguageState} = useUser(); const [languageIsReady, setLanguageIsReady] = useState(false); - const [languageApp, setLanguageApp] = useState(); + const [languageApp, setLanguageApp] = useState(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE); const [directionApp, setDirectionApp] = useState( process.env.NEXT_PUBLIC_DEFAULT_DIRECTION ); @@ -26,9 +26,7 @@ export const LanguageProvider = ({children}) => { useEffect(() => { const lang = localStorage.getItem("_language"); - if (!lang && !languageApp) { - setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE); - } else if (lang) { + if (lang) { setLanguageApp(lang); } }, []); From 18d6e93bd4bb8657b7332e2637c20f7d3c9e7316 Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Tue, 10 Oct 2023 09:54:09 +0330 Subject: [PATCH 4/9] CFE-4 delete role index test --- .../__test__/RoleManagementComponent.test.js | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js diff --git a/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js b/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js deleted file mode 100644 index cf6254f..0000000 --- a/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js +++ /dev/null @@ -1,17 +0,0 @@ -import {render} from "@testing-library/react"; -import MockAppWithProviders from "../../../../../mocks/AppWithProvider"; -import RoleManagementComponent from "@/components/dashboard/role-management/RoleManagementComponent"; - -describe("Role Management Component from Role Management page",()=>{ - describe("Rendering",()=>{ - it('should show columns text', () => { - render(( - - - - )) - const textElement = screen.queryByText("کد یکتا") - expect(textElement).toBeInTheDocument() - }); - }) -}) \ No newline at end of file From 99b4128cd90b6f13b94a8cf82ad96efb034a9697 Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Tue, 10 Oct 2023 10:05:29 +0330 Subject: [PATCH 5/9] CFE-4 rm cached .env.test --- .env.test | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .env.test diff --git a/.env.test b/.env.test deleted file mode 100644 index 0be16f0..0000000 --- a/.env.test +++ /dev/null @@ -1,12 +0,0 @@ -NEXT_PUBLIC_API_NAME = "CRM Dashboard" -NEXT_PUBLIC_API_VERSION = "0.0.1" -NEXT_PUBLIC_DEFAULT_LANGUAGE = "fa" -NEXT_PUBLIC_DEFAULT_DIRECTION = "rtl" - -NEXT_PUBLIC_PRIMARY_MAIN = "#1b4332" -NEXT_PUBLIC_SECONDARY_MAIN = "#800e13" - -NEXT_PUBLIC_BASE_URL = "https://crm.witel.ir" -NEXT_PUBLIC_POWERED_BY_URL = "https://witel.ir" - -NODE_ENV = "development" \ No newline at end of file From 9c74c180899846c1552748d7515ceee49b9f4130 Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Tue, 10 Oct 2023 11:38:09 +0330 Subject: [PATCH 6/9] CFE-4 check and set the api --- public/locales/fa/app.json | 3 +- .../Form/CreateForm/CreateContent.jsx | 6 +-- .../Form/DeleteForm/__test__/index.test.js | 20 +++---- .../role-management/Form/DeleteForm/index.jsx | 14 ++--- .../Form/UpdateForm/UpdateContent.jsx | 2 +- .../Form/UpdateForm/__test__/index.test.js | 22 +++----- .../role-management/Form/UpdateForm/index.jsx | 19 +++---- .../RoleManagementComponent.jsx | 2 +- .../role-management/TableToolbar.jsx | 2 +- .../__test__/RoleManagementComponent.test.js | 53 +++++++++++++++++++ .../dashboard/role-management/index.jsx | 6 +-- .../__test__/LoginExpertComponent.test.js | 1 + src/core/components/DataTable.jsx | 4 +- src/core/data/apiRoutes.js | 2 +- 14 files changed, 94 insertions(+), 62 deletions(-) create mode 100644 src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index cea9212..38083ec 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -73,7 +73,8 @@ "Dashboard": { "dashboard_page": "داشبورد", "change_password": "تغییر رمز عبور", - "edit_profile": "ویرایش پروفایل" + "edit_profile": "ویرایش پروفایل", + "role_management_page": "مدیریت دسترسی" }, "MuiDatePicker": { "date_picker_birthday": "تاریخ" diff --git a/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx b/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx index 117e009..b646133 100644 --- a/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx +++ b/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx @@ -34,7 +34,7 @@ const CreateContent = ({mutate, fetchUrl, setOpenConfirmDialog}) => { permissions: [], }, validationSchema, onSubmit: (values, {setSubmitting}) => { const formData = new FormData(); - formData.append("name_en", values.name_en); + formData.append("name", values.name_en); formData.append("name_fa", values.name_fa); for (let i = 0; i < values.permissions.length; i++) { formData.append(`permissions[${i}]`, values.permissions[i]); @@ -42,7 +42,7 @@ const CreateContent = ({mutate, fetchUrl, setOpenConfirmDialog}) => { requestServer(ADD_ROLE_MANAGEMENT, 'post', { data: formData, - }).then((response) => { + }).then(() => { setOpenConfirmDialog(false) mutate(fetchUrl) update_notification() @@ -57,7 +57,7 @@ const CreateContent = ({mutate, fetchUrl, setOpenConfirmDialog}) => { <> {t("AddDialog.add")} - + { describe("Rendering", () => { - it('should see Dialog text', () => { - render( - - - - ) - const textElement = screen.queryByText("ویرایش") - expect(textElement).toBeInTheDocument() - }); it('should see Dialog text when mouse is over', async () => { render( ) - const textElement = screen.queryByText("حذف") - fireEvent.mouseOver(textElement); - const tooltipTextElement = screen.getByText("حذف"); - expect(tooltipTextElement).toBeInTheDocument(); + const textElement = screen.getByTestId("dialog_tooltip") + fireEvent.mouseOver(textElement) + await waitFor(()=>{ + expect(screen.getByText("حذف")).toBeInTheDocument(); + }) }); }) }) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/DeleteForm/index.jsx b/src/components/dashboard/role-management/Form/DeleteForm/index.jsx index b2c14fa..b22a907 100644 --- a/src/components/dashboard/role-management/Form/DeleteForm/index.jsx +++ b/src/components/dashboard/role-management/Form/DeleteForm/index.jsx @@ -1,8 +1,7 @@ import {useTranslations} from "next-intl"; import {useState} from "react"; import { - Button, - Dialog, + Dialog, IconButton, Tooltip, } from "@mui/material"; import DeleteIcon from '@mui/icons-material/Delete'; @@ -16,18 +15,15 @@ const DeleteForm = ({rowId, fetchUrl, mutate}) => { return ( <> - + + diff --git a/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx b/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx index 23fa4e4..b149c85 100644 --- a/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx +++ b/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx @@ -59,7 +59,7 @@ const UpdateContent = ({mutate, row, fetchUrl, setOpenConfirmDialog}) => { <> {t("UpdateDialog.update")} - + { describe("Rendering",()=>{ - it('should see Dialog text', () => { - render( - - - - ) - const textElement = screen.queryByText("ویرایش") - expect(textElement).toBeInTheDocument() - }); - - it('should see Tooltip text when mouse over', () => { + it('should see Tooltip text when mouse over', async () => { render( ) - const buttonElement = screen.getByText("ویرایش"); + const buttonElement = screen.getByTestId("dialog_tooltip"); fireEvent.mouseOver(buttonElement); - const tooltipTextElement = screen.getByText("ویرایش"); - expect(tooltipTextElement).toBeInTheDocument(); + await waitFor(()=>{ + expect(screen.queryByText("ویرایش")).toBeVisible(); + }) }); }) }) \ No newline at end of file diff --git a/src/components/dashboard/role-management/Form/UpdateForm/index.jsx b/src/components/dashboard/role-management/Form/UpdateForm/index.jsx index a6d05c6..018fe32 100644 --- a/src/components/dashboard/role-management/Form/UpdateForm/index.jsx +++ b/src/components/dashboard/role-management/Form/UpdateForm/index.jsx @@ -1,8 +1,8 @@ -import {Button, Dialog, DialogTitle, Stack, Tooltip} from "@mui/material"; -import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; +import {Dialog, IconButton, Stack, Tooltip} from "@mui/material"; import {useTranslations} from "next-intl"; import {useState} from "react"; import UpdateContent from "@/components/dashboard/role-management/Form/UpdateForm/UpdateContent"; +import EditIcon from "@mui/icons-material/Edit"; const UpdateForm = ({mutate, fetchUrl, row}) => { const t = useTranslations(); @@ -10,19 +10,16 @@ const UpdateForm = ({mutate, fetchUrl, row}) => { return ( - - + + diff --git a/src/components/dashboard/role-management/RoleManagementComponent.jsx b/src/components/dashboard/role-management/RoleManagementComponent.jsx index 1aea1b7..0121c00 100644 --- a/src/components/dashboard/role-management/RoleManagementComponent.jsx +++ b/src/components/dashboard/role-management/RoleManagementComponent.jsx @@ -1,12 +1,12 @@ import DataTable from "@/core/components/DataTable"; import {GET_ROLE_MANAGEMENT} from "@/core/data/apiRoutes"; -import TableToolbar from "@/components/dashboard/role-management/TableToolbar"; import TableRowActions from "@/components/dashboard/role-management/TableRowActions"; import {Box, Typography} from "@mui/material"; import {useTranslations} from "next-intl"; import {useMemo} from "react"; import moment from "jalali-moment"; import MuiDatePicker from "@/core/components/MuiDatePicker"; +import TableToolbar from "@/components/dashboard/role-management/TableToolbar"; const RoleManagementComponent = () => { const t = useTranslations(); diff --git a/src/components/dashboard/role-management/TableToolbar.jsx b/src/components/dashboard/role-management/TableToolbar.jsx index c4cb13b..14dfef1 100644 --- a/src/components/dashboard/role-management/TableToolbar.jsx +++ b/src/components/dashboard/role-management/TableToolbar.jsx @@ -1,5 +1,5 @@ import {useTranslations} from "next-intl"; -import CreateForm from "./Form/CreateForm/index"; +import CreateForm from "@/components/dashboard/role-management/Form/CreateForm"; function TableToolbar({mutate, fetchUrl}) { const t = useTranslations(); diff --git a/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js b/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js new file mode 100644 index 0000000..2a50a99 --- /dev/null +++ b/src/components/dashboard/role-management/__test__/RoleManagementComponent.test.js @@ -0,0 +1,53 @@ +import {render, screen} from "@testing-library/react"; +import MockAppWithProviders from "../../../../../mocks/AppWithProvider"; +import RoleManagementComponent from "@/components/dashboard/role-management/RoleManagementComponent"; + +describe("Role Management", ()=>{ + describe("Rendering", ()=>{ + it('should see id title of data table', () => { + render( + + + + ) + const idEelement = screen.queryByText("کد یکتا") + expect(idEelement).toBeInTheDocument() + }); + it('should see name title of data table', () => { + render( + + + + ) + const nameEelement = screen.queryByText("نام انگلیسی") + expect(nameEelement).toBeInTheDocument() + }); + it('should see name_fa title of data table', () => { + render( + + + + ) + const name_faEelement = screen.queryByText("نام فارسی") + expect(name_faEelement).toBeInTheDocument() + }); + it('should see created at title of data table', () => { + render( + + + + ) + const createdEelement = screen.queryByText("تاریخ درخواست") + expect(createdEelement).toBeInTheDocument() + }); + it('should see updated at title of data table', () => { + render( + + + + ) + const updateEelement = screen.queryByText("تاریخ بروزرسانی") + expect(updateEelement).toBeInTheDocument() + }); + }) +}) \ No newline at end of file diff --git a/src/components/dashboard/role-management/index.jsx b/src/components/dashboard/role-management/index.jsx index 09f15bf..5251c8b 100644 --- a/src/components/dashboard/role-management/index.jsx +++ b/src/components/dashboard/role-management/index.jsx @@ -1,12 +1,12 @@ -import DashboardLayouts from "@/layouts/dashboardLayouts"; import RoleManagementComponent from "@/components/dashboard/role-management/RoleManagementComponent"; +import DashboardLayout from "@/layouts/DashboardLayout"; function DashboardRoleManagementComponent() { return ( - + - + ); } diff --git a/src/components/login-expert/__test__/LoginExpertComponent.test.js b/src/components/login-expert/__test__/LoginExpertComponent.test.js index d76e49d..695dbcb 100644 --- a/src/components/login-expert/__test__/LoginExpertComponent.test.js +++ b/src/components/login-expert/__test__/LoginExpertComponent.test.js @@ -124,6 +124,7 @@ describe('Login expert component from login page', () => { }) describe("validation", ()=>{ it("Disabled submit button until fields completed", async ()=> { + render( diff --git a/src/core/components/DataTable.jsx b/src/core/components/DataTable.jsx index 350f37c..aeac2c2 100644 --- a/src/core/components/DataTable.jsx +++ b/src/core/components/DataTable.jsx @@ -134,8 +134,8 @@ function DataTable(props) { renderTopToolbarCustomActions={({table}) => ( <> {props.enableCustomToolbar /* send condition */ - ? props.CustomToolbar /* send component */ - : ""} + ? /* send component */ + : ""} )} renderBottomToolbarCustomActions={({table}) => ( diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js index 0155d4c..4d0231f 100644 --- a/src/core/data/apiRoutes.js +++ b/src/core/data/apiRoutes.js @@ -23,5 +23,5 @@ export const DELETE_ROLE_MANAGEMENT = BASE_URL + "/api/roles" export const GET_PERMISSIONS_LIST = - BASE_URL + "/api/roles/list" + BASE_URL + "/api/permissions/list" //role management \ No newline at end of file From db58573c0e61f86e7095efeba1299c936040662c Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Tue, 10 Oct 2023 11:51:34 +0330 Subject: [PATCH 7/9] CFE-4 style create and update dialog --- .../role-management/Form/CreateForm/CreateContent.jsx | 3 ++- .../role-management/Form/UpdateForm/UpdateContent.jsx | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx b/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx index b646133..12523c2 100644 --- a/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx +++ b/src/components/dashboard/role-management/Form/CreateForm/CreateContent.jsx @@ -57,7 +57,7 @@ const CreateContent = ({mutate, fetchUrl, setOpenConfirmDialog}) => { <> {t("AddDialog.add")} - + { error={formik.touched.permissions && Boolean(formik.errors.permissions)} onBlur={formik.handleBlur("permissions")} sx={{mt: 2}} + fullWidth > {formik.touched.permissions && formik.errors.permissions} diff --git a/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx b/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx index b149c85..a17c48d 100644 --- a/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx +++ b/src/components/dashboard/role-management/Form/UpdateForm/UpdateContent.jsx @@ -91,6 +91,7 @@ const UpdateContent = ({mutate, row, fetchUrl, setOpenConfirmDialog}) => { error={formik.touched.permissions && Boolean(formik.errors.permissions)} onBlur={formik.handleBlur("permissions")} sx={{mt: 2}} + fullWidth > {formik.touched.permissions && formik.errors.permissions} From c95e52f33ce427cf6d64a496cb2ec47d44b7ec72 Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Tue, 10 Oct 2023 13:09:48 +0330 Subject: [PATCH 8/9] CFE-4 role management icon --- src/core/data/sidebarMenu.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx index dfc7df7..57d97ed 100644 --- a/src/core/data/sidebarMenu.jsx +++ b/src/core/data/sidebarMenu.jsx @@ -1,4 +1,5 @@ import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard"; +import AccessibilityIcon from '@mui/icons-material/Accessibility'; const sidebarMenu = [ [ @@ -15,7 +16,7 @@ const sidebarMenu = [ name : "role_management", type: "page", route: "/dashboard/role-management", - icon: , + icon: , selected: false, permission: "all", }, From 3c9c9551058f21fa14a57eafd4a58ccdec242295 Mon Sep 17 00:00:00 2001 From: Amin Ghasempoor Date: Tue, 10 Oct 2023 13:12:15 +0330 Subject: [PATCH 9/9] CFE-4 permission manage role --- src/core/data/sidebarMenu.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx index 57d97ed..2aeea36 100644 --- a/src/core/data/sidebarMenu.jsx +++ b/src/core/data/sidebarMenu.jsx @@ -18,7 +18,7 @@ const sidebarMenu = [ route: "/dashboard/role-management", icon: , selected: false, - permission: "all", + permission: "manage_roles", }, ], ];