211 lines
7.8 KiB
TypeScript
211 lines
7.8 KiB
TypeScript
|
import axios from "axios";
|
||
|
import { useEffect, useState } from "react";
|
||
|
import { Input } from "@/components/ui/input";
|
||
|
import { Button } from "@/components/ui/button";
|
||
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
|
||
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||
|
import { Label } from "../ui/label";
|
||
|
import { HelpCircleIcon, Trash2Icon } from "lucide-react";
|
||
|
import {
|
||
|
Tooltip,
|
||
|
TooltipContent,
|
||
|
TooltipProvider,
|
||
|
TooltipTrigger,
|
||
|
} from "../ui/tooltip"
|
||
|
import { Checkbox } from "../ui/checkbox";
|
||
|
|
||
|
interface Permission {
|
||
|
id: string|undefined
|
||
|
path: string
|
||
|
allow: boolean|null
|
||
|
groupId: string
|
||
|
edit: boolean
|
||
|
showEdit: boolean
|
||
|
isNew: boolean
|
||
|
permissionPaths: { path: string, description: string }[]
|
||
|
adder: (id: string, path: string, allow: boolean|null) => void
|
||
|
remover: (redemption: { id: string, path: string, allow: boolean|null }) => void
|
||
|
}
|
||
|
|
||
|
const GroupPermission = ({
|
||
|
id,
|
||
|
path,
|
||
|
allow,
|
||
|
groupId,
|
||
|
edit,
|
||
|
showEdit,
|
||
|
isNew,
|
||
|
permissionPaths,
|
||
|
adder,
|
||
|
remover
|
||
|
}: Permission) => {
|
||
|
const [pathOpen, setPathOpen] = useState(false)
|
||
|
const [isEditable, setIsEditable] = useState(edit)
|
||
|
const [oldData, setOldData] = useState<{ path: string, allow: boolean|null } | undefined>(undefined)
|
||
|
const [permission, setPermission] = useState<{ id: string|undefined, path: string, allow: boolean|null }>({ id, path, allow });
|
||
|
|
||
|
function Save() {
|
||
|
if (!permission || !permission.path)
|
||
|
return
|
||
|
|
||
|
if (isNew) {
|
||
|
axios.post("/api/settings/groups/permissions", {
|
||
|
path: permission.path,
|
||
|
allow: permission.allow,
|
||
|
groupId: groupId
|
||
|
}).then(d => {
|
||
|
if (!d || !d.data)
|
||
|
return
|
||
|
|
||
|
adder(d.data.id, permission.path, permission.allow)
|
||
|
setPermission({ id: undefined, path: "", allow: true })
|
||
|
})
|
||
|
} else {
|
||
|
axios.put("/api/settings/groups/permissions", {
|
||
|
id: permission.id,
|
||
|
path: permission.path,
|
||
|
allow: permission.allow
|
||
|
}).then(d => {
|
||
|
setIsEditable(false)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function Cancel() {
|
||
|
if (!oldData)
|
||
|
return
|
||
|
|
||
|
setPermission({ ...oldData, id: permission.id })
|
||
|
setIsEditable(false)
|
||
|
setOldData(undefined)
|
||
|
}
|
||
|
|
||
|
function Delete() {
|
||
|
axios.delete("/api/settings/groups/permissions?id=" + permission.id)
|
||
|
.then(d => {
|
||
|
remover(d.data)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<div
|
||
|
className="bg-green-400 p-2 border-2 border-green-500 rounded-lg grid grid-flow-row">
|
||
|
<div
|
||
|
className="pb-3 flex grow">
|
||
|
{!isEditable &&
|
||
|
<Input
|
||
|
className="flex grow ml-1"
|
||
|
id="path"
|
||
|
value={permission.path}
|
||
|
readOnly />
|
||
|
|| isEditable &&
|
||
|
<Popover
|
||
|
open={pathOpen}
|
||
|
onOpenChange={setPathOpen}>
|
||
|
<PopoverTrigger asChild>
|
||
|
<Button
|
||
|
variant="outline"
|
||
|
id="path"
|
||
|
role="combobox"
|
||
|
className="flex grow justify-between"
|
||
|
>{!permission.path ? "Select a permission" : permission.path}</Button>
|
||
|
</PopoverTrigger>
|
||
|
<PopoverContent>
|
||
|
<Command>
|
||
|
<CommandInput
|
||
|
placeholder="Search..."
|
||
|
inputMode="search"
|
||
|
autoFocus={true} />
|
||
|
<CommandList>
|
||
|
<CommandEmpty>No permission found.</CommandEmpty>
|
||
|
<CommandGroup>
|
||
|
{permissionPaths.map((p) => (
|
||
|
<CommandItem
|
||
|
value={p.path}
|
||
|
key={p.path}
|
||
|
onSelect={(value) => {
|
||
|
setPermission({ ...permission, path: permissionPaths.find(v => v.path.toLowerCase() == value.toLowerCase())?.path ?? value.toLowerCase()})
|
||
|
setPathOpen(false)
|
||
|
}}>
|
||
|
<div>
|
||
|
<div className="text-lg">
|
||
|
{p.path}
|
||
|
</div>
|
||
|
<div className="text-xs text-green-200">
|
||
|
{p.description}
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
</CommandItem>
|
||
|
))}
|
||
|
</CommandGroup>
|
||
|
</CommandList>
|
||
|
</Command>
|
||
|
</PopoverContent>
|
||
|
</Popover>
|
||
|
}
|
||
|
</div>
|
||
|
<div
|
||
|
className="grid grid-cols-2 gap-1">
|
||
|
<Label>
|
||
|
Inherit from parent
|
||
|
</Label>
|
||
|
<Checkbox
|
||
|
checked={permission.allow === null}
|
||
|
onCheckedChange={(e) => {
|
||
|
if (permission.allow === null)
|
||
|
setPermission({ ...permission, allow: false })
|
||
|
else
|
||
|
setPermission({ ...permission, allow: null })
|
||
|
}}
|
||
|
disabled={!isEditable} />
|
||
|
<Label
|
||
|
htmlFor="inherit">
|
||
|
Allow
|
||
|
</Label>
|
||
|
<Checkbox
|
||
|
id="inherit"
|
||
|
checked={permission.allow === true}
|
||
|
onCheckedChange={(e) => {
|
||
|
setPermission({ ...permission, allow: !permission.allow })
|
||
|
}}
|
||
|
disabled={!isEditable || permission === undefined} />
|
||
|
</div>
|
||
|
<div>
|
||
|
{isEditable &&
|
||
|
<Button
|
||
|
className="m-3"
|
||
|
onClick={() => Save()}>
|
||
|
{isNew ? "Add" : "Save"}
|
||
|
</Button>
|
||
|
}
|
||
|
{isEditable && !isNew &&
|
||
|
<Button
|
||
|
className="m-3"
|
||
|
onClick={() => Cancel()}>
|
||
|
Cancel
|
||
|
</Button>
|
||
|
}
|
||
|
{showEdit && !isEditable &&
|
||
|
<Button
|
||
|
className="m-3"
|
||
|
onClick={() => {
|
||
|
setOldData({ ...permission })
|
||
|
setIsEditable(true)
|
||
|
}}>
|
||
|
Edit
|
||
|
</Button>
|
||
|
}
|
||
|
{!isEditable &&
|
||
|
<Button
|
||
|
className="m-3 bg-red-500 hover:bg-red-600 align-bottom"
|
||
|
onClick={() => Delete()}>
|
||
|
<Trash2Icon />
|
||
|
</Button>
|
||
|
}
|
||
|
</div>
|
||
|
</div>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
export default GroupPermission;
|