From 357da9baf27c0662b98d4de2d3d0577ce68cac0a Mon Sep 17 00:00:00 2001 From: Mohamed Marrouchi Date: Sun, 29 Sep 2024 21:48:40 +0100 Subject: [PATCH 1/2] fix(frontend): align data grid toggle action --- api/src/user/schemas/user.schema.ts | 1 - .../src/app-components/tables/DataGrid.tsx | 49 ++++++++------ frontend/src/components/contents/index.tsx | 64 +++++++++++++------ .../src/components/context-vars/index.tsx | 3 + frontend/src/components/languages/index.tsx | 39 ++++++----- frontend/src/components/users/index.tsx | 50 +++++++-------- 6 files changed, 124 insertions(+), 82 deletions(-) diff --git a/api/src/user/schemas/user.schema.ts b/api/src/user/schemas/user.schema.ts index 83b8be5..a6c6970 100644 --- a/api/src/user/schemas/user.schema.ts +++ b/api/src/user/schemas/user.schema.ts @@ -42,7 +42,6 @@ export class UserStub extends BaseSchema { @Prop({ type: String, - unique: true, required: true, }) password: string; diff --git a/frontend/src/app-components/tables/DataGrid.tsx b/frontend/src/app-components/tables/DataGrid.tsx index 4248a42..e49d1e7 100644 --- a/frontend/src/app-components/tables/DataGrid.tsx +++ b/frontend/src/app-components/tables/DataGrid.tsx @@ -6,11 +6,12 @@ * 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 { styled } from "@mui/material"; +import { useTheme } from "@mui/material"; import { DataGridProps, gridClasses, GridColDef, + GridValidRowModel, DataGrid as MuiDataGrid, } from "@mui/x-data-grid"; @@ -18,22 +19,34 @@ import { renderHeader } from "./columns/renderHeader"; import { styledPaginationSlots } from "./DataGridStyledPagination"; import { NoDataOverlay } from "./NoDataOverlay"; -const StyledDataGrid = styled(MuiDataGrid)(({ theme }) => ({ - "& .MuiDataGrid-overlayWrapper": { - height: "fit-content", - }, +export const StyledDataGrid = ( + props: DataGridProps, +) => { + const theme = useTheme(); + const { sx, ...otherProps } = props; - [`& .${gridClasses.row}`]: { - "&:hover": { - backgroundColor: theme.palette.background.default, - "@media (hover: none)": { - backgroundColor: theme.palette.background.default, - }, - }, - }, -})); + return ( + + ); +}; -export const DataGrid = ({ +export const DataGrid = ({ columns, rows = [], autoHeight = true, @@ -46,8 +59,8 @@ export const DataGrid = ({ showColumnVerticalBorder = false, sx = { border: "none" }, ...rest -}: DataGridProps) => { - const styledColumns: GridColDef[] = columns.map((col) => ({ +}: DataGridProps) => { + const styledColumns: GridColDef[] = columns.map((col) => ({ disableColumnMenu: true, renderHeader, headerAlign: "left", @@ -56,7 +69,7 @@ export const DataGrid = ({ })); return ( - autoHeight={autoHeight} disableRowSelectionOnClick={disableRowSelectionOnClick} slots={slots} diff --git a/frontend/src/components/contents/index.tsx b/frontend/src/components/contents/index.tsx index 8f49ea0..0634b5a 100644 --- a/frontend/src/components/contents/index.tsx +++ b/frontend/src/components/contents/index.tsx @@ -9,7 +9,7 @@ import { faAlignLeft } from "@fortawesome/free-solid-svg-icons"; import AddIcon from "@mui/icons-material/Add"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; -import { Button, Chip, Grid, Paper, Typography } from "@mui/material"; +import { Button, Chip, Grid, Paper, Switch, Typography } from "@mui/material"; import Link from "next/link"; import { useRouter } from "next/router"; import { useTranslation } from "react-i18next"; @@ -24,13 +24,14 @@ import { renderHeader } from "@/app-components/tables/columns/renderHeader"; import { DataGrid } from "@/app-components/tables/DataGrid"; import { useDelete } from "@/hooks/crud/useDelete"; import { useFind } from "@/hooks/crud/useFind"; -import { useGet } from "@/hooks/crud/useGet"; +import { useGet, useGetFromCache } from "@/hooks/crud/useGet"; +import { useUpdate } from "@/hooks/crud/useUpdate"; import { getDisplayDialogs, useDialog } from "@/hooks/useDialog"; import { useHasPermission } from "@/hooks/useHasPermission"; import { useSearch } from "@/hooks/useSearch"; import { useToast } from "@/hooks/useToast"; import { PageHeader } from "@/layout/content/PageHeader"; -import { EntityType } from "@/services/types"; +import { EntityType, Format } from "@/services/types"; import { IContentType } from "@/types/content-type.types"; import { IContent } from "@/types/content.types"; import { PermissionAction } from "@/types/permission.types"; @@ -62,17 +63,26 @@ export const Contents = () => { entity: EntityType.CONTENT_TYPE, }); const { dataGridProps } = useFind( - { entity: EntityType.CONTENT }, + { entity: EntityType.CONTENT, format: Format.FULL }, { params: searchPayload, }, ); + const { mutateAsync: updateContent } = useUpdate(EntityType.CONTENT, { + onError: (error) => { + toast.error(error.message || t("message.internal_server_error")); + }, + onSuccess() { + toast.success(t("message.success_save")); + }, + }); const { mutateAsync: deleteContent } = useDelete(EntityType.CONTENT, { onSuccess: () => { deleteDialogCtl.closeDialog(); toast.success(t("message.item_delete_success")); }, }); + const getEntityFromCache = useGetFromCache(EntityType.CONTENT_TYPE); const actionColumns = useActionColumns( EntityType.CONTENT, [ @@ -108,7 +118,7 @@ export const Contents = () => { } + chip={} title={t("title.content")} > @@ -143,7 +153,7 @@ export const Contents = () => { - {...dataGridProps} disableColumnFilter showCellVerticalBorder={false} @@ -155,25 +165,39 @@ export const Contents = () => { field: "entity", headerName: t("label.entity"), flex: 1, - valueGetter: (row) => row["name"], + valueGetter: (row: IContent) => { + const contentType = getEntityFromCache(row.id); + + return contentType?.name; + }, }, { + maxWidth: 120, field: "status", headerName: t("label.status"), - resizable: false, + disableColumnMenu: true, + renderHeader, + headerAlign: "left", renderCell: (params) => ( - - - - - + { + updateContent({ + id: params.row.id, + params: { + status: !params.row.status, + }, + }); + }} + /> ), }, { diff --git a/frontend/src/components/context-vars/index.tsx b/frontend/src/components/context-vars/index.tsx index 5b6a2f1..8037c46 100644 --- a/frontend/src/components/context-vars/index.tsx +++ b/frontend/src/components/context-vars/index.tsx @@ -107,6 +107,9 @@ export const ContextVars = () => { checked={params.value} color="primary" inputProps={{ "aria-label": "primary checkbox" }} + disabled={ + !hasPermission(EntityType.CONTEXT_VAR, PermissionAction.UPDATE) + } onChange={() => { updateContextVar({ id: params.row.id, diff --git a/frontend/src/components/languages/index.tsx b/frontend/src/components/languages/index.tsx index b7355e2..bf90aa7 100644 --- a/frontend/src/components/languages/index.tsx +++ b/frontend/src/components/languages/index.tsx @@ -8,7 +8,7 @@ import { Flag } from "@mui/icons-material"; import AddIcon from "@mui/icons-material/Add"; -import { Button, Grid, Paper } from "@mui/material"; +import { Button, Grid, Paper, Switch } from "@mui/material"; import { GridColDef } from "@mui/x-data-grid"; import { useTranslation } from "react-i18next"; import { useQueryClient } from "react-query"; @@ -92,13 +92,6 @@ export const Languages = () => { const actionColumns = useActionColumns( EntityType.LANGUAGE, [ - { - label: ActionColumnLabel.Toggle, - action: (row) => toggleDefault(row), - requires: [PermissionAction.UPDATE], - getState: (row) => row.isDefault, - helperText: t("button.mark_as_default"), - }, { label: ActionColumnLabel.Edit, action: (row) => editDialogCtl.openDialog(row), @@ -131,15 +124,6 @@ export const Languages = () => { renderHeader, headerAlign: "left", }, - { - flex: 1, - field: "isDefault", - headerName: t("label.is_default"), - disableColumnMenu: true, - renderHeader, - headerAlign: "left", - valueGetter: (value) => (value ? t("label.yes") : t("label.no")), - }, { flex: 1, field: "isRTL", @@ -149,6 +133,27 @@ export const Languages = () => { headerAlign: "left", valueGetter: (value) => (value ? t("label.yes") : t("label.no")), }, + { + maxWidth: 120, + field: "isDefault", + headerName: t("label.is_default"), + disableColumnMenu: true, + renderHeader, + headerAlign: "left", + renderCell: (params) => ( + { + toggleDefault(params.row); + }} + /> + ), + }, { minWidth: 140, field: "createdAt", diff --git a/frontend/src/components/users/index.tsx b/frontend/src/components/users/index.tsx index 47a51a3..fc2eeea 100644 --- a/frontend/src/components/users/index.tsx +++ b/frontend/src/components/users/index.tsx @@ -8,7 +8,7 @@ import { faUsers } from "@fortawesome/free-solid-svg-icons"; import PersonAddAlt1Icon from "@mui/icons-material/PersonAddAlt1"; -import { Button, Grid, Paper } from "@mui/material"; +import { Button, Grid, Paper, Switch } from "@mui/material"; import { GridColDef } from "@mui/x-data-grid"; import { useTranslation } from "react-i18next"; @@ -23,6 +23,7 @@ import { buildRenderPicture } from "@/app-components/tables/columns/renderPictur import { DataGrid } from "@/app-components/tables/DataGrid"; import { useFind } from "@/hooks/crud/useFind"; import { useUpdate } from "@/hooks/crud/useUpdate"; +import { useAuth } from "@/hooks/useAuth"; import { useConfig } from "@/hooks/useConfig"; import { getDisplayDialogs, useDialog } from "@/hooks/useDialog"; import { useHasPermission } from "@/hooks/useHasPermission"; @@ -42,6 +43,7 @@ export const Users = () => { const { ssoEnabled } = useConfig(); const { t } = useTranslation(); const { toast } = useToast(); + const { user } = useAuth(); const { mutateAsync: updateUser } = useUpdate(EntityType.USER, { onError: (error) => { toast.error(error.message || t("message.internal_server_error")); @@ -136,33 +138,29 @@ export const Users = () => { maxWidth: 120, field: "state", headerName: t("label.status"), - resizable: false, disableColumnMenu: true, - renderCell: (params) => ( - - - - ), - headerAlign: "center", renderHeader, + headerAlign: "left", + renderCell: (params) => ( + { + updateUser({ + id: params.row.id, + params: { + state: !params.row.state, + }, + }); + }} + /> + ), }, { minWidth: 140, From 69818840f63f178a1bd03eb214e9e1f7ab0eb0b6 Mon Sep 17 00:00:00 2001 From: Mohamed Marrouchi Date: Mon, 30 Sep 2024 11:21:37 +0100 Subject: [PATCH 2/2] Update frontend/src/components/languages/index.tsx Co-authored-by: Yassine <95612053+yassinedorbozgithub@users.noreply.github.com> --- frontend/src/components/languages/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/languages/index.tsx b/frontend/src/components/languages/index.tsx index bf90aa7..78b3d84 100644 --- a/frontend/src/components/languages/index.tsx +++ b/frontend/src/components/languages/index.tsx @@ -146,6 +146,7 @@ export const Languages = () => { color="primary" inputProps={{ "aria-label": "primary checkbox" }} disabled={ + params.value || !hasPermission(EntityType.LANGUAGE, PermissionAction.UPDATE) } onChange={() => {