From ec5e8eea05571030a2a5d485029a7827b27848df Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Tue, 31 Mar 2020 18:02:11 -0700 Subject: [PATCH] Merge pull request #11681 from PersianXerxes/medicalTGUINext TGUI Next in the Medbay --- .../chemistry/machinery/chem_master.dm | 358 ++++++-------- .../packages/tgui/interfaces/ChemDispenser.js | 180 +++++++ .../packages/tgui/interfaces/ChemHeater.js | 75 +++ .../packages/tgui/interfaces/ChemMaster.js | 448 ++++++++++++++++++ tgui-next/packages/tgui/routes.js | 15 + 5 files changed, 864 insertions(+), 212 deletions(-) create mode 100644 tgui-next/packages/tgui/interfaces/ChemDispenser.js create mode 100644 tgui-next/packages/tgui/interfaces/ChemHeater.js create mode 100644 tgui-next/packages/tgui/interfaces/ChemMaster.js diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index ea8e4fdf..d001d7f5 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -199,86 +199,129 @@ //Calculated at init time as it never changes data["pillStyles"] = pillStyles - return data /obj/machinery/chem_master/ui_act(action, params) if(..()) return + switch(action) if("eject") replace_beaker(usr) . = TRUE - if("ejectp") + if("ejectPillBottle") replace_pillbottle(usr) . = TRUE - if("transferToBuffer") - if(beaker) - var/reagent = text2path(params["id"]) //This change was necessary due to some byond fuckery with reagents being translated back to their paths. Please do not modify this under any circumstance, otherwise you will break synthtissue. - var/amount = text2num(params["amount"]) - if (amount > 0) - end_fermi_reaction() - beaker.reagents.trans_id_to(src, reagent, amount) - . = TRUE - else if (amount == -1) // -1 means custom amount - useramount = input("Enter the Amount you want to transfer:", name, useramount) as num|null - if (useramount > 0) - end_fermi_reaction() - beaker.reagents.trans_id_to(src, reagent, useramount) - . = TRUE - - if("transferFromBuffer") + if("transfer") + if(!beaker) + return FALSE var/reagent = text2path(params["id"]) //This change was necessary due to some byond fuckery with reagents being translated back to their paths. Please do not modify this under any circumstance, otherwise you will break synthtissue. var/amount = text2num(params["amount"]) - if (amount > 0) - if(mode) - reagents.trans_id_to(beaker, reagent, amount) - . = TRUE - else - reagents.remove_reagent(reagent, amount) - . = TRUE - else if (amount == -1) // -1 means custom amount - useramount = input("Enter the Amount you want to transfer:", name, useramount) as num|null - if (useramount > 0) - end_fermi_reaction() - reagents.trans_id_to(beaker, reagent, useramount) - . = TRUE + var/to_container = params["to"] + // Custom amount + if (amount == -1) + amount = text2num(input( + "Enter the amount you want to transfer:", + name, "")) + if (amount == null || amount <= 0) + return FALSE + if (to_container == "buffer") + end_fermi_reaction() + beaker.reagents.trans_id_to(src, reagent, amount) + return TRUE + if (to_container == "beaker" && mode) + end_fermi_reaction() + reagents.trans_id_to(beaker, reagent, amount) + return TRUE + if (to_container == "beaker" && !mode) + end_fermi_reaction() + reagents.remove_reagent(reagent, amount) + return TRUE + return FALSE if("toggleMode") mode = !mode . = TRUE - if("createPill") - var/many = params["many"] + if("pillStyle") + var/id = text2num(params["id"]) + chosenPillStyle = id + return TRUE + + if("create") if(reagents.total_volume == 0) - return - if(!condi) - var/amount = 1 - var/vol_each = min(reagents.total_volume, 50) - if(text2num(many)) - amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many pills?", amount) as num|null), 0, 10) - if(!amount) - return - vol_each = min(reagents.total_volume / amount, 50) - var/name = html_decode(stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) - return + return FALSE + var/item_type = params["type"] + // Get amount of items + var/amount = text2num(params["amount"]) + if(amount == null) + amount = text2num(input(usr, + "Max 10. Buffer content will be split evenly.", + "How many to make?", 1)) + amount = clamp(round(amount), 0, 10) + if (amount <= 0) + return FALSE + // Get units per item + var/vol_each = text2num(params["volume"]) + var/vol_each_text = params["volume"] + var/vol_each_max = reagents.total_volume / amount + if (item_type == "pill") + vol_each_max = min(50, vol_each_max) + else if (item_type == "patch") + vol_each_max = min(40, vol_each_max) + else if (item_type == "bottle") + vol_each_max = min(30, vol_each_max) + else if (item_type == "condimentPack") + vol_each_max = min(10, vol_each_max) + else if (item_type == "condimentBottle") + vol_each_max = min(50, vol_each_max) + else if (item_type == "hypoVial") + vol_each_max = min(60, vol_each_max) + else if (item_type == "smartDart") + vol_each_max = min(20, vol_each_max) + else + return FALSE + if(vol_each_text == "auto") + vol_each = vol_each_max + if(vol_each == null) + vol_each = text2num(input(usr, + "Maximum [vol_each_max] units per item.", + "How many units to fill?", + vol_each_max)) + vol_each = clamp(vol_each, 0, vol_each_max) + if(vol_each <= 0) + return FALSE + // Get item name + var/name = params["name"] + var/name_has_units = item_type == "pill" || item_type == "patch" + if(!name) + var/name_default = reagents.get_master_reagent_name() + if (name_has_units) + name_default += " ([vol_each]u)" + name = stripped_input(usr, + "Name:", + "Give it a name!", + name_default, + MAX_NAME_LEN) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + return FALSE + // Start filling + if(item_type == "pill") var/obj/item/reagent_containers/pill/P var/target_loc = drop_location() var/drop_threshold = INFINITY if(bottle) - var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage) + var/datum/component/storage/STRB = bottle.GetComponent( + /datum/component/storage) if(STRB) drop_threshold = STRB.max_items - bottle.contents.len - target_loc = bottle - - for(var/i in 1 to amount) - if(i <= drop_threshold) - P = new(target_loc) + for(var/i = 0; i < amount; i++) + if(i < drop_threshold) + P = new/obj/item/reagent_containers/pill(target_loc) else - P = new(drop_location()) + P = new/obj/item/reagent_containers/pill(drop_location()) P.name = trim("[name] pill") if(chosenPillStyle == RANDOM_PILL_STYLE) P.icon_state ="pill[rand(1,21)]" @@ -287,171 +330,62 @@ if(P.icon_state == "pill4") P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality." adjust_item_drop_location(P) - reagents.trans_to(P,vol_each) - else - var/name = html_decode(stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) - return - var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location()) - - P.originalname = name - P.name = trim("[name] pack") - P.desc = "A small condiment pack. The label says it contains [name]." - reagents.trans_to(P,10) - . = TRUE - - if("pillStyle") - var/id = text2num(params["id"]) - chosenPillStyle = id - - if("createPatch") - var/many = params["many"] - if(reagents.total_volume == 0) - return - var/amount = 1 - var/vol_each = min(reagents.total_volume, 40) - if(text2num(many)) - amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many patches?", amount) as num|null), 0, 10) - if(!amount) - return - vol_each = min(reagents.total_volume / amount, 40) - var/name = html_decode(stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) - return - var/obj/item/reagent_containers/pill/P - - for(var/i = 0; i < amount; i++) - P = new/obj/item/reagent_containers/pill/patch(drop_location()) - P.name = trim("[name] patch") - adjust_item_drop_location(P) - reagents.trans_to(P,vol_each) - . = TRUE - - if("createBottle") - var/many = params["many"] - if(reagents.total_volume == 0) - return - - if(condi) - var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) - return - var/obj/item/reagent_containers/food/condiment/P = new(drop_location()) - P.originalname = name - P.name = trim("[name] bottle") - reagents.trans_to(P, P.volume) - else - var/amount_full = 0 - var/vol_part = min(reagents.total_volume, 30) - if(text2num(many)) - amount_full = round(reagents.total_volume / 30) - vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals. - var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) - return - + reagents.trans_to(P, vol_each) + return TRUE + if(item_type == "patch") + var/obj/item/reagent_containers/pill/patch/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/pill/patch(drop_location()) + P.name = trim("[name] patch") + adjust_item_drop_location(P) + reagents.trans_to(P, vol_each) + return TRUE + if(item_type == "bottle") var/obj/item/reagent_containers/glass/bottle/P - for(var/i = 0; i < amount_full; i++) + for(var/i = 0; i < amount; i++) P = new/obj/item/reagent_containers/glass/bottle(drop_location()) P.name = trim("[name] bottle") adjust_item_drop_location(P) - reagents.trans_to(P, 30) - - if(vol_part) - P = new/obj/item/reagent_containers/glass/bottle(drop_location()) + reagents.trans_to(P, vol_each) + return TRUE + if(item_type == "condimentPack") + var/obj/item/reagent_containers/food/condiment/pack/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/food/condiment/pack(drop_location()) + P.originalname = name + P.name = trim("[name] pack") + P.desc = "A small condiment pack. The label says it contains [name]." + reagents.trans_to(P, vol_each) + return TRUE + if(item_type == "condimentBottle") + var/obj/item/reagent_containers/food/condiment/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/food/condiment(drop_location()) + P.originalname = name P.name = trim("[name] bottle") + reagents.trans_to(P, vol_each) + return TRUE + if(item_type == "hypoVial") + var/obj/item/reagent_containers/glass/bottle/vial/small/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location()) + P.name = trim("[name] hypovial") adjust_item_drop_location(P) - reagents.trans_to(P, vol_part) - . = TRUE - //CITADEL ADD Hypospray Vials - if("createVial") - var/many = params["many"] - if(reagents.total_volume == 0) - return + reagents.trans_to(P, vol_each) + return TRUE + if(item_type == "smartDart") + var/obj/item/reagent_containers/syringe/dart/P + for(var/i = 0; i < amount; i++) + P = new /obj/item/reagent_containers/syringe/dart(drop_location()) + P.name = trim("[name] SmartDart") + adjust_item_drop_location(P) + reagents.trans_to(P, vol_each) + P.mode=!mode + P.update_icon() + return TRUE + return FALSE - var/amount_full = 0 - var/vol_part = min(reagents.total_volume, 60) - if(text2num(many)) - amount_full = round(reagents.total_volume / 60) - vol_part = reagents.total_volume % 60 - var/name = html_decode(stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) - return - - var/obj/item/reagent_containers/glass/bottle/vial/small/P - for(var/i = 0; i < amount_full; i++) - P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location()) - P.name = trim("[name] hypovial") - adjust_item_drop_location(P) - reagents.trans_to(P, 60) - - if(vol_part) - P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location()) - P.name = trim("[name] hypovial") - adjust_item_drop_location(P) - reagents.trans_to(P, vol_part) - . = TRUE - - if("createDart") - for(var/datum/reagent/R in reagents.reagent_list) - if(!(istype(R, /datum/reagent/medicine))) - visible_message("The [src] beeps, \"SmartDarts are insoluble with non-medicinal compounds.\"") - return - - var/many = params["many"] - if(reagents.total_volume == 0) - return - var/amount = 1 - var/vol_each = min(reagents.total_volume, 20) - if(text2num(many)) - amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many darts?", amount) as num|null), 0, 10) - if(!amount) - return - vol_each = min(reagents.total_volume / amount, 20) - - var/name = html_decode(stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) - return - - var/obj/item/reagent_containers/syringe/dart/D - for(var/i = 0; i < amount; i++) - D = new /obj/item/reagent_containers/syringe/dart(drop_location()) - D.name = trim("[name] SmartDart") - adjust_item_drop_location(D) - reagents.trans_to(D, vol_each) - D.mode=!mode - D.update_icon() - . = TRUE - - //END CITADEL ADDITIONS - if("analyzeBeak") - var/datum/reagent/R = text2path(params["id"]) - if(R) - var/state = "Unknown" - if(initial(R.reagent_state) == 1) - state = "Solid" - else if(initial(R.reagent_state) == 2) - state = "Liquid" - else if(initial(R.reagent_state) == 3) - state = "Gas" - var/const/P = 3 //The number of seconds between life ticks - var/T = initial(R.metabolization_rate) * (60 / P) - var/datum/chemical_reaction/Rcr = get_chemical_reaction(R) - if(Rcr && Rcr.FermiChem) - fermianalyze = TRUE - var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2 - var/datum/reagent/targetReagent = beaker.reagents.has_reagent(R) - - if(!targetReagent) - CRASH("Tried to find a reagent that doesn't exist in the chem_master!") - analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache) - else - fermianalyze = FALSE - analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold)) - screen = "analyze" - return - - if("analyzeBuff") + if("analyze") var/datum/reagent/R = text2path(params["id"]) if(R) var/state = "Unknown" @@ -476,7 +410,7 @@ fermianalyze = FALSE analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold)) screen = "analyze" - return + return TRUE if("goScreen") screen = params["screen"] @@ -527,4 +461,4 @@ condi = TRUE #undef PILL_STYLE_COUNT -#undef RANDOM_PILL_STYLE \ No newline at end of file +#undef RANDOM_PILL_STYLE diff --git a/tgui-next/packages/tgui/interfaces/ChemDispenser.js b/tgui-next/packages/tgui/interfaces/ChemDispenser.js new file mode 100644 index 00000000..4e9ca5a7 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/ChemDispenser.js @@ -0,0 +1,180 @@ +import { toFixed } from 'common/math'; +import { toTitleCase } from 'common/string'; +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { AnimatedNumber, Box, Button, Icon, LabeledList, ProgressBar, Section } from '../components'; + +export const ChemDispenser = props => { + const { act, data } = useBackend(props); + const recording = !!data.recordingRecipe; + // TODO: Change how this piece of shit is built on server side + // It has to be a list, not a fucking OBJECT! + const recipes = Object.keys(data.recipes) + .map(name => ({ + name, + contents: data.recipes[name], + })); + const beakerTransferAmounts = data.beakerTransferAmounts || []; + const beakerContents = recording + && Object.keys(data.recordingRecipe) + .map(id => ({ + id, + name: toTitleCase(id.replace(/_/, ' ')), + volume: data.recordingRecipe[id], + })) + || data.beakerContents + || []; + return ( + +
+ + Recording + + )}> + + + + + +
+
+ {!recording && ( + +
+
( +
+
( +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/ChemHeater.js b/tgui-next/packages/tgui/interfaces/ChemHeater.js new file mode 100644 index 00000000..8618fc0f --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/ChemHeater.js @@ -0,0 +1,75 @@ +import { round, toFixed } from 'common/math'; +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { AnimatedNumber, Box, Button, LabeledList, NumberInput, Section } from '../components'; +import { BeakerContents } from './common/BeakerContents'; + +export const ChemHeater = props => { + const { act, data } = useBackend(props); + const { + targetTemp, + isActive, + isBeakerLoaded, + currentTemp, + beakerCurrentVolume, + beakerMaxVolume, + beakerContents = [], + } = data; + return ( + +
act('power')} /> + )}> + + + act('temperature', { + target: value, + })} /> + + + + {isBeakerLoaded && ( + toFixed(value) + ' K'} /> + ) || '—'} + + + +
+
+ + {beakerCurrentVolume} / {beakerMaxVolume} units + +
+
+ ); +}; diff --git a/tgui-next/packages/tgui/interfaces/ChemMaster.js b/tgui-next/packages/tgui/interfaces/ChemMaster.js new file mode 100644 index 00000000..00c61ddf --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/ChemMaster.js @@ -0,0 +1,448 @@ +import { Component, Fragment } from 'inferno'; +import { act } from '../byond'; +import { AnimatedNumber, Box, Button, ColorBox, LabeledList, NumberInput, Section, Table } from '../components'; + +export const ChemMaster = props => { + const { state } = props; + const { config, data } = state; + const { ref } = config; + const { + screen, + beakerContents = [], + bufferContents = [], + beakerCurrentVolume, + beakerMaxVolume, + isBeakerLoaded, + isPillBottleLoaded, + pillBottleCurrentAmount, + pillBottleMaxAmount, + } = data; + + return ( + +
+ + + {` / ${beakerMaxVolume} units`} + +
+
+ + Mode: + +
+
+ +
+ {!!isPillBottleLoaded && ( +
+ + {pillBottleCurrentAmount} / {pillBottleMaxAmount} pills + + + ))} + + )} + {!condi && ( + this.setState({ + pillAmount: value, + })} + onCreate={() => act(ref, 'create', { + type: 'pill', + amount: pillAmount, + volume: 'auto', + })} /> + )} + {!condi && ( + this.setState({ + patchAmount: value, + })} + onCreate={() => act(ref, 'create', { + type: 'patch', + amount: patchAmount, + volume: 'auto', + })} /> + )} + {!condi && ( + this.setState({ + bottleAmount: value, + })} + onCreate={() => act(ref, 'create', { + type: 'bottle', + amount: bottleAmount, + volume: 'auto', + })} /> + )} + {!condi && ( + this.setState({ + vialAmount: value, + })} + onCreate={() => act(ref, 'create', { + type: 'hypoVial', + amount: vialAmount, + volume: 'auto', + })} /> + )} + {!condi && ( + this.setState({ + dartAmount: value, + })} + onCreate={() => act(ref, 'create', { + type: 'smartDart', + amount: dartAmount, + volume: 'auto', + })} /> + )} + {!!condi && ( + this.setState({ + packAmount: value, + })} + onCreate={() => act(ref, 'create', { + type: 'condimentPack', + amount: packAmount, + volume: 'auto', + })} /> + )} + {!!condi && ( + this.setState({ + bottleAmount: value, + })} + onCreate={() => act(ref, 'create', { + type: 'condimentBottle', + amount: bottleAmount, + volume: 'auto', + })} /> + )} + + ); + } +} + +const AnalysisResults = props => { + const { state, fermianalyze } = props; + const { ref } = state.config; + const { analyzeVars } = state.data; + return ( +
act(ref, 'goScreen', { + screen: 'home', + })} /> + )}> + {!fermianalyze && ( + + + {analyzeVars.name} + + + {analyzeVars.state} + + + + {analyzeVars.color} + + + {analyzeVars.description} + + + {analyzeVars.metaRate} u/minute + + + {analyzeVars.overD} + + + {analyzeVars.addicD} + + + )} + {!! data.fermianalyze && ( + + + {analyzeVars.name} + + + {analyzeVars.state} + + + + {analyzeVars.color} + + + {analyzeVars.description} + + + {analyzeVars.metaRate} u/minute + + + {analyzeVars.overD} + + + {analyzeVars.addicD} + + + {analyzeVars.purityF} + + + {analyzeVars.inverseRatioF} + + + {analyzeVars.purityE} + + + {analyzeVars.minTemp} + + + {analyzeVars.maxTemp} + + + {analyzeVars.eTemp} + + + {analyzeVars.pHpeak} + + + )} +
+ ); +}; diff --git a/tgui-next/packages/tgui/routes.js b/tgui-next/packages/tgui/routes.js index d80b25df..5c0a2d92 100644 --- a/tgui-next/packages/tgui/routes.js +++ b/tgui-next/packages/tgui/routes.js @@ -19,7 +19,10 @@ import { CellularEmporium } from './interfaces/CellularEmporium'; import { CentcomPodLauncher } from './interfaces/CentcomPodLauncher'; import { ChemAcclimator } from './interfaces/ChemAcclimator'; import { ChemDebugSynthesizer } from './interfaces/ChemDebugSynthesizer'; +import { ChemDispenser } from './interfaces/ChemDispenser'; import { ChemFilter } from './interfaces/ChemFilter'; +import { ChemHeater } from './interfaces/ChemHeater'; +import { ChemMaster } from './interfaces/ChemMaster'; import { ChemPress } from './interfaces/ChemPress'; import { ChemReactionChamber } from './interfaces/ChemReactionChamber'; import { ChemSplitter } from './interfaces/ChemSplitter'; @@ -179,10 +182,22 @@ const ROUTES = { component: () => ChemAcclimator, scrollable: false, }, + chem_dispenser: { + component: () => ChemDispenser, + scrollable: true, + }, chemical_filter: { component: () => ChemFilter, scrollable: true, }, + chem_heater: { + component: () => ChemHeater, + scrollable: true, + }, + chem_master: { + component: () => ChemMaster, + scrollable: true, + }, chem_press: { component: () => ChemPress, scrollable: false,