From d4858d809d912d4e2a83d46ec7a8b1b28dd94667 Mon Sep 17 00:00:00 2001 From: "Navy.gif" Date: Sat, 22 Apr 2023 20:18:04 +0300 Subject: [PATCH] Create role fields and button and some other WIP --- src/@types/ApiStructures.ts | 5 +- .../{FileSelector.tsx => Selectors.tsx} | 34 +++++- src/pages/Admin.tsx | 4 +- src/pages/Login.tsx | 2 +- src/pages/admin/Roles.tsx | 73 ++++++++--- src/pages/admin/Users.tsx | 115 ++++++++++-------- src/pages/home/Profile.tsx | 2 +- src/util/ErrorBoundary.tsx | 4 +- src/util/Util.ts | 1 + src/{components => views}/PermissionsView.tsx | 15 ++- src/{components => views}/RateLimitsView.tsx | 0 11 files changed, 172 insertions(+), 83 deletions(-) rename src/components/{FileSelector.tsx => Selectors.tsx} (60%) rename src/{components => views}/PermissionsView.tsx (81%) rename src/{components => views}/RateLimitsView.tsx (100%) diff --git a/src/@types/ApiStructures.ts b/src/@types/ApiStructures.ts index 0eb6dd1..d6fd9b0 100644 --- a/src/@types/ApiStructures.ts +++ b/src/@types/ApiStructures.ts @@ -24,12 +24,13 @@ type APIEntity = { name: string, disabled: boolean, permissions: Permissions, - createdTimestamp: number + createdTimestamp: number, + note: string } export type UserLike = { icon: string | null, - roles: string[], + roles: Role[], temporary: boolean } & APIEntity diff --git a/src/components/FileSelector.tsx b/src/components/Selectors.tsx similarity index 60% rename from src/components/FileSelector.tsx rename to src/components/Selectors.tsx index 72116cc..3614011 100644 --- a/src/components/FileSelector.tsx +++ b/src/components/Selectors.tsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; -const FileSelector = ({cb}: {cb: (file: File) => void}) => { - +export const FileSelector = ({ cb }: { cb: (file: File) => void }) => { + if (!cb) throw new Error('Missing callback'); const [file, setFile] = useState(null); @@ -35,4 +35,32 @@ const FileSelector = ({cb}: {cb: (file: File) => void}) => { ; }; -export default FileSelector; \ No newline at end of file +type DropdownProps = { + name?: string, + multi?: boolean, + selection?: [], + children: React.ReactNode +} + +export const DropdownMenu = (props: DropdownProps) => { + + return
+
+ +
+
+ {props.children} +
+
; + +}; + +export const ToggleSwitch = ({ value, onChange, ref, children }: + { value: boolean, ref?: React.RefObject, onChange?: React.ChangeEventHandler, children: string }) => { + return

+ + {children} + + +

; +}; \ No newline at end of file diff --git a/src/pages/Admin.tsx b/src/pages/Admin.tsx index 67a270f..ac98443 100644 --- a/src/pages/Admin.tsx +++ b/src/pages/Admin.tsx @@ -1,6 +1,6 @@ -import React, { useRef, useState } from "react"; +import React, { useState } from "react"; import { Route, Routes } from "react-router"; -import FileSelector from "../components/FileSelector"; +import { FileSelector } from "../components/Selectors"; import '../css/pages/Admin.css'; import ErrorBoundary from "../util/ErrorBoundary"; import Roles from "./admin/Roles"; diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 2fc33be..f9aff1e 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -57,7 +57,7 @@ const CredentialFields = () => {
- +
diff --git a/src/pages/admin/Roles.tsx b/src/pages/admin/Roles.tsx index cf88269..b623e0e 100644 --- a/src/pages/admin/Roles.tsx +++ b/src/pages/admin/Roles.tsx @@ -1,27 +1,18 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { Route, Routes, useNavigate, useParams } from "react-router"; import { BackButton, PageButtons } from "../../components/PageControls"; -import { Permissions } from "../../components/PermissionsView"; -import { RateLimits } from "../../components/RateLimitsView"; +import { Permissions } from "../../views/PermissionsView"; +import { RateLimits } from "../../views/RateLimitsView"; import { Table, TableListEntry } from "../../components/Table"; import ErrorBoundary from "../../util/ErrorBoundary"; -import { get, patch } from "../../util/Util"; +import { get, patch, post } from "../../util/Util"; import { Permissions as Perms, Role as R } from "../../@types/ApiStructures"; +import { ToggleSwitch } from "../../components/Selectors"; const Role = ({ role }: {role: R}) => { - const perms = { ...role.permissions }; - const updatePerms = (chain: string, raw: string) => { - const value = parseInt(raw); - if (isNaN(value)) return; - - let selected = perms; - const keys = chain.split(':'); - for (const key of keys) { - if (key === keys[keys.length - 1]) selected[key] = value; - else selected = selected[key] as Perms; - } - }; + // const perms = { ...role.permissions }; + const [perms, updatePerms] = useState(role.permissions); const commitPerms = async () => { await patch(`/api/roles/${role.id}`, perms); @@ -42,7 +33,11 @@ const Role = ({ role }: {role: R}) => {

Created: {new Date(role.createdTimestamp).toDateString()}

-

Disabled: {role.disabled.toString()}

+ {/*

Disabled: {role.disabled.toString()}

*/} + + + Disabled + @@ -50,8 +45,8 @@ const Role = ({ role }: {role: R}) => {
- - + +
@@ -62,6 +57,43 @@ const Role = ({ role }: {role: R}) => { ; }; +const CreateRoleField = ({ numRoles, className, addRole }: { numRoles: number, className?: string, addRole: (role: R) => void }) => { + + const [error, setError] = useState(null); + const nameRef = useRef(null); + const positionRef = useRef(null); + + const createRole: React.MouseEventHandler = async (event) => { + event.preventDefault(); + + if (!nameRef.current || !positionRef.current) return setError('Must supply name and position'); + const name = nameRef.current.value; + const position = parseInt(positionRef.current.value); + + const response = await post('/api/roles', { name, position }); + if (!response.success) return setError(response.message || 'Unknown error'); + addRole(response.data as R); + + }; + + return
+ +

Create Role

+ + {error &&

{error}

} +
+ + + + + + + +
+
; + +}; + const Roles = () => { const [error, setError] = useState(null); @@ -108,6 +140,9 @@ const Roles = () => { + + setRoles([...roles, role])} className='col-6-lg col-12' numRoles={roles.length} /> + ; }; diff --git a/src/pages/admin/Users.tsx b/src/pages/admin/Users.tsx index 785e4b1..825f2b1 100644 --- a/src/pages/admin/Users.tsx +++ b/src/pages/admin/Users.tsx @@ -5,10 +5,11 @@ import { get, post } from '../../util/Util'; import '../../css/pages/Users.css'; import { Table, TableListEntry } from "../../components/Table"; import { BackButton, PageButtons } from "../../components/PageControls"; -import { Permissions } from "../../components/PermissionsView"; -import { Application as App, Permissions as Perms, User as APIUser } from "../../@types/ApiStructures"; +import { Permissions } from "../../views/PermissionsView"; +import { Application as App, Permissions as Perms, User as APIUser, Role } from "../../@types/ApiStructures"; +import { DropdownMenu, ToggleSwitch } from "../../components/Selectors"; -const ApplicationList = ({ apps }: {apps: App[]}) => { +const ApplicationList = ({ apps }: { apps: App[] }) => { const navigate = useNavigate(); return @@ -24,12 +25,12 @@ const ApplicationList = ({ apps }: {apps: App[]}) => { }; -const Application = ({ app }: {app: App}) => { - - const descProps = {defaultValue: app.description || '', placeholder: 'Describe your application'}; +const Application = ({ app }: { app: App }) => { + + const descProps = { defaultValue: app.description || '', placeholder: 'Describe your application' }; return

{app.name} ({app.id})

- + Description