StoragePoliciesBucketRow.tsx108 lines · main
1import { FilesBucket as FilesBucketIcon } from 'icons'
2import { noop } from 'lodash'
3import { forwardRef, type CSSProperties } from 'react'
4import {
5 Badge,
6 Button,
7 Card,
8 CardContent,
9 CardHeader,
10 CardTitle,
11 Table,
12 TableBody,
13 TableHead,
14 TableHeader,
15 TableRow,
16 Tooltip,
17 TooltipContent,
18 TooltipTrigger,
19} from 'ui'
20
21import { PolicyRow } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow'
22import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
23import { PUBLIC_BUCKET_TOOLTIP } from '@/components/interfaces/Storage/Storage.constants'
24import { Bucket } from '@/data/storage/buckets-query'
25
26interface StoragePoliciesBucketRowProps {
27 table: string
28 label: string
29 bucket?: Bucket
30 policies: Policy[]
31 style?: CSSProperties
32 onSelectPolicyAdd: (bucketName: string | undefined, table: string) => void
33 onSelectPolicyEdit: (policy: Policy, bucketName: string, table: string) => void
34 onSelectPolicyDelete: (policy: Policy) => void
35}
36
37export const StoragePoliciesBucketRow = forwardRef<HTMLDivElement, StoragePoliciesBucketRowProps>(
38 (
39 {
40 table = '',
41 label = '',
42 bucket,
43 policies = [],
44 style,
45 onSelectPolicyAdd = noop,
46 onSelectPolicyEdit = noop,
47 onSelectPolicyDelete = noop,
48 },
49 ref
50 ) => {
51 return (
52 <Card ref={ref} style={style}>
53 <CardHeader className="flex flex-row w-full items-center justify-between gap-2 space-y-0">
54 <div className="flex flex-1 min-w-0 items-center gap-3">
55 <FilesBucketIcon className="text-foreground-muted" size={16} strokeWidth={1.5} />
56 <div className="flex flex-1 min-w-0 items-center gap-1.5">
57 <CardTitle className="truncate">{label}</CardTitle>
58 {bucket?.public && (
59 <Tooltip>
60 <TooltipTrigger asChild>
61 <Badge variant="warning" className="flex">
62 Public
63 </Badge>
64 </TooltipTrigger>
65 <TooltipContent side="top">{PUBLIC_BUCKET_TOOLTIP}</TooltipContent>
66 </Tooltip>
67 )}
68 </div>
69 </div>
70 <Button type="outline" onClick={() => onSelectPolicyAdd(bucket?.name, table)}>
71 New policy
72 </Button>
73 </CardHeader>
74 {policies.length === 0 ? (
75 <CardContent>
76 <p className="text-sm text-foreground-lighter">No policies created yet</p>
77 </CardContent>
78 ) : (
79 <CardContent className="p-0">
80 <Table className="table-fixed">
81 <TableHeader>
82 <TableRow>
83 <TableHead className="w-[40%]">Name</TableHead>
84 <TableHead className="w-[20%]">Command</TableHead>
85 <TableHead className="w-[30%]">Applied to</TableHead>
86 <TableHead className="text-right">
87 <span className="sr-only">Actions</span>
88 </TableHead>
89 </TableRow>
90 </TableHeader>
91 <TableBody>
92 {policies.map((policy) => (
93 <PolicyRow
94 key={policy.id ?? policy.name}
95 policy={policy}
96 onSelectEditPolicy={(p) => onSelectPolicyEdit(p, bucket?.name ?? '', table)}
97 onSelectDeletePolicy={onSelectPolicyDelete}
98 />
99 ))}
100 </TableBody>
101 </Table>
102 </CardContent>
103 )}
104 </Card>
105 )
106 }
107)
108StoragePoliciesBucketRow.displayName = 'StoragePoliciesBucketRow'