1
Fork 0
mirror of https://github.com/Steffo99/sophon.git synced 2024-12-22 14:54:22 +00:00

🔧 Move users list to its own context

This commit is contained in:
Steffo 2021-10-12 04:12:17 +02:00
parent eb7d0ed84e
commit cd8dfb14d0
7 changed files with 72 additions and 79 deletions

View file

@ -21,6 +21,7 @@ import {ProjectRouter} from "./components/project/ProjectRouter"
import {ThemedBluelib} from "./components/theme/ThemedBluelib"
import {ThemedTitle} from "./components/theme/ThemedTitle"
import {AuthorizationProvider} from "./contexts/authorization"
import {CacheProvider} from "./contexts/cache"
import {InstanceProvider} from "./contexts/instance"
import {ThemeProvider} from "./contexts/theme"
@ -40,26 +41,28 @@ function App({..._}: RouteComponentProps) {
<AuthorizationStepPage/>
</>}
selectedRoute={() => <>
<GroupRouter
unselectedRoute={({viewSet}) => <>
<GroupListBox viewSet={viewSet}/>
<GroupCreateBox viewSet={viewSet}/>
</>}
selectedRoute={({selection}) => <>
<GroupDescriptionBox resource={selection}/>
<ProjectRouter
groupPk={selection.value.slug}
unselectedRoute={({viewSet}) => <ProjectListBox viewSet={viewSet}/>}
selectedRoute={({selection}) => <>
<NotebookRouter
projectPk={selection.value.slug}
unselectedRoute={({viewSet}) => <NotebookListBox viewSet={viewSet}/>}
selectedRoute={DebugBox}
/>
</>}
/>
</>}
/>
<CacheProvider>
<GroupRouter
unselectedRoute={({viewSet}) => <>
<GroupListBox viewSet={viewSet}/>
<GroupCreateBox viewSet={viewSet}/>
</>}
selectedRoute={({selection}) => <>
<GroupDescriptionBox resource={selection}/>
<ProjectRouter
groupPk={selection.value.slug}
unselectedRoute={({viewSet}) => <ProjectListBox viewSet={viewSet}/>}
selectedRoute={({selection}) => <>
<NotebookRouter
projectPk={selection.value.slug}
unselectedRoute={({viewSet}) => <NotebookListBox viewSet={viewSet}/>}
selectedRoute={DebugBox}
/>
</>}
/>
</>}
/>
</CacheProvider>
</>}
/>
</AuthorizationProvider>

View file

@ -1,15 +1,18 @@
import {Box, BringAttention as B, Heading, ListUnordered as UL} from "@steffo/bluelib-react"
import * as React from "react"
import {useInstanceContext} from "../../contexts/instance"
import {useCacheContext} from "../../contexts/cache"
export function InstanceStatsBox(): JSX.Element | null {
const instance = useInstanceContext()
export function CacheStatsBox(): JSX.Element | null {
const cache = useCacheContext()
if(!instance) {
if(!cache) {
return null
}
if(!instance.state.users) {
if(!cache.users) {
return null
}
if(!cache.users.resources) {
return null
}
@ -19,7 +22,7 @@ export function InstanceStatsBox(): JSX.Element | null {
Instance stats
</Heading>
<UL>
<UL.Item>This instance has <B>{instance.state.users.length}</B> registered users.</UL.Item>
<UL.Item>This instance has <B>{cache.users.resources.length}</B> registered users.</UL.Item>
</UL>
</Box>
)

View file

@ -1,6 +1,7 @@
import {Box, Details, Form, 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 {SophonResearchGroup} from "../../types/SophonTypes"
@ -15,6 +16,7 @@ export interface GroupCreateBoxProps {
export function GroupCreateBox({viewSet}: GroupCreateBoxProps): JSX.Element | null {
const instance = useInstanceContext()
const authorization = useAuthorizationContext()
const cache = useCacheContext()
const name =
useFormState<string>("", val => val.length > 0 ? true : undefined)
@ -24,9 +26,9 @@ export function GroupCreateBox({viewSet}: GroupCreateBoxProps): JSX.Element | nu
const membersOptions: { [key: string]: number } | undefined =
React.useMemo(
() => instance?.state?.users?.filter(m => m.id !== authorization?.state.user?.id).map(m => {
() => cache.users?.resources?.filter(m => m.value.id !== authorization?.state.user?.id).map(m => {
const obj: { [key: string]: number } = {}
obj[m.username] = m.id
obj[m.value.username] = m.value.id
return obj
}).reduce((a, b) => {
return {...a, ...b}

View file

@ -1,12 +1,11 @@
import {navigate} from "@reach/router"
import {Box, Form, Heading, useFormState} from "@steffo/bluelib-react"
import {Validator} from "@steffo/bluelib-react/dist/types"
import Axios, {AxiosResponse} from "axios-lab"
import Axios from "axios-lab"
import * as React from "react"
import {CHECK_TIMEOUT_MS} from "../../constants"
import {useInstanceContext} from "../../contexts/instance"
import {DjangoPage} from "../../types/DjangoTypes"
import {SophonInstanceDetails, SophonUser} from "../../types/SophonTypes"
import {SophonInstanceDetails} from "../../types/SophonTypes"
import {InstanceEncoder} from "../../utils/InstanceEncoder"
@ -70,31 +69,11 @@ export function InstanceFormBox(): JSX.Element {
return null
}
// Try to get the user data from the backend
// FIXME: This won't work if Django returns multiple pages, but it is insignificant right now, as we won't ever have >500 users
let users: AxiosResponse<DjangoPage<SophonUser>>
try {
users = await Axios.get<DjangoPage<SophonUser>>("/api/core/users/", {baseURL: url.toString(), signal})
}
catch(e) {
if(signal.aborted) {
return
}
else {
throw e
}
}
if(signal.aborted) {
return
}
// If the response is successful, update the info about the current instance
instance.dispatch({
type: "select",
url: url,
details: response.data,
users: users.data.results,
})
// Success!

View file

@ -3,8 +3,7 @@ import * as React from "react"
import {useInstanceContext} from "../../contexts/instance"
import {useAbortEffect} from "../../hooks/useAbortEffect"
import {useSophonPath} from "../../hooks/useSophonPath"
import {DjangoPage} from "../../types/DjangoTypes"
import {SophonInstanceDetails, SophonUser} from "../../types/SophonTypes"
import {SophonInstanceDetails} from "../../types/SophonTypes"
import {InstanceEncoder} from "../../utils/InstanceEncoder"
@ -54,31 +53,11 @@ export function useInstanceLoader() {
return
}
// Try to get the user data from the backend
// FIXME: This won't work if Django returns multiple pages, but it is insignificant right now, as we won't ever have >500 users
let users: AxiosResponse<DjangoPage<SophonUser>>
try {
users = await Axios.get<DjangoPage<SophonUser>>("/api/core/users/", {baseURL: url.toString(), signal})
}
catch(e) {
if(signal.aborted) {
return
}
else {
throw e
}
}
if(signal.aborted) {
return
}
// If the response is successful, update the info about the current instance
instance.dispatch({
type: "select",
url: url,
details: response.data,
users: users.data.results,
})
},
[instance, path],

View file

@ -0,0 +1,32 @@
import * as React from "react"
import {ManagedViewSet, useManagedViewSet} from "../hooks/useManagedViewSet"
import {WithChildren} from "../types/ExtraTypes"
import {SophonUser} from "../types/SophonTypes"
// States
type Cache = {
users?: ManagedViewSet<SophonUser>,
}
// Actions
const cacheContext = React.createContext<Cache>({})
const CacheContext = cacheContext
// Hooks
export function useCacheContext(): Cache {
return React.useContext(cacheContext)
}
// Components
export function CacheProvider({children}: WithChildren): JSX.Element {
const users = useManagedViewSet<SophonUser>("/api/core/users/", "id")
return <CacheContext.Provider value={{users}} children={children}/>
}

View file

@ -1,20 +1,18 @@
import * as React from "react"
import {ContextData} from "../types/ContextTypes"
import {WithChildren} from "../types/ExtraTypes"
import {SophonInstanceDetails, SophonUser} from "../types/SophonTypes"
import {SophonInstanceDetails} from "../types/SophonTypes"
// States
type InstanceNotSelected = {
url: undefined,
details: undefined,
users: undefined,
}
type InstanceSelected = {
url: URL,
details: SophonInstanceDetails,
users: SophonUser[],
}
@ -24,7 +22,6 @@ type InstanceSelect = {
type: "select",
url: URL,
details: SophonInstanceDetails,
users: SophonUser[],
}
type InstanceDeselect = {
@ -44,7 +41,6 @@ export type InstanceContextData = ContextData<InstanceState, InstanceAction> | u
const instanceDefaultState: InstanceState = {
url: undefined,
details: undefined,
users: undefined,
}
const instanceReducer: React.Reducer<InstanceState, InstanceAction> = (prevState, action) => {
@ -58,7 +54,6 @@ const instanceReducer: React.Reducer<InstanceState, InstanceAction> = (prevState
return {
url: action.url,
details: action.details,
users: action.users,
}
case "deselect":
// Bail out if no instance is currently selected