From 695395a3b827e816a11000f092368174af358797 Mon Sep 17 00:00:00 2001 From: Maciej Szewczyk <34482854+mmaciekk@users.noreply.github.com> Date: Fri, 30 Aug 2024 14:22:48 +0200 Subject: [PATCH] add permissions for PDU module frontend (#4169) * add permissions for PDU module frontend * display permission denied --------- Co-authored-by: Maciej Szewczyk --- .../PeriodicDataUpdates.tsx | 20 ++++++-- .../PeriodicDataUpdatesTemplatesList.tsx | 24 +++++++--- .../PeriodicDataUpdatesUploadDialog.tsx | 19 ++++---- frontend/src/config/permissions.ts | 6 +++ .../pages/population/HouseholdMembersPage.tsx | 46 +++++++++++++------ 5 files changed, 81 insertions(+), 34 deletions(-) diff --git a/frontend/src/components/periodicDataUpdates/PeriodicDataUpdates.tsx b/frontend/src/components/periodicDataUpdates/PeriodicDataUpdates.tsx index c66ff57650..37c3d5a41d 100644 --- a/frontend/src/components/periodicDataUpdates/PeriodicDataUpdates.tsx +++ b/frontend/src/components/periodicDataUpdates/PeriodicDataUpdates.tsx @@ -1,5 +1,5 @@ import { BaseSection } from '@components/core/BaseSection'; -import { Box, Tab, Tabs, Button, Fade } from '@mui/material'; +import { Box, Tab, Tabs, Fade } from '@mui/material'; import { useState } from 'react'; import { Link } from 'react-router-dom'; import AddIcon from '@mui/icons-material/Add'; @@ -8,11 +8,20 @@ import { PeriodicDataUpdatesUpdatesList } from './PeriodicDataUpdatesUpdatesList import { useBaseUrl } from '@hooks/useBaseUrl'; import { PeriodDataUpdatesUploadDialog } from './PeriodicDataUpdatesUploadDialog'; import { useProgramContext } from 'src/programContext'; +import { usePermissions } from '@hooks/usePermissions'; +import { hasPermissions, PERMISSIONS } from 'src/config/permissions'; +import { ButtonTooltip } from '@components/core/ButtonTooltip'; export const PeriodicDataUpdates = (): React.ReactElement => { const [value, setValue] = useState(0); const { baseUrl } = useBaseUrl(); const { isSocialDctType } = useProgramContext(); + const permissions = usePermissions(); + + const canCreatePDUTemplate = hasPermissions( + PERMISSIONS.PDU_TEMPLATE_CREATE, + permissions, + ); const handleChange = ( _event: React.ChangeEvent, @@ -35,24 +44,25 @@ export const PeriodicDataUpdates = (): React.ReactElement => { onChange={handleChange} aria-label="periodic data updates tabs" > - - + + } buttons={ - + diff --git a/frontend/src/components/periodicDataUpdates/PeriodicDataUpdatesTemplatesList.tsx b/frontend/src/components/periodicDataUpdates/PeriodicDataUpdatesTemplatesList.tsx index 9266fbbd83..545a929c34 100644 --- a/frontend/src/components/periodicDataUpdates/PeriodicDataUpdatesTemplatesList.tsx +++ b/frontend/src/components/periodicDataUpdates/PeriodicDataUpdatesTemplatesList.tsx @@ -7,7 +7,7 @@ import { useBaseUrl } from '@hooks/useBaseUrl'; import GetAppIcon from '@mui/icons-material/GetApp'; import UploadIcon from '@mui/icons-material/Upload'; import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Button, IconButton, TableCell, Tooltip } from '@mui/material'; +import { IconButton, TableCell, Tooltip } from '@mui/material'; import { useQuery } from '@tanstack/react-query'; import { ReactElement, useEffect, useState } from 'react'; import { PeriodicDataUpdatesTemplateDetailsDialog } from './PeriodicDataUpdatesTemplateDetailsDialog'; @@ -19,6 +19,9 @@ import { StatusBox } from '@core/StatusBox'; import { periodicDataUpdateTemplateStatusToColor } from '@utils/utils'; import { useSnackbar } from '@hooks/useSnackBar'; import { useTranslation } from 'react-i18next'; +import { ButtonTooltip } from '@components/core/ButtonTooltip'; +import { usePermissions } from '@hooks/usePermissions'; +import { hasPermissions, PERMISSIONS } from 'src/config/permissions'; export interface Template { id: number; @@ -87,6 +90,7 @@ export const PeriodicDataUpdatesTemplatesList = (): ReactElement => { const { t } = useTranslation(); const { businessArea: businessAreaSlug, programId } = useBaseUrl(); const [isDialogOpen, setIsDialogOpen] = useState(false); + const permissions = usePermissions(); const [selectedTemplateId, setSelectedTemplateId] = useState( null, ); @@ -161,6 +165,11 @@ export const PeriodicDataUpdatesTemplatesList = (): ReactElement => { (template) => template.id === selectedTemplateId, ); + const canExportOrDownloadTemplate = hasPermissions( + PERMISSIONS.PDU_TEMPLATE_DOWNLOAD, + permissions, + ); + const renderTemplateRow = (row: Template): ReactElement => ( {row.id} @@ -194,28 +203,31 @@ export const PeriodicDataUpdatesTemplatesList = (): ReactElement => { } > - + ) : row.can_export ? ( - + ) : null} diff --git a/frontend/src/components/periodicDataUpdates/PeriodicDataUpdatesUploadDialog.tsx b/frontend/src/components/periodicDataUpdates/PeriodicDataUpdatesUploadDialog.tsx index 5faf1769a5..374c00b4b7 100644 --- a/frontend/src/components/periodicDataUpdates/PeriodicDataUpdatesUploadDialog.tsx +++ b/frontend/src/components/periodicDataUpdates/PeriodicDataUpdatesUploadDialog.tsx @@ -5,8 +5,6 @@ import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import { DialogTitleWrapper } from '@containers/dialogs/DialogTitleWrapper'; -//TODO MS: display errors -// import { ImportErrors } from '@containers/tables/payments/VerificationRecordsTable/errors/ImportErrors'; import { useSnackbar } from '@hooks/useSnackBar'; import { DropzoneField } from '@core/DropzoneField'; @@ -14,6 +12,9 @@ import { LoadingButton } from '@core/LoadingButton'; import { useProgramContext } from 'src/programContext'; import { useUploadPeriodicDataUpdateTemplate } from './PeriodicDataUpdatesTemplatesListActions'; import { useBaseUrl } from '@hooks/useBaseUrl'; +import { usePermissions } from '@hooks/usePermissions'; +import { hasPermissions, PERMISSIONS } from 'src/config/permissions'; +import { ButtonTooltip } from '@components/core/ButtonTooltip'; const Error = styled.div` color: ${({ theme }) => theme.palette.error.dark}; @@ -31,12 +32,14 @@ const DisabledUploadIcon = styled(Publish)` export const PeriodDataUpdatesUploadDialog = (): React.ReactElement => { const { showMessage } = useSnackbar(); const { businessArea, programId } = useBaseUrl(); + const permissions = usePermissions(); const [open, setOpenImport] = useState(false); const [isLoading, setIsLoading] = useState(false); const [fileToImport, setFileToImport] = useState(null); const { isActiveProgram } = useProgramContext(); const { t } = useTranslation(); const { mutate, error } = useUploadPeriodicDataUpdateTemplate(); + const canPDUUpload = hasPermissions(PERMISSIONS.PDU_UPLOAD, permissions); const handleFileUpload = (): void => { if (fileToImport) { @@ -65,11 +68,7 @@ export const PeriodDataUpdatesUploadDialog = (): React.ReactElement => { } }; let errorMessage = null; - // @ts-ignore - if (error && error?.data?.error) { - // @ts-ignore - errorMessage = {error?.data?.error}; - } else if (error) { + if (error) { errorMessage = ( {t('Error uploading file:')} {error.message} @@ -80,15 +79,15 @@ export const PeriodDataUpdatesUploadDialog = (): React.ReactElement => { return ( <> - + { isNewTemplateJustCreated ? 1 : 0, ); + const canViewPDUListAndDetails = hasPermissions( + PERMISSIONS.PDU_VIEW_LIST_AND_DETAILS, + permissions, + ); + + const canViewHouseholdMembersPage = hasPermissions( + PERMISSIONS.POPULATION_VIEW_INDIVIDUALS_LIST, + permissions, + ); + if (householdChoicesLoading || individualChoicesLoading) return ; if (!individualChoicesData || !householdChoicesData || permissions === null) return null; - if ( - !hasPermissions(PERMISSIONS.POPULATION_VIEW_INDIVIDUALS_LIST, permissions) - ) - return ; + if (!canViewHouseholdMembersPage) return ; return ( <> @@ -84,7 +91,24 @@ export const HouseholdMembersPage = (): React.ReactElement => { }} > - {!programHasPdu ? ( + {programHasPdu ? ( + canViewPDUListAndDetails ? ( + + ) : ( + + + + + + ) + ) : ( { > - ) : ( - )} } @@ -136,8 +154,10 @@ export const HouseholdMembersPage = (): React.ReactElement => { /> - ) : ( + ) : canViewPDUListAndDetails ? ( + ) : ( + )}