Role selector WIP
flags page WIP
This commit is contained in:
parent
953366d394
commit
6476a205a4
@ -52,4 +52,16 @@ export type Application = {
|
||||
export type Role = {
|
||||
position: number,
|
||||
rateLimits: RateLimits
|
||||
} & APIEntity
|
||||
} & APIEntity
|
||||
|
||||
type FlagType = string | number | boolean | number[] | null
|
||||
type FlagEnv = 'test' | 'prod'
|
||||
type FlagConsumer = 'client' | 'server' | 'api'
|
||||
|
||||
export type Flag = {
|
||||
id: string,
|
||||
name: string,
|
||||
env: FlagEnv,
|
||||
consumer: FlagConsumer,
|
||||
value: FlagType
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
export type DropdownBaseProps = {
|
||||
children: React.ReactNode
|
||||
children: React.ReactNode,
|
||||
className?: string
|
||||
}
|
||||
|
||||
export type DropdownItemProps = {
|
||||
|
@ -49,7 +49,8 @@ function App() {
|
||||
{
|
||||
to: '/admin', label: 'Admin', items: [
|
||||
{ to: '/users', label: 'Users', relative: true },
|
||||
{ to: '/roles', label: 'Roles', relative: true }
|
||||
{ to: '/roles', label: 'Roles', relative: true },
|
||||
{ to: '/flags', label: 'Flags', relative: true }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Children, useRef, useState } from "react";
|
||||
import ClickDetector from "../util/ClickDetector";
|
||||
import { DropdownBaseProps, DropdownItemProps } from "../@types/Components";
|
||||
import '../css/components/Selectors.css';
|
||||
import '../css/components/InputElements.css';
|
||||
|
||||
export const FileSelector = ({ cb }: { cb: (file: File) => void }) => {
|
||||
|
||||
@ -62,8 +62,12 @@ export const VerticalToggleSwitch = ({ value, onChange, ref, children }:
|
||||
</p>;
|
||||
};
|
||||
|
||||
const DropdownHeader = ({ children }: DropdownBaseProps) => {
|
||||
return <summary className='card is-vertical-align dropdown-header'>
|
||||
export const NumberInput = () => {
|
||||
//
|
||||
};
|
||||
|
||||
const DropdownHeader = ({ children, className = '' }: DropdownBaseProps) => {
|
||||
return <summary className={`card is-vertical-align dropdown-header p-2 ${className}`}>
|
||||
{children}
|
||||
</summary>;
|
||||
};
|
||||
@ -83,7 +87,7 @@ const DropdownItem = ({ children, type, selected, onClick }: DropdownItemProps)
|
||||
};
|
||||
|
||||
const DropdownItemList = ({ children }: DropdownBaseProps) => {
|
||||
return <div className='card'>
|
||||
return <div className='card w-100 '>
|
||||
{children}
|
||||
</div>;
|
||||
};
|
||||
@ -92,10 +96,11 @@ type DropdownProps = {
|
||||
name?: string,
|
||||
multi?: boolean,
|
||||
selection?: [],
|
||||
children: React.ReactNode[]
|
||||
children: React.ReactNode[],
|
||||
className?: string
|
||||
}
|
||||
|
||||
const DropdownComp = ({ children }: DropdownProps) => {
|
||||
const DropdownComp = ({ children, className = '' }: DropdownProps) => {
|
||||
|
||||
if (!children)
|
||||
throw new Error('Missing children');
|
||||
@ -108,7 +113,7 @@ const DropdownComp = ({ children }: DropdownProps) => {
|
||||
return <ClickDetector callback={() => {
|
||||
if (detailsRef.current) detailsRef.current.open = false;
|
||||
}}>
|
||||
<details ref={detailsRef} className='dropdown'>
|
||||
<details ref={detailsRef} className={`dropdown w-100 ${className}`}>
|
||||
{children}
|
||||
</details>
|
||||
</ClickDetector>;
|
1200
src/css/chota.min.css
vendored
1200
src/css/chota.min.css
vendored
File diff suppressed because one or more lines are too long
3
src/css/components/InputElements.css
Normal file
3
src/css/components/InputElements.css
Normal file
@ -0,0 +1,3 @@
|
||||
.role-selector {
|
||||
background-color: white;
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
import React, { useState } from "react";
|
||||
import { Route, Routes } from "react-router";
|
||||
import { FileSelector } from "../components/Selectors";
|
||||
import { FileSelector } from "../components/InputElements";
|
||||
import '../css/pages/Admin.css';
|
||||
import ErrorBoundary from "../util/ErrorBoundary";
|
||||
import Roles from "./admin/Roles";
|
||||
import Users from "./admin/Users";
|
||||
import Flags from "./admin/Flags";
|
||||
|
||||
|
||||
const Main = () => {
|
||||
@ -42,6 +43,7 @@ const Admin = () => {
|
||||
<Route path="/" element={<Main />} />
|
||||
<Route path="/users/*" element={<Users />} />
|
||||
<Route path='/roles/*' element={<Roles />} />
|
||||
<Route path='/flags/*' element={<Flags />} />
|
||||
</Routes>
|
||||
</ErrorBoundary>;
|
||||
};
|
||||
|
69
src/pages/admin/Flags.tsx
Normal file
69
src/pages/admin/Flags.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Flag as APIFlag } from "../../@types/ApiStructures";
|
||||
import { get } from "../../util/Util";
|
||||
import { ToggleSwitch } from "../../components/InputElements";
|
||||
|
||||
const inputTypes = {
|
||||
boolean: ToggleSwitch
|
||||
|
||||
};
|
||||
|
||||
const Flag = ({ flag }: { flag: APIFlag }) => {
|
||||
|
||||
return <div className='flag card'>
|
||||
<p><b>Name:</b> {flag.name}</p>
|
||||
<p><b>ID:</b> {flag.id}</p>
|
||||
<p><b>Environment:</b> {flag.env}</p>
|
||||
<p><b>Consumer:</b> {flag.consumer}</p>
|
||||
<label><b>Value:</b> <input /></label>
|
||||
</div>;
|
||||
|
||||
};
|
||||
|
||||
const FlagList = ({ flags, error }: { flags: APIFlag[], error: string | null }) => {
|
||||
|
||||
console.log(flags);
|
||||
return <div className='col-6-lg col-12'>
|
||||
<h4>Flags</h4>
|
||||
{error && <p>{error}</p>}
|
||||
|
||||
{flags.map(flag => <Flag key={flag.id} flag={flag} />)}
|
||||
|
||||
</div>;
|
||||
|
||||
};
|
||||
|
||||
const CreateFlag = () => {
|
||||
return <div className='col-6-lg col-12'>
|
||||
<h4>Create Flag</h4>
|
||||
|
||||
<div className='card'>
|
||||
|
||||
</div>
|
||||
</div>;
|
||||
};
|
||||
|
||||
const Flags = () => {
|
||||
|
||||
const [flags, setFlags] = useState<APIFlag[]>([]);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const response = await get('/api/flags');
|
||||
if (!response.success) return setError(response.message as string);
|
||||
setFlags(response.data as APIFlag[]);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return <div className='row'>
|
||||
|
||||
<FlagList flags={flags} error={error} />
|
||||
|
||||
<CreateFlag />
|
||||
|
||||
</div>;
|
||||
|
||||
};
|
||||
|
||||
export default Flags;
|
@ -7,7 +7,7 @@ import { Table, TableListEntry } from "../../components/Table";
|
||||
import ErrorBoundary from "../../util/ErrorBoundary";
|
||||
import { get, patch, post } from "../../util/Util";
|
||||
import { Permissions as Perms, Role as R } from "../../@types/ApiStructures";
|
||||
import { ToggleSwitch } from "../../components/Selectors";
|
||||
import { ToggleSwitch } from "../../components/InputElements";
|
||||
|
||||
const Role = ({ role }: {role: R}) => {
|
||||
|
||||
|
@ -7,7 +7,7 @@ import { Table, TableListEntry } from "../../components/Table";
|
||||
import { BackButton, PageButtons } from "../../components/PageControls";
|
||||
import { Permissions } from "../../views/PermissionsView";
|
||||
import { Application as App, Permissions as Perms, User as APIUser, Role } from "../../@types/ApiStructures";
|
||||
import { Dropdown, ToggleSwitch } from "../../components/Selectors";
|
||||
import { Dropdown, ToggleSwitch } from "../../components/InputElements";
|
||||
|
||||
type PartialUser = {
|
||||
apps: App[]
|
||||
@ -78,7 +78,7 @@ const Application = ({ app }: { app: App }) => {
|
||||
};
|
||||
|
||||
const RoleComp = ({ role, onClick }: { role: Role, onClick: React.ReactEventHandler }) => {
|
||||
return <div className='role card' >
|
||||
return <div className='role card p-3' >
|
||||
{role.name} <span className="clickable" onClick={onClick}>X</span>
|
||||
</div>;
|
||||
};
|
||||
@ -98,7 +98,7 @@ const Roles = ({ userRoles, roles }: { userRoles: Role[], roles: Role[] }) => {
|
||||
};
|
||||
return <Dropdown>
|
||||
|
||||
<Dropdown.Header>
|
||||
<Dropdown.Header className='role-selector'>
|
||||
{equippedRoles.map(role => <RoleComp key={role.id} role={role} onClick={() => {
|
||||
roleDeselected(role);
|
||||
}} />)}
|
||||
@ -167,9 +167,9 @@ const User = ({ user, roles }: { user: APIUser, roles: Role[] }) => {
|
||||
<label>Roles</label>
|
||||
<Roles userRoles={user.roles} roles={roles} />
|
||||
|
||||
<button className="button primary">
|
||||
{/* <button className="button primary">
|
||||
Save User
|
||||
</button>
|
||||
</button> */}
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import { capitalise, get, post } from "../../util/Util";
|
||||
import { useLoginContext } from "../../structures/UserContext";
|
||||
import { FileSelector } from "../../components/Selectors";
|
||||
import { FileSelector } from "../../components/InputElements";
|
||||
import { ExternalProfile as EP, User } from "../../@types/ApiStructures";
|
||||
|
||||
const TwoFactorControls = ({ user }: {user: User}) => {
|
||||
|
Loading…
Reference in New Issue
Block a user