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:
parent
eb7d0ed84e
commit
cd8dfb14d0
7 changed files with 72 additions and 79 deletions
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
)
|
|
@ -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}
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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],
|
||||
|
|
32
frontend/src/contexts/cache.tsx
Normal file
32
frontend/src/contexts/cache.tsx
Normal 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}/>
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue