From 0bfb5cbddd8d7318800c576b3a939a651c97aba8 Mon Sep 17 00:00:00 2001 From: Anna Viklund Date: Sun, 18 Feb 2024 23:00:42 +0100 Subject: [PATCH] Consider job permissions in UI (#346) * Check user permissions for creating jobs * Check user permissions for processing captures * Check user permissions for marking capture as starred * Check project permissions instead of capture permissions --- ui/src/data-services/hooks/jobs/useJobs.ts | 4 ++++ .../hooks/projects/useProjectDetails.ts | 4 +++- ui/src/pages/jobs/jobs.tsx | 19 +++++++++++++------ .../playback/capture-job/process-now.tsx | 9 ++++++++- .../playback-controls/star-button.tsx | 14 +++++++++++--- ui/src/utils/language.ts | 3 +++ 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/ui/src/data-services/hooks/jobs/useJobs.ts b/ui/src/data-services/hooks/jobs/useJobs.ts index 0f9d73f6e..68dc24ae4 100644 --- a/ui/src/data-services/hooks/jobs/useJobs.ts +++ b/ui/src/data-services/hooks/jobs/useJobs.ts @@ -4,6 +4,7 @@ import { FetchParams } from 'data-services/types' import { getFetchUrl } from 'data-services/utils' import { useMemo } from 'react' import { useAuthorizedQuery } from '../auth/useAuthorizedQuery' +import { UserPermission } from 'utils/user/types' const REFETCH_INTERVAL = 10000 // Refetch every 10 second @@ -14,6 +15,7 @@ export const useJobs = ( ): { jobs?: Job[] total: number + userPermissions?: UserPermission[] isLoading: boolean isFetching: boolean error?: unknown @@ -22,6 +24,7 @@ export const useJobs = ( const { data, isLoading, isFetching, error } = useAuthorizedQuery<{ results: ServerJob[] + user_permissions?: UserPermission[] count: number }>({ queryKey: [API_ROUTES.JOBS, params], @@ -34,6 +37,7 @@ export const useJobs = ( return { jobs, total: data?.count ?? 0, + userPermissions: data?.user_permissions, isLoading, isFetching, error, diff --git a/ui/src/data-services/hooks/projects/useProjectDetails.ts b/ui/src/data-services/hooks/projects/useProjectDetails.ts index e0edf1df4..945e576dc 100644 --- a/ui/src/data-services/hooks/projects/useProjectDetails.ts +++ b/ui/src/data-services/hooks/projects/useProjectDetails.ts @@ -6,7 +6,8 @@ import { useAuthorizedQuery } from '../auth/useAuthorizedQuery' const convertServerRecord = (record: ServerProject) => new Project(record) export const useProjectDetails = ( - projectId: string + projectId: string, + useInternalCache?: boolean ): { project?: Project isLoading: boolean @@ -16,6 +17,7 @@ export const useProjectDetails = ( const { data, isLoading, isFetching, error } = useAuthorizedQuery({ queryKey: [API_ROUTES.PROJECTS, projectId], url: `${API_URL}/${API_ROUTES.PROJECTS}/${projectId}/`, + staleTime: useInternalCache ? Infinity : undefined, }) const project = useMemo( diff --git a/ui/src/pages/jobs/jobs.tsx b/ui/src/pages/jobs/jobs.tsx index c613e3a1f..2bc3abf52 100644 --- a/ui/src/pages/jobs/jobs.tsx +++ b/ui/src/pages/jobs/jobs.tsx @@ -18,16 +18,19 @@ import { STRING, translate } from 'utils/language' import { usePagination } from 'utils/usePagination' import { columns } from './jobs-columns' import styles from './jobs.module.scss' +import { UserPermission } from 'utils/user/types' export const Jobs = () => { const { projectId, id } = useParams() const { pagination, setPage } = usePagination() const [sort, setSort] = useState() - const { jobs, total, isLoading, isFetching, error } = useJobs({ - projectId, - pagination, - sort, - }) + const { jobs, userPermissions, total, isLoading, isFetching, error } = + useJobs({ + projectId, + pagination, + sort, + }) + const canCreate = userPermissions?.includes(UserPermission.Create) if (!isLoading && error) { return @@ -55,7 +58,11 @@ export const Jobs = () => { setPage={setPage} /> ) : null} - {!isLoading && id ? : } + {!isLoading && id ? ( + + ) : canCreate ? ( + + ) : null} ) } diff --git a/ui/src/pages/session-details/playback/capture-job/process-now.tsx b/ui/src/pages/session-details/playback/capture-job/process-now.tsx index c79a31d42..1b3505f0f 100644 --- a/ui/src/pages/session-details/playback/capture-job/process-now.tsx +++ b/ui/src/pages/session-details/playback/capture-job/process-now.tsx @@ -1,4 +1,5 @@ import { useCreateJob } from 'data-services/hooks/jobs/useCreateJob' +import { useProjectDetails } from 'data-services/hooks/projects/useProjectDetails' import { CaptureDetails } from 'data-services/models/capture-details' import { Button, ButtonTheme } from 'design-system/components/button/button' import { IconType } from 'design-system/components/icon/icon' @@ -14,6 +15,7 @@ export const ProcessNow = ({ pipelineId?: string }) => { const { projectId } = useParams() + const { project } = useProjectDetails(projectId as string, true) const { createJob, isLoading, isSuccess } = useCreateJob() const icon = isSuccess ? IconType.RadixCheck : undefined const disabled = !capture || capture.hasJobInProgress || !pipelineId @@ -30,9 +32,14 @@ export const ProcessNow = ({ ) } + const tooltipContent = project?.canUpdate + ? translate(STRING.MESSAGE_PROCESS_NOW_TOOLTIP) + : translate(STRING.MESSAGE_PERMISSIONS_MISSING) + return ( - +