frontend/src/grain/CustomGrainSelector.tsx

155 lines
No EOL
4.8 KiB
TypeScript

import { ExpandMore } from "@mui/icons-material"
import { Accordion, AccordionDetails, AccordionSummary, Box, Button, Typography } from "@mui/material"
import SearchSelect, { Option } from "common/SearchSelect"
import { pond } from "protobuf-ts/pond"
import { useGlobalState } from "providers"
import { useGrainAPI } from "providers/pond/grainAPI"
import React, { useEffect, useState } from "react"
import CustomGrainForm from "./CustomGrainForm"
interface Props {
initialGrain?: pond.GrainSettings
onGrainSettingsChange: (settings: pond.GrainSettings) => void
}
export default function CustomGrainSelector(props: Props) {
const {initialGrain, onGrainSettingsChange} = props
const grainAPI = useGrainAPI()
const [{as}] = useGlobalState()
const [newGrainSettings, setNewGrainSettings] = useState(initialGrain ?? pond.GrainSettings.create())
const [formValid, setFormValid] = useState(true)
const [grainMap, setGrainMap] = useState<Map<string, pond.GrainObject>>(
initialGrain ?
new Map([
["Active", pond.GrainObject.create({key: "Active", name: initialGrain.name, settings: initialGrain})]
])
:
new Map())
const [grainOptions, setGrainOptions] = useState<Option[]>(
initialGrain ?
[
{
label: initialGrain.name,
value: "Active",
group: "Active"
}
]
:
[]
)
const [isNew, setIsNew] = useState(false)
const [selectedOption, setSelectedOption] = useState<Option | null>(initialGrain ? {
label: initialGrain.name,
value: "Active",
group: "Active"
} : null)
useEffect(()=>{
grainAPI.listGrains(0, 0, "asc", "name", undefined, undefined, undefined, as).then(resp => {
let options: Option[] = grainOptions
let map: Map<string, pond.GrainObject> = grainMap
if (resp.data.grains){
resp.data.grains.forEach(grain => {
map.set(grain.key, grain)
options.push({
label: grain.name,
value: grain.key,
group: grain.settings?.group,
})
})
}
setGrainOptions([...options])
setGrainMap(map)
})
},[grainAPI])
const saveGrain = () => {
// console.log(newGrainSettings)
grainAPI.addGrain(newGrainSettings, as).then(resp => {
console.log("grain added")
}).catch(err => {
console.log("err")
})
}
const settingsChanged = (newSettings: pond.GrainSettings, formValid: boolean) => {
setNewGrainSettings(newSettings)
setIsNew(true)
setFormValid(formValid)
onGrainSettingsChange(newSettings)
}
const grainAccordion = () => {
return (
<Accordion>
<AccordionSummary expandIcon={<ExpandMore />}>Custom Grain Properties</AccordionSummary>
<AccordionDetails>
<CustomGrainForm grainSettings={newGrainSettings} onGrainSettingsChange={settingsChanged}/>
{isNew &&
<Box display='flex' justifyContent="flex-end">
<Button
variant="contained"
disabled={!formValid}
onClick={() => {
setIsNew(false)
saveGrain()
}}
color="primary">
Save Custom Grain
</Button>
</Box>
}
</AccordionDetails>
</Accordion>
)
}
return (
<React.Fragment>
{grainOptions.length === 0 ?
<Box>
<Typography sx={{marginBottom: 1}}>Custom Grain Properties</Typography>
<CustomGrainForm grainSettings={newGrainSettings} onGrainSettingsChange={settingsChanged}/>
{isNew &&
<Box display='flex' justifyContent="flex-end">
<Button
variant="contained"
disabled={!formValid}
onClick={() => {
setIsNew(false)
}}
color="primary">
Save Custom Grain
</Button>
</Box>
}
</Box>
:
<Box>
<Box sx={{marginBottom: 2}}>
<SearchSelect
label="My Grains"
selected={selectedOption}
changeSelection={option => {
setIsNew(false)
setSelectedOption(option)
//when an option is selected set all of the state variables controlling the form entries
let grain = grainMap.get(option?.value)
if(grain && grain.settings){
//the the new grain settings object
setNewGrainSettings(grain.settings)
//pass that settings object back up
settingsChanged(grain.settings, true)
}
}}
group
options={grainOptions}
/>
</Box>
{grainAccordion()}
</Box>
}
</React.Fragment>
)
}