Skip to content

Commit aa5e93a

Browse files
[OPIK-4716] Annotation queue edit permission (#5878)
* [OPIK-4716] Add permission * [OPIK-4716] Implement guards
1 parent c1a02c4 commit aa5e93a

File tree

10 files changed

+49
-14
lines changed

10 files changed

+49
-14
lines changed

apps/opik-frontend/src/plugins/comet/PermissionsProvider.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const PermissionsProvider: React.FC<{ children: ReactNode }> = ({
2020
canCreateProjects,
2121
canDeleteProjects,
2222
canCreateAnnotationQueues,
23+
canEditAnnotationQueues,
2324
canDeleteAnnotationQueues,
2425
canDeleteTraces,
2526
canDeletePrompts,
@@ -50,6 +51,7 @@ const PermissionsProvider: React.FC<{ children: ReactNode }> = ({
5051
canCreateProjects,
5152
canDeleteProjects,
5253
canCreateAnnotationQueues,
54+
canEditAnnotationQueues,
5355
canDeleteAnnotationQueues,
5456
canDeleteTraces,
5557
canDeletePrompts,
@@ -78,6 +80,7 @@ const PermissionsProvider: React.FC<{ children: ReactNode }> = ({
7880
canCreateProjects,
7981
canDeleteProjects,
8082
canCreateAnnotationQueues,
83+
canEditAnnotationQueues,
8184
canDeleteAnnotationQueues,
8285
canDeleteTraces,
8386
canDeletePrompts,

apps/opik-frontend/src/plugins/comet/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export enum ManagementPermissionsNames {
7474
DATASET_EDIT = "dataset_edit",
7575
DATASET_DELETE = "dataset_delete",
7676
ANNOTATION_QUEUE_CREATE = "annotation_queue_create",
77+
ANNOTATION_QUEUE_EDIT = "annotation_queue_edit",
7778
ANNOTATION_QUEUE_DELETE = "annotation_queue_delete",
7879
TRACE_TAG = "trace_tag",
7980
TRACE_DELETE = "trace_delete",

apps/opik-frontend/src/plugins/comet/useUserPermission.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ const useUserPermission = (config?: { enabled?: boolean }) => {
141141
[checkNullablePermission],
142142
);
143143

144+
const canEditAnnotationQueues = useMemo(
145+
() =>
146+
checkNullablePermission(ManagementPermissionsNames.ANNOTATION_QUEUE_EDIT),
147+
[checkNullablePermission],
148+
);
149+
144150
const canDeleteAnnotationQueues = useMemo(
145151
() =>
146152
checkNullablePermission(
@@ -233,6 +239,7 @@ const useUserPermission = (config?: { enabled?: boolean }) => {
233239
canCreateProjects,
234240
canDeleteProjects,
235241
canCreateAnnotationQueues,
242+
canEditAnnotationQueues,
236243
canDeleteAnnotationQueues,
237244
canDeleteTraces,
238245
canDeletePrompts,

apps/opik-frontend/src/types/permissions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export interface Permissions {
1111
canDeleteDatasets: boolean;
1212
canDeleteProjects: boolean;
1313
canCreateAnnotationQueues: boolean;
14+
canEditAnnotationQueues: boolean;
1415
canDeleteAnnotationQueues: boolean;
1516
canDeleteTraces: boolean;
1617
canDeletePrompts: boolean;
@@ -44,6 +45,7 @@ export const DEFAULT_PERMISSIONS: PermissionsContextValue = {
4445
canDeleteDatasets: true,
4546
canDeleteProjects: true,
4647
canCreateAnnotationQueues: true,
48+
canEditAnnotationQueues: true,
4749
canDeleteAnnotationQueues: true,
4850
canDeleteTraces: true,
4951
canDeletePrompts: true,

apps/opik-frontend/src/v1/pages-shared/annotation-queues/AddEditAnnotationQueueDialog.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const AddEditAnnotationQueueDialog: React.FunctionComponent<
8888
queue: defaultQueue,
8989
}) => {
9090
const {
91-
permissions: { canCreateAnnotationQueues },
91+
permissions: { canCreateAnnotationQueues, canEditAnnotationQueues },
9292
} = usePermissions();
9393

9494
const [isNestedDialogOpen, setIsNestedDialogOpen] = useState(false);
@@ -163,7 +163,9 @@ const AddEditAnnotationQueueDialog: React.FunctionComponent<
163163

164164
return (
165165
<Dialog
166-
open={open && (isEdit || canCreateAnnotationQueues)}
166+
open={
167+
open && (isEdit ? canEditAnnotationQueues : canCreateAnnotationQueues)
168+
}
167169
onOpenChange={setOpen}
168170
>
169171
<DialogContent

apps/opik-frontend/src/v1/pages-shared/annotation-queues/AnnotationQueueRowActionsCell.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const AnnotationQueueRowActionsCell: React.FunctionComponent<
3333
const { mutate } = useAnnotationQueueDeleteMutation();
3434

3535
const {
36-
permissions: { canDeleteAnnotationQueues },
36+
permissions: { canEditAnnotationQueues, canDeleteAnnotationQueues },
3737
} = usePermissions();
3838

3939
const handleCopySMELink = useCallback(() => {
@@ -95,10 +95,12 @@ const AnnotationQueueRowActionsCell: React.FunctionComponent<
9595
<Copy className="mr-2 size-4" />
9696
Copy sharing link
9797
</DropdownMenuItem>
98-
<DropdownMenuItem onClick={handleEdit}>
99-
<Pencil className="mr-2 size-4" />
100-
Edit
101-
</DropdownMenuItem>
98+
{canEditAnnotationQueues && (
99+
<DropdownMenuItem onClick={handleEdit}>
100+
<Pencil className="mr-2 size-4" />
101+
Edit
102+
</DropdownMenuItem>
103+
)}
102104
{canDeleteAnnotationQueues && (
103105
<>
104106
<DropdownMenuSeparator />

apps/opik-frontend/src/v1/pages/AnnotationQueuePage/EditAnnotationQueueButton.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import AddEditAnnotationQueueDialog from "@/v1/pages-shared/annotation-queues/Ad
44
import { Button } from "@/ui/button";
55
import { Pencil } from "lucide-react";
66
import TooltipWrapper from "@/shared/TooltipWrapper/TooltipWrapper";
7+
import { usePermissions } from "@/contexts/PermissionsContext";
78

89
interface EditAnnotationQueueButtonProps {
910
annotationQueue: AnnotationQueue;
@@ -12,6 +13,10 @@ interface EditAnnotationQueueButtonProps {
1213
const EditAnnotationQueueButton: React.FunctionComponent<
1314
EditAnnotationQueueButtonProps
1415
> = ({ annotationQueue }) => {
16+
const {
17+
permissions: { canEditAnnotationQueues },
18+
} = usePermissions();
19+
1520
const resetKeyRef = useRef(0);
1621
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
1722

@@ -20,6 +25,8 @@ const EditAnnotationQueueButton: React.FunctionComponent<
2025
resetKeyRef.current = resetKeyRef.current + 1;
2126
}, []);
2227

28+
if (!canEditAnnotationQueues) return null;
29+
2330
return (
2431
<>
2532
<AddEditAnnotationQueueDialog

apps/opik-frontend/src/v2/pages-shared/annotation-queues/AddEditAnnotationQueueDialog.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ const AddEditAnnotationQueueDialog: React.FunctionComponent<
8787
queue: defaultQueue,
8888
}) => {
8989
const {
90-
permissions: { canCreateAnnotationQueues },
90+
permissions: { canCreateAnnotationQueues, canEditAnnotationQueues },
9191
} = usePermissions();
9292

9393
const [isNestedDialogOpen, setIsNestedDialogOpen] = useState(false);
@@ -162,7 +162,9 @@ const AddEditAnnotationQueueDialog: React.FunctionComponent<
162162

163163
return (
164164
<Dialog
165-
open={open && (isEdit || canCreateAnnotationQueues)}
165+
open={
166+
open && (isEdit ? canEditAnnotationQueues : canCreateAnnotationQueues)
167+
}
166168
onOpenChange={setOpen}
167169
>
168170
<DialogContent

apps/opik-frontend/src/v2/pages-shared/annotation-queues/AnnotationQueueRowActionsCell.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const AnnotationQueueRowActionsCell: React.FunctionComponent<
3333
const { mutate } = useAnnotationQueueDeleteMutation();
3434

3535
const {
36-
permissions: { canDeleteAnnotationQueues },
36+
permissions: { canEditAnnotationQueues, canDeleteAnnotationQueues },
3737
} = usePermissions();
3838

3939
const handleCopySMELink = useCallback(() => {
@@ -95,10 +95,12 @@ const AnnotationQueueRowActionsCell: React.FunctionComponent<
9595
<Copy className="mr-2 size-4" />
9696
Copy sharing link
9797
</DropdownMenuItem>
98-
<DropdownMenuItem onClick={handleEdit}>
99-
<Pencil className="mr-2 size-4" />
100-
Edit
101-
</DropdownMenuItem>
98+
{canEditAnnotationQueues && (
99+
<DropdownMenuItem onClick={handleEdit}>
100+
<Pencil className="mr-2 size-4" />
101+
Edit
102+
</DropdownMenuItem>
103+
)}
102104
{canDeleteAnnotationQueues && (
103105
<>
104106
<DropdownMenuSeparator />

apps/opik-frontend/src/v2/pages/AnnotationQueuePage/EditAnnotationQueueButton.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import AddEditAnnotationQueueDialog from "@/v2/pages-shared/annotation-queues/Ad
44
import { Button } from "@/ui/button";
55
import { Pencil } from "lucide-react";
66
import TooltipWrapper from "@/shared/TooltipWrapper/TooltipWrapper";
7+
import { usePermissions } from "@/contexts/PermissionsContext";
78

89
interface EditAnnotationQueueButtonProps {
910
annotationQueue: AnnotationQueue;
@@ -12,6 +13,10 @@ interface EditAnnotationQueueButtonProps {
1213
const EditAnnotationQueueButton: React.FunctionComponent<
1314
EditAnnotationQueueButtonProps
1415
> = ({ annotationQueue }) => {
16+
const {
17+
permissions: { canEditAnnotationQueues },
18+
} = usePermissions();
19+
1520
const resetKeyRef = useRef(0);
1621
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
1722

@@ -20,6 +25,8 @@ const EditAnnotationQueueButton: React.FunctionComponent<
2025
resetKeyRef.current = resetKeyRef.current + 1;
2126
}, []);
2227

28+
if (!canEditAnnotationQueues) return null;
29+
2330
return (
2431
<>
2532
<AddEditAnnotationQueueDialog

0 commit comments

Comments
 (0)