mirror of
https://github.com/Steffo99/sophon.git
synced 2024-12-22 23:04:21 +00:00
✨ Add group edit box
This commit is contained in:
parent
ee4d774d99
commit
029c3dee38
4 changed files with 81 additions and 39 deletions
|
@ -8,7 +8,7 @@
|
|||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||
"@fortawesome/react-fontawesome": "^0.1.15",
|
||||
"@reach/router": "^1.3.4",
|
||||
"@steffo/bluelib-react": "^4.0.4",
|
||||
"@steffo/bluelib-react": "^4.0.5",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
|
|
|
@ -57,6 +57,7 @@ function App({..._}: RouteComponentProps) {
|
|||
groupPk={selection.value.slug}
|
||||
unselectedRoute={({viewSet}) => <>
|
||||
<ProjectListBox viewSet={viewSet}/>
|
||||
<GroupCreateBox resource={selection}/>
|
||||
</>}
|
||||
selectedRoute={({selection}) => <>
|
||||
<NotebookRouter
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
import {Box, Details, Form, useFormState} from "@steffo/bluelib-react"
|
||||
import {Box, Details, Form, Idiomatic as I, useFormState} from "@steffo/bluelib-react"
|
||||
import * as React from "react"
|
||||
import {useAuthorizationContext} from "../../contexts/authorization"
|
||||
import {useCacheContext} from "../../contexts/cache"
|
||||
import {useInstanceContext} from "../../contexts/instance"
|
||||
import {ManagedViewSet} from "../../hooks/useManagedViewSet"
|
||||
import {ManagedResource, ManagedViewSet} from "../../hooks/useManagedViewSet"
|
||||
import {SophonResearchGroup} from "../../types/SophonTypes"
|
||||
import {ErrorBox} from "../errors/ErrorBox"
|
||||
|
||||
|
||||
export interface GroupCreateBoxProps {
|
||||
viewSet: ManagedViewSet<SophonResearchGroup>
|
||||
viewSet?: ManagedViewSet<SophonResearchGroup>,
|
||||
resource?: ManagedResource<SophonResearchGroup>,
|
||||
}
|
||||
|
||||
|
||||
export function GroupCreateBox({viewSet}: GroupCreateBoxProps): JSX.Element | null {
|
||||
export function GroupCreateBox({viewSet, resource}: GroupCreateBoxProps): JSX.Element | null {
|
||||
const instance = useInstanceContext()
|
||||
const authorization = useAuthorizationContext()
|
||||
const cache = useCacheContext()
|
||||
|
||||
const name =
|
||||
useFormState<string>("", val => val.length > 0 ? true : undefined)
|
||||
useFormState<string>(resource?.value.name ?? "", val => val.length > 0 ? true : undefined)
|
||||
|
||||
const description =
|
||||
useFormState<string>("", val => val.length > 0 ? true : undefined)
|
||||
useFormState<string>(resource?.value.description ?? "", val => val.length > 0 ? true : undefined)
|
||||
|
||||
const membersOptions: { [key: string]: number } | undefined =
|
||||
React.useMemo(
|
||||
|
@ -37,18 +37,28 @@ export function GroupCreateBox({viewSet}: GroupCreateBoxProps): JSX.Element | nu
|
|||
)
|
||||
|
||||
const members =
|
||||
useFormState<number[]>([], arr => arr.length > 0 ? true : undefined)
|
||||
useFormState<number[]>(resource?.value.members ?? [], arr => arr.length > 0 ? true : undefined)
|
||||
|
||||
const access =
|
||||
useFormState<"OPEN" | "MANUAL" | undefined>(undefined, val => (
|
||||
useFormState<"OPEN" | "MANUAL" | undefined>(resource?.value.access ?? undefined, val => (
|
||||
val?.length
|
||||
) ? true : undefined)
|
||||
|
||||
const slug = name.value.replaceAll(/[^A-Za-z0-9-]/g, "-").toLowerCase()
|
||||
|
||||
const doCreate =
|
||||
const onSubmit =
|
||||
React.useCallback(
|
||||
async () => {
|
||||
if(resource) {
|
||||
await resource.update({
|
||||
name: name.value,
|
||||
slug: slug,
|
||||
description: description.value,
|
||||
members: members.value,
|
||||
access: access.value,
|
||||
})
|
||||
}
|
||||
else if(viewSet) {
|
||||
await viewSet.create({
|
||||
name: name.value,
|
||||
slug: slug,
|
||||
|
@ -56,11 +66,36 @@ export function GroupCreateBox({viewSet}: GroupCreateBoxProps): JSX.Element | nu
|
|||
members: members.value,
|
||||
access: access.value,
|
||||
})
|
||||
}
|
||||
},
|
||||
[viewSet, name, slug, description, members, access],
|
||||
[viewSet, resource, name, slug, description, members, access],
|
||||
)
|
||||
|
||||
const canCreate =
|
||||
const trueMembers =
|
||||
React.useMemo(
|
||||
() => resource ? [...new Set([resource.value.owner, ...resource.value.members])] : undefined,
|
||||
[resource],
|
||||
)
|
||||
|
||||
const canEdit =
|
||||
React.useMemo(
|
||||
() => !resource ||
|
||||
(
|
||||
authorization && authorization.state.user && trueMembers?.includes(authorization.state.user.id)
|
||||
),
|
||||
[authorization, resource],
|
||||
)
|
||||
|
||||
const canAdministrate =
|
||||
React.useMemo(
|
||||
() => !resource ||
|
||||
(
|
||||
authorization && authorization.state.user && authorization.state.user.id === resource.value.owner
|
||||
),
|
||||
[authorization, resource],
|
||||
)
|
||||
|
||||
const canSubmit =
|
||||
React.useMemo(
|
||||
() => name.validity === true && access.validity === true && Boolean(authorization?.state.user?.username),
|
||||
[name, access, authorization],
|
||||
|
@ -69,22 +104,31 @@ export function GroupCreateBox({viewSet}: GroupCreateBoxProps): JSX.Element | nu
|
|||
if(!authorization?.state.token) {
|
||||
return null
|
||||
}
|
||||
if(!(
|
||||
viewSet || resource
|
||||
)) {
|
||||
return null
|
||||
}
|
||||
if(!canEdit) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Details>
|
||||
<Details.Summary>
|
||||
Create a new group
|
||||
{resource ? <>Edit <I>{resource.value.name}</I></> : "Create a new group"}
|
||||
</Details.Summary>
|
||||
<Details.Content>
|
||||
<Form>
|
||||
<Form.Field label={"Name"} required {...name}/>
|
||||
<Form.Field label={"Name"} required disabled={!canEdit} {...name}/>
|
||||
<Form.Field label={"Slug"} required disabled={true} value={slug} validity={slug.length > 0 ? true : undefined}/>
|
||||
<Form.Area label={"Description"} {...description}/>
|
||||
<Form.Multiselect label={"Members"} options={membersOptions ?? {}} {...members}/>
|
||||
<Form.Area label={"Description"} disabled={!canEdit} {...description}/>
|
||||
<Form.Multiselect label={"Members"} disabled={!canAdministrate} options={membersOptions ?? {}} {...members}/>
|
||||
<Form.Field label={"Owner"} required disabled={true} value={authorization?.state.user?.username} validity={Boolean(authorization?.state.user?.username)}/>
|
||||
<Form.Select
|
||||
label={"Access"}
|
||||
disabled={!canAdministrate}
|
||||
options={{
|
||||
"": undefined,
|
||||
"⛔️ Collaborators must be added manually": "MANUAL",
|
||||
|
@ -92,16 +136,13 @@ export function GroupCreateBox({viewSet}: GroupCreateBoxProps): JSX.Element | nu
|
|||
}}
|
||||
{...access}
|
||||
/>
|
||||
{
|
||||
viewSet.operationError ?
|
||||
<Form.Row>
|
||||
<ErrorBox error={viewSet.operationError ?? undefined}/>
|
||||
</Form.Row>
|
||||
: null
|
||||
}
|
||||
<Form.Row>
|
||||
<Form.Button type={"button"} onClick={doCreate} disabled={!canCreate}>
|
||||
Create
|
||||
<Form.Button
|
||||
type={"button"} onClick={onSubmit} disabled={!canSubmit} builtinColor={(
|
||||
viewSet?.operationError || resource?.error
|
||||
) ? "red" : undefined}
|
||||
>
|
||||
{resource ? "Edit" : "Create"}
|
||||
</Form.Button>
|
||||
</Form.Row>
|
||||
</Form>
|
||||
|
|
|
@ -1617,10 +1617,10 @@
|
|||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@steffo/bluelib-react@^4.0.4":
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@steffo/bluelib-react/-/bluelib-react-4.0.4.tgz#1a4f4ccd3ee185603a95b7a0a183a919f29e9d32"
|
||||
integrity sha512-ZwnAqbZ4LaYbQu56fMX0OIKBJA1X4LUfTIJsxnkJbPrr2qX0D+zQUl2vI2Jm/wlZdltvwm5ftCTLDwpqg/1h/g==
|
||||
"@steffo/bluelib-react@^4.0.5":
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@steffo/bluelib-react/-/bluelib-react-4.0.5.tgz#6128454b03fc1888c4e7f4dbb1675f71fba2153c"
|
||||
integrity sha512-W2TguaP5vixV0C1/chQ+SO69YydBMLWG+ml7TVgRIHoRtr3cKHpp8VVij8qxovdZ1dnkBMD9/z3skcdoRpToag==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.3"
|
||||
classnames "^2.3.1"
|
||||
|
|
Loading…
Reference in a new issue