234 lines
9.1 KiB
React
234 lines
9.1 KiB
React
import {Flex, Separator, Text, Table, IconButton, NativeSelect, Button} from "@chakra-ui/react";
|
|
import { useMemo } from "react";
|
|
import { useForm, useFieldArray } from "react-hook-form";
|
|
import { Check, X, PenLine } from 'lucide-react';
|
|
import VdapApi from "../../hooks/useVdapApi.js";
|
|
import useBuildUrl from "../../hooks/useBuildUrl.js";
|
|
|
|
export default function WebAdmin() {
|
|
// TODO: add below api endpoint
|
|
// const {data: users, isLoading, error} = VdapApi('/api/v2/vdap_web_users');
|
|
|
|
const users = useMemo(() => [
|
|
{
|
|
"username": "vkuchenik",
|
|
"firstName": "Venessa",
|
|
"lastName": "Kuchenik",
|
|
"permissions": {
|
|
"ivans": 2, // 2 => requested permission
|
|
"rs": 0, // 0 => no permissions and not requested
|
|
},
|
|
"team": "Computer Science",
|
|
"group": "Super User",
|
|
},
|
|
{
|
|
"username": "amack",
|
|
"firstName": "Adeiline",
|
|
"lastName": "Mack",
|
|
"permissions": {
|
|
"ivans": 2, // 0 => no permissions and not requested
|
|
"rs": 2, // 1 => has permission
|
|
},
|
|
"team": "Remote Sensing",
|
|
"group": "Member",
|
|
}
|
|
], []);
|
|
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
control,
|
|
errors,
|
|
formState: { isDirty }
|
|
} = useForm({
|
|
defaultValues: {users: users}
|
|
});
|
|
|
|
const { fields, append, remove } = useFieldArray({
|
|
control,
|
|
name: "users" // Matches the key in defaultValues
|
|
})
|
|
|
|
const grant = (user, category) => {
|
|
// 1. post data via api
|
|
// 2. fetch the new data via api again to force re-render
|
|
console.log(user.username, "was granted", category, "permission");
|
|
}
|
|
|
|
const deny = (user, category) => {
|
|
console.log(user.username, "was denied", category, "permission");
|
|
}
|
|
|
|
const users_req_ivans = useMemo(() => {
|
|
return users.filter(user => user.permissions.ivans === 2);
|
|
}, [users]);
|
|
|
|
const users_req_rs = useMemo(() => {
|
|
return users.filter(user => user.permissions.rs === 2);
|
|
}, [users]);
|
|
|
|
const onSubmit = (data, event) => {
|
|
event.preventDefault();
|
|
console.log(data);
|
|
}
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit(onSubmit)}>
|
|
<Flex direction="column" w="100%" h="100%" p="15rem" pt="3rem" gap="3rem">
|
|
|
|
{/* CONTENT */}
|
|
<Flex direction="column" w="100%" gap={4}>
|
|
{/* Header */}
|
|
<Text fontSize="xl" fontWeight="bold">Web Admin Panel</Text>
|
|
|
|
<Separator borderColor="gray.300"/>
|
|
|
|
{/* Permission Requests */}
|
|
<Flex direction="column" w="100%" gap={2} pb={4}>
|
|
<Text fontSize="lg" fontWeight="bold">Incoming Permission Requests</Text>
|
|
<Flex direction="row" w="100%" gap={5}>
|
|
{/* ivans requests table */}
|
|
<Flex direction="column" w="100%" gap={2}>
|
|
<Text fontSize="sm" fontWeight="bold">IVANS</Text>
|
|
<Table.Root w="100%" size="sm" variant="outline" borderRadius="lg">
|
|
<Table.Header>
|
|
<Table.Row>
|
|
<Table.ColumnHeader w="100%" fontWeight="bold">User</Table.ColumnHeader>
|
|
<Table.ColumnHeader fontWeight="bold" textAlign="left">Permission</Table.ColumnHeader>
|
|
</Table.Row>
|
|
</Table.Header>
|
|
<Table.Body>
|
|
{users_req_ivans.map((user) => (
|
|
<Table.Row key={user.username}>
|
|
<Table.Cell w="100%">{user.lastName}, {user.firstName}</Table.Cell>
|
|
<Table.Cell >
|
|
<Flex w="100%" gap={1} justify="left">
|
|
<IconButton borderRadius="xl" size="xs" variant="subtle" onClick={() => grant(user, "ivans")}>
|
|
<Check />
|
|
</IconButton>
|
|
<IconButton borderRadius="xl" size="xs" variant="subtle" onClick={() => deny(user, "ivans")}>
|
|
<X />
|
|
</IconButton>
|
|
</Flex>
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
))}
|
|
</Table.Body>
|
|
</Table.Root>
|
|
</Flex>
|
|
{/* rs requests table */}
|
|
<Flex direction="column" w="100%" gap={2}>
|
|
<Text fontSize="sm" fontWeight="bold">Remote Sensing</Text>
|
|
<Table.Root w="100%" size="sm" variant="outline" borderRadius="lg">
|
|
<Table.Header>
|
|
<Table.Row>
|
|
<Table.ColumnHeader w="100%" fontWeight="bold">User</Table.ColumnHeader>
|
|
<Table.ColumnHeader fontWeight="bold" textAlign="left">Permission</Table.ColumnHeader>
|
|
</Table.Row>
|
|
</Table.Header>
|
|
<Table.Body>
|
|
{users_req_rs.map((user) => (
|
|
<Table.Row key={user.username}>
|
|
<Table.Cell>{user.lastName}, {user.firstName}</Table.Cell>
|
|
<Table.Cell>
|
|
<Flex w="100%" gap={1} justify="left">
|
|
<IconButton borderRadius="xl" size="xs" variant="subtle" onClick={() => grant(user, "rs")}>
|
|
<Check />
|
|
</IconButton>
|
|
<IconButton borderRadius="xl" size="xs" variant="subtle" onClick={() => deny(user, "rs")}>
|
|
<X />
|
|
</IconButton>
|
|
</Flex>
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
))}
|
|
</Table.Body>
|
|
</Table.Root>
|
|
</Flex>
|
|
</Flex>
|
|
</Flex>
|
|
|
|
<Separator borderColor="gray.300"/>
|
|
|
|
{/* Group Assignment */}
|
|
<Flex direction="column" w="100%" gap={2} pb={4}>
|
|
<Text fontWeight="bold" fontSize="lg">Groups</Text>
|
|
<Table.Root w="50%" size="sm" variant="outline" borderRadius="lg">
|
|
<Table.Header>
|
|
<Table.Row>
|
|
<Table.ColumnHeader fontWeight="bold">User</Table.ColumnHeader>
|
|
<Table.ColumnHeader fontWeight="bold" textAlign="left">Group</Table.ColumnHeader>
|
|
</Table.Row>
|
|
</Table.Header>
|
|
<Table.Body>
|
|
{users.map((user, index) => (
|
|
<Table.Row key={user.username}>
|
|
<Table.Cell w="100%">{user.lastName}, {user.firstName}</Table.Cell>
|
|
<Table.Cell>
|
|
<Flex w="100%" justify="left">
|
|
<NativeSelect.Root size="sm" w="175px" variant="subtle">
|
|
<NativeSelect.Field
|
|
defaultValue={user.group}
|
|
{...register(`users.${index}.group`)}
|
|
>
|
|
<option value="Super User">Super User</option>
|
|
<option value="Member">Member</option>
|
|
</NativeSelect.Field>
|
|
<NativeSelect.Indicator />
|
|
</NativeSelect.Root>
|
|
</Flex>
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
))}
|
|
</Table.Body>
|
|
</Table.Root>
|
|
</Flex>
|
|
|
|
<Separator borderColor="gray.300"/>
|
|
|
|
{/* Team Assignment */}
|
|
<Flex direction="column" w="100%" gap={2} pb={4}>
|
|
<Text fontWeight="bold" fontSize="lg">Teams</Text>
|
|
<Table.Root w="50%" size="sm" variant="outline" borderRadius="lg">
|
|
<Table.Header>
|
|
<Table.Row>
|
|
<Table.ColumnHeader fontWeight="bold" w="100%">User</Table.ColumnHeader>
|
|
<Table.ColumnHeader fontWeight="bold" textAlign="left">Team</Table.ColumnHeader>
|
|
</Table.Row>
|
|
</Table.Header>
|
|
<Table.Body>
|
|
{users.map((user, index) => {
|
|
console.log("user in team: ", user.team);
|
|
return(
|
|
<Table.Row key={user.username}>
|
|
<Table.Cell>
|
|
{user.lastName}, {user.firstName}
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
<Flex w="100%" justify="right">
|
|
<NativeSelect.Root size="sm" w="175px" variant="subtle">
|
|
<NativeSelect.Field
|
|
defaultValue={user.team}
|
|
{...register(`users.${index}.team`)}
|
|
>
|
|
<option value="Computer Science">Computer Science</option>
|
|
<option value="Remote Sensing">Remote Sensing</option>
|
|
</NativeSelect.Field>
|
|
<NativeSelect.Indicator />
|
|
</NativeSelect.Root>
|
|
</Flex>
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
)})}
|
|
</Table.Body>
|
|
</Table.Root>
|
|
</Flex>
|
|
</Flex>
|
|
|
|
<Button type="submit" w="100px" variant="subtle" alignSelf="center">
|
|
Save
|
|
</Button>
|
|
</Flex>
|
|
</form>
|
|
)
|
|
} |