defined device change data, and started working on storage

This commit is contained in:
csawatzky 2026-07-08 10:57:23 -06:00
parent bced38d454
commit 7e6b41273b
7 changed files with 118 additions and 66 deletions

View file

@ -60,14 +60,6 @@ export default function bin3dVisualizer(props: Props){
setBinMode(bin.settings.mode)
},[bin])
const updateBin = (newMode: pond.BinMode) => {
if(updateBinCallback){
let clone = cloneDeep(bin)
clone.settings.mode = newMode
updateBinCallback(clone)
}
};
const binModeControl = () => {
return (
<Box>
@ -374,9 +366,6 @@ export default function bin3dVisualizer(props: Props){
componentMap={componentMap}
newMode={newMode}
open={openModeChange}
updateMode={(newMode) => {
updateBin(newMode)
}}
onClose={()=>{setOpenModeChange(false)}}
/>
<Box position={"relative"} height={600}>

View file

@ -1,15 +1,23 @@
import { Box, Button, DialogActions, DialogContent, DialogTitle, Typography } from "@mui/material";
import { Box, Button, DialogActions, DialogContent, DialogTitle } from "@mui/material";
import ResponsiveDialog from "common/ResponsiveDialog";
import { Bin, Component, Device, Interaction } from "models";
import { pond } from "protobuf-ts/pond";
import React, { useEffect, useState } from "react";
import StorageMode from "./StorageMode";
import DryingMode, { DryingBaseStepCount } from "./DryingMode";
import DryingMode from "./DryingMode";
import HydratingMode from "./HydratingMode";
import CooldownMode from "./CooldownMode";
import { PromiseProgress, Stage, Step } from "common/PromiseProgress";
import { useComponentAPI, useInteractionsAPI } from "providers";
import { useBinAPI, useComponentAPI, useInteractionsAPI } from "providers";
import { ComponentSet } from "bin/conditioning/pickComponentSet";
import { cloneDeep } from "lodash";
export interface DeviceChangeData {
deviceId: number
toRemove: Interaction[]
toAdd?: pond.MultiInteractionSettings
componentSets: ComponentSet[]
}
interface Props {
newMode: pond.BinMode //used to control which dialog to open
@ -20,16 +28,17 @@ interface Props {
devices: Device[]
componentDevices: Map<string, number>
componentMap: Map<string, Component>
updateMode: (newMode: pond.BinMode) => void
modeUpdated?: (mode: pond.BinMode) => void
}
export default function BinModeController(props: Props) {
const {open, onClose, newMode, updateMode, devices, componentDevices, componentMap, binPrefs, bin} = props
const {open, onClose, newMode, devices, componentDevices, componentMap, binPrefs, bin, modeUpdated} = props
const [showProgress, setShowProgress] = useState(false)
const [deviceComponents, setDeviceComponents] = useState<Map<number, Component[]>>(new Map())
const [promiseStages, setPromiseStages] = useState<Stage[]>([])
const interactionAPI = useInteractionsAPI()
const componentAPI = useComponentAPI()
const binAPI = useBinAPI();
//the use effects for the initial setup of what will be needed
useEffect(()=>{
@ -59,55 +68,79 @@ export default function BinModeController(props: Props) {
onClose()
}
const buildStages = (conflictingInteractions: Interaction[], deviceId: number, newInteractions: pond.MultiInteractionSettings, componentSets: ComponentSet[]) => {
const buildStages = (deviceData: DeviceChangeData[]) => {
//build the stages to pass into the PromiseProgress
//stage one is to remove conflicting interactions
let stages: Stage[] = []
let stage1: Stage = {
title: "Remove Conflicting Interactions",
title: "Remove Interactions",
steps: []
}
conflictingInteractions.forEach(i => {
let newStep: Step = {
title: "Removing Interaction",
promise: interactionAPI.removeInteraction(deviceId, i.key())
}
stage1.steps.push(newStep);
});
if(stage1.steps.length > 0){
stages.push(stage1)
}
//stage two is to add the new interactions
let stage2: Stage = {
title: "Add New Interactions",
steps: [
{
title: "Adding Interactions",
promise: interactionAPI.addMultiInteractions(deviceId, newInteractions)
}
]
steps: []
}
if(stage2.steps.length > 0){
stages.push(stage2)
}
//stage three is to update the controller components
let stage3: Stage = {
title: "Update Controllers",
steps: []
}
componentSets.forEach(set => {
set.controllers.forEach(controller => {
let newStep: Step = {
title: "Updating " + controller.name(),
promise: componentAPI.update(deviceId, controller.settings)
}
stage3.steps.push(newStep)
deviceData.forEach(data => {
data.toRemove.forEach(interaction => {
let newStep: Step = {
title: "Removing Interaction",
promise: () => interactionAPI.removeInteraction(data.deviceId, interaction.key())
}
stage1.steps.push(newStep);
})
let newInteractions = data.toAdd
if(newInteractions){
stage2.steps.push({
title: "Adding Interactions",
promise: () => interactionAPI.addMultiInteractions(data.deviceId, newInteractions)
})
}
data.componentSets.forEach(set => {
set.controllers.forEach(controller => {
let newStep: Step = {
title: "Updating " + controller.name(),
promise: () => componentAPI.update(data.deviceId, controller.settings)
}
stage3.steps.push(newStep)
})
})
})
if(stage1.steps.length > 0){
stages.push(stage1)
}
if(stage2.steps.length > 0){
stages.push(stage2)
}
if(stage3.steps.length > 0){
stages.push(stage3)
}
//stage 4 is to update the bin with the new mode
let stage4: Stage = {
title: "Update Bin With New Mode",
steps: [
{
title: "Update " + bin.name(),
promise: () => {
let clone = cloneDeep(bin.settings)
clone.mode = newMode
//this will set the bin to use the auto top nodes for cables when the bin is going into storage mode, and turn them off if the bin is being conditioned
if(newMode === pond.BinMode.BIN_MODE_STORAGE){
clone.autoGrainNode = true
}else{
clone.autoGrainNode = false
}
return binAPI.updateBin(bin.key(), clone)
},
onComplete: () => modeUpdated?.(newMode)
}
]
}
stages.push(stage4)
//set those stages to a state variable
setPromiseStages(stages)
}
@ -136,7 +169,7 @@ export default function BinModeController(props: Props) {
/>
</DialogContent>
<DialogActions>
<Button onClick={closeDialog}>Cancel</Button>
<Button onClick={closeDialog}>Close</Button>
</DialogActions>
</React.Fragment>
)
@ -152,8 +185,8 @@ export default function BinModeController(props: Props) {
binPrefs={binPrefs}
deviceComponents={deviceComponents}
cancel={closeDialog}
confirm={(conflicting, device, newInteractions, components) => {
buildStages(conflicting, device, newInteractions, components)
confirm={(deviceData) => {
buildStages(deviceData)
setShowProgress(true)
}}
/>
@ -162,7 +195,7 @@ export default function BinModeController(props: Props) {
case pond.BinMode.BIN_MODE_COOLDOWN:
return <CooldownMode />
default:
return <StorageMode />
return <StorageMode devices={devices} confirm={()=>{}}/>
}
}

View file

@ -18,6 +18,7 @@ import { useGlobalState, useInteractionsAPI } from "providers";
import BinConditioningInteraction from "bin/BinConditioningInteraction";
import ConditionDisplay from "./conditionDisplay";
import React from "react";
import { DeviceChangeData } from "./BinModeController";
const useStyles = makeStyles((theme: Theme) => {
@ -33,8 +34,6 @@ interface Step {
completed?: boolean;
}
export const DryingBaseStepCount = 3
interface Option {
label: string;
device: Device;
@ -47,7 +46,7 @@ interface Props {
binPrefs?: Map<string, pond.BinComponentPreferences>
grain?: pond.Grain
cancel: () => void
confirm: (conflictingInteractions: Interaction[], deviceId: number, newInteractions: pond.MultiInteractionSettings, componentSets: ComponentSet[]) => void
confirm: (deviceData: DeviceChangeData[]) => void
}
const steps = [{label: "Style"}, {label: "Device"}, {label: "Interaction"}]
@ -419,6 +418,7 @@ export default function DryingMode(props: Props){
}
const deviceStep = () => {
return (
<Box>
<Typography>Devices</Typography>
@ -497,7 +497,7 @@ export default function DryingMode(props: Props){
{/* next - goes to the next step, hidden on the last step */}
{currentStep !== steps.length - 1 && <Button onClick={() => {setCurrentStep(currentStep+1)}}>Next</Button>}
{/* confirm - tells the parent to build the stages using the data, only visible on the last step */}
{currentStep === steps.length - 1 && interactionsToAdd && selectedDevice && <Button onClick={() => {confirm(conflictingInteractions, selectedDevice.id(), interactionsToAdd, componentSets)}}>Confirm</Button>}
{currentStep === steps.length - 1 && interactionsToAdd && selectedDevice && <Button onClick={() => {confirm([{ toRemove: conflictingInteractions, deviceId: selectedDevice.id(), toAdd: interactionsToAdd, componentSets}])}}>Confirm</Button>}
</React.Fragment>
)
}

View file

@ -1,9 +1,38 @@
import { Box } from "@mui/material";
import { Box, DialogContent, DialogTitle, DialogActions } from "@mui/material";
import { ComponentSet } from "bin/conditioning/pickComponentSet";
import { Device, Interaction } from "models";
import { pond } from "protobuf-ts/pond";
import React from "react";
interface InteractionToRemove {
deviceID: number,
//interactions:
}
interface Props {
// the devices connected to the bin
devices: Device[]
confirm: (conflictingInteractions: Interaction[], deviceId: number, newInteractions: pond.MultiInteractionSettings, componentSets: ComponentSet[]) => void
}
/**
* when a bin goes into storage mode then the auto top node needs to be set, should be handled in the controller actually
* interactions with connected controllers as sink should be deleted, and controllers should be set to off
* @returns
*/
export default function StorageMode(props: Props){
//load the interactions for all of the bins connected devices
//
export default function StorageMode(){
return (
<Box>
</Box>
<React.Fragment>
<DialogTitle>Storage Mode</DialogTitle>
<DialogContent>
{/* could have the explanation of what changing to storage mode does here */}
</DialogContent>
<DialogActions></DialogActions>
</React.Fragment>
)
}

View file

@ -439,7 +439,7 @@ if (!selectedDevice) return;
conflictingSetInteractions.forEach(i => {
let newStep: PromiseStep = {
title: "Removing Interaction",
promise: interactionAPI.removeInteraction(selectedDevice.id(), i.key(), as)
promise: () => interactionAPI.removeInteraction(selectedDevice.id(), i.key(), as)
}
stage1.steps.push(newStep);
});
@ -452,7 +452,7 @@ if (!selectedDevice) return;
steps: [
{
title: "Adding Interactions",
promise: interactionAPI.addMultiInteractions(selectedDevice.id(), interactionsToAdd)
promise: () => interactionAPI.addMultiInteractions(selectedDevice.id(), interactionsToAdd)
}
]
}
@ -469,7 +469,7 @@ if (!selectedDevice) return;
set.controllers.forEach(controller => {
let newStep: PromiseStep = {
title: "Updating " + controller.name(),
promise: componentAPI.update(selectedDevice.id(), controller.settings)
promise: () => componentAPI.update(selectedDevice.id(), controller.settings)
}
stage3.steps.push(newStep)
})

View file

@ -11,7 +11,7 @@ export interface Stage {
export interface Step {
title: string
promise: Promise<AxiosResponse>
promise: () => Promise<AxiosResponse>
onComplete?: () => void
onError?: () => void
}
@ -52,7 +52,7 @@ export function PromiseProgress(props: Props){
// mark step as in progress
progMap.set(i+"-"+k, progress.InProgress);
setCompletion(new Map(progMap));
return step.promise
return step.promise()
.then(() => {
// mark step as completed
progMap.set(i+"-"+k, progress.Complete);

View file

@ -417,7 +417,8 @@ export default function ComponentProvider(props: PropsWithChildren<Props>) {
"&end=" +
end +
(keys ? "&keys=" + keys : "&keys=" + [deviceId.toString()]) +
(types ? "&types=" + types : "&types=" + ["device"])
(types ? "&types=" + types : "&types=" + ["device"]) +
(as ? "&as=" + as : "")
)
return new Promise<AxiosResponse<pond.ListComponentHistoryBetweenResponse>>((resolve,reject) => {
get<pond.ListComponentHistoryBetweenResponse>(url).then(resp => {