/* * Copyright © 2024 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ import AddIcon from "@mui/icons-material/Add"; import DeleteOutlinedIcon from "@mui/icons-material/DeleteOutlined"; import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; import { Accordion, AccordionDetails, AccordionSummary, Dialog, Grid, MenuItem, Paper, Typography, DialogContent, DialogActions, Button, Divider, } from "@mui/material"; import { useState, FC, useEffect } from "react"; import { IconButton } from "@/app-components/buttons/IconButton"; import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; import { Input } from "@/app-components/inputs/Input"; import { useCreate } from "@/hooks/crud/useCreate"; import { useDelete } from "@/hooks/crud/useDelete"; import { useFind } from "@/hooks/crud/useFind"; import { useGetFromCache } from "@/hooks/crud/useGet"; import { DialogControlProps } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; import { useTranslate } from "@/hooks/useTranslate"; import { EntityType, Format } from "@/services/types"; import { IPermission, IPermissionAttributes } from "@/types/permission.types"; import { IRole } from "@/types/role.types"; export type PermissionsDialogProps = DialogControlProps<{ role: IRole; }>; const DEFAULT_PAYLOAD: IPermissionAttributes = { action: "", model: "", relation: "", role: "", }; const AccordionModelHead = () => ( Action Relation ); export const PermissionsDialog: FC = ({ open, data, closeDialog: closeFunction, }) => { const { t } = useTranslate(); const { toast } = useToast(); const { data: models, refetch: modelRefetch } = useFind( { entity: EntityType.MODEL, format: Format.FULL }, { hasCount: false, }, ); const getPermisionFromCache = useGetFromCache(EntityType.PERMISSION); const { mutateAsync: createPermission } = useCreate(EntityType.PERMISSION, { onError: (error: Error & { statusCode?: number }) => { if (error.statusCode === 409) { toast.error(t("message.permission_already_exists")); } else { toast.error(t("message.internal_server_error")); } }, onSuccess: () => { modelRefetch(); toast.success(t("message.success_save")); }, }); const { mutateAsync: deletePermission } = useDelete(EntityType.PERMISSION, { onError: () => { toast.error(t("message.internal_server_error")); }, onSuccess: () => { modelRefetch(); toast.success(t("message.item_delete_success")); }, }); const [expanded, setExpanded] = useState(false); const [payload, setPayload] = useState(DEFAULT_PAYLOAD); const reset = () => setPayload(DEFAULT_PAYLOAD); const handleChange = (panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => { setExpanded(isExpanded ? panel : false); }; useEffect(() => { if (expanded === false && models?.[0]?.id) setExpanded(models[0].id); }, [models]); return ( {t("title.manage_permissions")} {data?.role.name} {models?.map((model) => { return ( } sx={{ backgroundColor: "background.default", borderRadius: 1, fontFamily: "inherit", }} > {model.name} {model.permissions ?.map((p) => getPermisionFromCache(p)) ?.filter( (permission) => permission && permission.role === data?.role.id, ) .map((p) => p as IPermission) .map(({ id, action, relation }, index) => { return ( <> {index > 0 && } { deletePermission(id); }} size="small" > {action} {relation} ); })} { if (data?.role.id) createPermission({ ...payload, model: model.id, role: data.role.id, }); reset(); }} > { if (e.target.value) setPayload((currentPayload) => ({ ...currentPayload, action: e.target.value, })); }} > {t("label.create")} {t("label.read")} {t("label.update")} {t("label.delete")} { if (e.target.value) setPayload((currentPayload) => ({ ...currentPayload, relation: e.target.value, })); }} > {t("label.role")} ); })} ); };