mirror of
https://github.com/Steffo99/sophon.git
synced 2024-12-22 14:54:22 +00:00
✨ Create GroupListBox
This commit is contained in:
parent
a765681c3f
commit
a7eb7a78b4
4 changed files with 141 additions and 2 deletions
|
@ -6,6 +6,7 @@ import {AuthorizationRouter} from "./components/authorization/AuthorizationRoute
|
||||||
import {AuthorizationStepPage} from "./components/authorization/AuthorizationStepPage"
|
import {AuthorizationStepPage} from "./components/authorization/AuthorizationStepPage"
|
||||||
import {SophonFooter} from "./components/elements/SophonFooter"
|
import {SophonFooter} from "./components/elements/SophonFooter"
|
||||||
import {ErrorCatcherBox} from "./components/errors/ErrorCatcherBox"
|
import {ErrorCatcherBox} from "./components/errors/ErrorCatcherBox"
|
||||||
|
import {GroupListBox} from "./components/group/GroupListBox"
|
||||||
import {GroupRouter} from "./components/group/GroupRouter"
|
import {GroupRouter} from "./components/group/GroupRouter"
|
||||||
import {InstanceRouter} from "./components/instance/InstanceRouter"
|
import {InstanceRouter} from "./components/instance/InstanceRouter"
|
||||||
import {InstanceStepPage} from "./components/instance/InstanceStepPage"
|
import {InstanceStepPage} from "./components/instance/InstanceStepPage"
|
||||||
|
@ -17,7 +18,7 @@ import {InstanceProvider} from "./contexts/instance"
|
||||||
import {ThemeProvider} from "./contexts/theme"
|
import {ThemeProvider} from "./contexts/theme"
|
||||||
|
|
||||||
|
|
||||||
function App({...props}: RouteComponentProps) {
|
function App({}: RouteComponentProps) {
|
||||||
return (
|
return (
|
||||||
<InstanceProvider>
|
<InstanceProvider>
|
||||||
<InstanceRouter
|
<InstanceRouter
|
||||||
|
@ -32,7 +33,7 @@ function App({...props}: RouteComponentProps) {
|
||||||
</>}
|
</>}
|
||||||
selectedRoute={() => <>
|
selectedRoute={() => <>
|
||||||
<GroupRouter
|
<GroupRouter
|
||||||
unselectedRoute={DebugBox}
|
unselectedRoute={(props) => <GroupListBox {...props}/>}
|
||||||
selectedRoute={DebugBox}
|
selectedRoute={DebugBox}
|
||||||
/>
|
/>
|
||||||
</>}
|
</>}
|
||||||
|
|
22
frontend/src/components/group/GroupListBox.tsx
Normal file
22
frontend/src/components/group/GroupListBox.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import {Box, Heading} from "@steffo/bluelib-react"
|
||||||
|
import * as React from "react"
|
||||||
|
import {SophonResearchGroup} from "../../types/SophonTypes"
|
||||||
|
import {ListRouteProps} from "../routing/ViewSetRouter"
|
||||||
|
import {GroupResourcePanel} from "./GroupResourcePanel"
|
||||||
|
|
||||||
|
|
||||||
|
export interface GroupListBoxProps extends ListRouteProps<SophonResearchGroup> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function GroupListBox({viewSet}: GroupListBoxProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Heading level={3}>
|
||||||
|
Research groups
|
||||||
|
</Heading>
|
||||||
|
{viewSet.resources?.map(res => <GroupResourcePanel resource={res} key={res.value.slug}/>)}
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
37
frontend/src/components/group/GroupResourcePanel.tsx
Normal file
37
frontend/src/components/group/GroupResourcePanel.tsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import {faEnvelope, faGlobe} from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
||||||
|
import * as React from "react"
|
||||||
|
import {ManagedResource} from "../../hooks/useManagedViewSet"
|
||||||
|
import {SophonResearchGroup} from "../../types/SophonTypes"
|
||||||
|
import {Link} from "../elements/Link"
|
||||||
|
import {ResourcePanel} from "../elements/ResourcePanel"
|
||||||
|
|
||||||
|
|
||||||
|
export interface GroupResourcePanelProps {
|
||||||
|
resource: ManagedResource<SophonResearchGroup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function GroupResourcePanel({resource}: GroupResourcePanelProps): JSX.Element {
|
||||||
|
const icon = resource.value.access === "OPEN" ? faGlobe : faEnvelope
|
||||||
|
const members = resource.value.members.length
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ResourcePanel>
|
||||||
|
<ResourcePanel.Icon>
|
||||||
|
<FontAwesomeIcon icon={icon}/>
|
||||||
|
</ResourcePanel.Icon>
|
||||||
|
<ResourcePanel.Name>
|
||||||
|
<Link href={`g/${resource.value.slug}/`}>
|
||||||
|
{resource.value.name}
|
||||||
|
</Link>
|
||||||
|
</ResourcePanel.Name>
|
||||||
|
<ResourcePanel.Text>
|
||||||
|
{members} member{members !== 1 ? "s" : ""}
|
||||||
|
</ResourcePanel.Text>
|
||||||
|
<ResourcePanel.Buttons>
|
||||||
|
|
||||||
|
</ResourcePanel.Buttons>
|
||||||
|
</ResourcePanel>
|
||||||
|
)
|
||||||
|
}
|
79
frontend/src/contexts/group.tsx
Normal file
79
frontend/src/contexts/group.tsx
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import * as React from "react"
|
||||||
|
import {ContextData} from "../types/ContextTypes"
|
||||||
|
import {WithChildren} from "../types/ExtraTypes"
|
||||||
|
|
||||||
|
// States
|
||||||
|
|
||||||
|
type GroupSelected = {
|
||||||
|
bluelib: "sophon" | "royalblue" | "hacker" | "paper",
|
||||||
|
title: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
|
||||||
|
type GroupSet = {
|
||||||
|
type: "set",
|
||||||
|
bluelib: "sophon" | "royalblue" | "hacker" | "paper",
|
||||||
|
title: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
type GroupReset = {
|
||||||
|
type: "reset",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Composition
|
||||||
|
|
||||||
|
export type GroupState = GroupSelected
|
||||||
|
type GroupAction = GroupSet | GroupReset
|
||||||
|
export type GroupContextData = ContextData<GroupState, GroupAction> | undefined
|
||||||
|
|
||||||
|
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
const groupDefaultState: GroupState = {
|
||||||
|
bluelib: "sophon",
|
||||||
|
title: "Sophon",
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupReducer: React.Reducer<GroupState, GroupAction> = (prevState, action) => {
|
||||||
|
switch(action.type) {
|
||||||
|
case "set":
|
||||||
|
// Bail out if trying to set to the same state as earlier
|
||||||
|
if(prevState.bluelib === action.bluelib && prevState.title === action.title) {
|
||||||
|
return prevState
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
bluelib: action.bluelib,
|
||||||
|
title: action.title,
|
||||||
|
}
|
||||||
|
case "reset":
|
||||||
|
return groupDefaultState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupContext = React.createContext<GroupContextData>(undefined)
|
||||||
|
const GroupContext = groupContext
|
||||||
|
|
||||||
|
|
||||||
|
// Hooks
|
||||||
|
|
||||||
|
export function useGroupReducer(): GroupContextData {
|
||||||
|
const [state, dispatch] = React.useReducer(groupReducer, groupDefaultState)
|
||||||
|
return {state, dispatch}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useGroupContext(): GroupContextData {
|
||||||
|
return React.useContext(groupContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Components
|
||||||
|
|
||||||
|
export function GroupProvider({children}: WithChildren): JSX.Element {
|
||||||
|
const reducer = useGroupReducer()
|
||||||
|
|
||||||
|
return <GroupContext.Provider value={reducer} children={children}/>
|
||||||
|
}
|
Loading…
Reference in a new issue