import axios from "axios"; import { useState } from "react"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Label } from "../ui/label"; import { Maximize2, Minimize2, Trash2Icon } from "lucide-react"; import GroupPermission from "./group-permission"; import { z } from "zod"; import UserList from "./user-list-group"; interface Group { id: string | undefined name: string priority: number permissionsLoaded: { id: string, path: string, allow: boolean | null }[] edit: boolean showEdit: boolean isNewGroup: boolean permissionPaths: { path: string, description: string }[] specialGroups: string[] adder: (id: string, name: string, priority: number) => void remover: (group: { id: string, name: string, priority: number }) => void } const GroupElement = ({ id, name, priority, permissionsLoaded, edit, showEdit, isNewGroup, permissionPaths, specialGroups, adder, remover }: Group) => { const [isEditable, setIsEditable] = useState(edit) const [isNew, setIsNew] = useState(isNewGroup) const [isMinimized, setIsMinimized] = useState(true) const [oldData, setOldData] = useState<{ name: string, priority: number } | undefined>(undefined) const [group, setGroup] = useState<{ id: string | undefined, name: string, priority: number }>({ id, name, priority }) const [permissions, setPermissions] = useState<{ id: string, path: string, allow: boolean | null }[]>(permissionsLoaded); const isSpecial = (isEditable || oldData === undefined) && !!group && specialGroups.includes(group?.name) const [error, setError] = useState(undefined) function addPermission(id: string, path: string, allow: boolean | null) { setPermissions([...permissions, { id, path, allow }]) } function removePermission(permission: { id: string, path: string, allow: boolean | null }) { setPermissions(permissions.filter(p => p.id != permission.id)) } const nameSchema = z.string({ required_error: "Name is required.", invalid_type_error: "Name must be a string" }).regex(/^[\w\-\s]{1,20}$/, "Name must contain only letters, numbers, dashes, and underscores.") const prioritySchema = z.string().regex(/^-?\d{1,5}$/, "Priority must be a valid number.") function Save() { setError(undefined) if (!isNew && !id) return const nameValidation = nameSchema.safeParse(group.name) if (!nameValidation.success) { setError(JSON.parse(nameValidation.error['message'])[0].message) return } const priorityValidation = prioritySchema.safeParse(group.priority.toString()) if (!priorityValidation.success) { setError(JSON.parse(priorityValidation.error['message'])[0].message) return } if (isNew || group.id?.startsWith('$')) { axios.post("/api/settings/groups", { name: group.name, priority: group.priority }).then(d => { if (!d) { setError("Something went wrong.") return } console.log("DATA", d.data) if (specialGroups.includes(group.name)) { setIsNew(false) setIsEditable(false) setGroup({ id: d.data.id, name: d.data.name, priority: d.data.priority }) } else { adder(d.data.id, group.name.toLowerCase(), group.priority) setGroup({ id: undefined, name: "", priority: 0 }) } }).catch(() => { setError("Potential group name duplicate.") }) } else { axios.put("/api/settings/groups", { id: group.id, name: group.name, priority: group.priority }).then(d => { console.log("DATA", d.data) setIsEditable(false) }).catch(() => { setError("Potential group name duplicate.") }) } } function Cancel() { setError(undefined) if (!oldData) return setGroup({ ...oldData, id: group.id }) setIsEditable(false) setOldData(undefined) } function Delete() { axios.delete("/api/settings/groups?id=" + group.id) .then(d => { if (specialGroups.includes(group.name)) { setPermissions([]) setIsMinimized(true) setOldData(undefined) setIsNew(true) setIsEditable(true) } else remover(d.data) }) } return (
{isSpecial &&
auto-generated
} setGroup({ ...group, name: e.target.value })} readOnly={isSpecial || !isEditable} />
setGroup(d => { let temp = { ...group } const v = parseInt(e.target.value) if (e.target.value.length == 0) { temp.priority = 0 } else if (!Number.isNaN(v) && Number.isSafeInteger(v)) { temp.priority = v } else if (Number.isNaN(v)) { temp.priority = 0 } return temp })} readOnly={!isEditable} />

{error}

{isEditable && } {isEditable && !isNew && } {showEdit && !isEditable && } {!isEditable && !isNew && } {!isNew && !group?.id?.startsWith('$') && } {!isNew && !isSpecial && }
{!isNew && !isMinimized &&
{permissions.map(permission =>
)}
}
); } export default GroupElement;