role menu WIP

This commit is contained in:
Erik 2023-05-02 02:09:15 +03:00
parent 33c0e362f5
commit d6384af097
Signed by: Navy.gif
GPG Key ID: 2532FBBB61C65A68
4 changed files with 120 additions and 37 deletions

View File

@ -20,7 +20,7 @@
"react"
],
"rules": {
// "@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-var-requires":"off",
"react/no-unescaped-entities": "warn",
"react/prop-types": "off",

9
src/@types/Components.ts Normal file
View File

@ -0,0 +1,9 @@
export type DropdownBaseProps = {
children: React.ReactNode
}
export type DropdownItemProps = {
type?: 'select' | 'multi-select',
selected?: boolean,
onChange?: React.ReactEventHandler
} & DropdownBaseProps

View File

@ -1,4 +1,6 @@
import React, { useState } from "react";
import React, { Children, useRef, useState } from "react";
import ClickDetector from "../util/ClickDetector";
import { DropdownBaseProps, DropdownItemProps } from "../@types/Components";
export const FileSelector = ({ cb }: { cb: (file: File) => void }) => {
@ -35,32 +37,82 @@ export const FileSelector = ({ cb }: { cb: (file: File) => void }) => {
</label>;
};
type DropdownProps = {
name?: string,
multi?: boolean,
selection?: [],
children: React.ReactNode
}
export const DropdownMenu = (props: DropdownProps) => {
return <div>
<div>
</div>
<div>
{props.children}
</div>
</div>;
};
export const ToggleSwitch = ({ value, onChange, ref, children }:
{ value: boolean, ref?: React.RefObject<HTMLInputElement>, onChange?: React.ChangeEventHandler, children: string }) => {
return <p>
<span className="check-box check-box-row">
<b>{children}:</b>
<b>{children}</b>
<input ref={ref} defaultChecked={value} onChange={onChange} type='checkbox' />
</span>
</p>;
};
export const VerticalToggleSwitch = ({ value, onChange, ref, children }:
{ value: boolean, ref?: React.RefObject<HTMLInputElement>, onChange?: React.ChangeEventHandler, children: string }) => {
return <p>
<b>{children}</b>
<span className="check-box">
<input ref={ref} defaultChecked={value} onChange={onChange} type='checkbox' />
</span>
</p>;
};
const DropdownHeader = ({children}: DropdownBaseProps) => {
return <summary className='is-vertical-align'>
{children}
</summary>;
};
const DropdownItem = ({ children, type, selected, onChange }: DropdownItemProps) => {
if (type === 'multi-select')
return <ToggleSwitch value={selected || false} onChange={onChange}>
{children as string}
</ToggleSwitch>;
return <div>
{children}
</div>;
};
const DropdownItemList = ({ children }: DropdownBaseProps) => {
return <div className='card'>
{children}
</div>;
};
type DropdownProps = {
name?: string,
multi?: boolean,
selection?: [],
children: React.ReactNode[]
}
const DropdownComp = ({children, ...props}: DropdownProps) => {
console.log(props);
console.log(children);
if (!children)
throw new Error('Missing children');
if (!children.some(element => element && (element as React.ReactElement).type === DropdownHeader))
throw new Error('Missing a header');
const detailsRef = useRef<HTMLDetailsElement>(null);
return <ClickDetector callback={() => {
if(detailsRef.current) detailsRef.current.open = false;
}}>
<details ref={detailsRef} className='dropdown'>
{children}
</details>
</ClickDetector>;
};
const Dropdown = Object.assign(DropdownComp, {
Header: DropdownHeader,
ItemList: DropdownItemList,
Item: DropdownItem
});
export { Dropdown };

View File

@ -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 { DropdownMenu, ToggleSwitch } from "../../components/Selectors";
import { Dropdown, ToggleSwitch } from "../../components/Selectors";
const ApplicationList = ({ apps }: { apps: App[] }) => {
@ -38,16 +38,39 @@ const Application = ({ app }: { app: App }) => {
</div>;
};
const RoleComp = ({ role }: {role: Role}) => {
return <div className='role'>
{role.name}
</div>;
};
const Roles = ({ userRoles, roles }: { userRoles: Role[], roles: Role[] }) => {
console.log(roles);
return <DropdownMenu>
{roles.map(role => {
return <div key={role.id}>
<label>{role.name}</label>
<input defaultChecked={Boolean(userRoles.find((r: Role) => r.id === role.id))} type='checkbox' />
</div>;
})}
</DropdownMenu>;
console.log(roles, userRoles);
const roleSelected = (role: Role, selected: boolean) => {
console.log(role, selected);
};
return <Dropdown>
<Dropdown.Header>
{userRoles.map(role => <RoleComp key={role.id} role={role} />)}
</Dropdown.Header>
<Dropdown.ItemList>
{roles.map(role => <Dropdown.Item
type='multi-select' key={role.id}
selected={userRoles.some(r => r.id === role.id)}
onChange={(event) => {
const elem = event.target as HTMLInputElement;
roleSelected(role, elem.checked);
}}
>
{role.name}
</Dropdown.Item>)}
</Dropdown.ItemList>
</Dropdown>;
};
const User = ({ user, roles }: { user: APIUser, roles: Role[] }) => {
@ -99,10 +122,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>