with changing unit preferences and such to use the user object and not local storage, the decriber needed to be updated as well and i missed that part, so now describeMeasurement takes in an optional user and uses its settings for the unit and such and when not passed in will use the defaults

This commit is contained in:
csawatzky 2026-04-01 10:42:16 -06:00
parent 9d41499c27
commit 52c8a02af3
18 changed files with 117 additions and 56 deletions

View file

@ -103,7 +103,7 @@ export default function BinConditioningInteraction(props: Props) {
let sliderVals: Map<quack.MeasurementType, number> = new Map();
let sliderMarks: Map<quack.MeasurementType, number> = new Map();
passedInteraction.conditions().forEach(condition => {
let describer = describeMeasurement(condition.measurementType, source.type());
let describer = describeMeasurement(condition.measurementType, source.type(), undefined, undefined, user);
//NOTE: toDisplay will convert the temp value to fahrenheit
sliderVals.set(condition.measurementType, describer.toDisplay(condition.value));
});
@ -173,17 +173,17 @@ export default function BinConditioningInteraction(props: Props) {
return (
<Grid container>
{interaction.conditions().map((condition, i) => {
let describer = describeMeasurement(condition.measurementType, source?.type());
let labelTail = "";
let describer = describeMeasurement(condition.measurementType, source?.type(), source.subType(), undefined, user);
let labelTail = describer.unit();
let marks: Mark[] = [];
if (condition.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) {
if (user.tempUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
labelTail = "°F";
} else {
labelTail = "°C";
}
}
// if (condition.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) {
// if (user.tempUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) {
// labelTail = "°F";
// } else {
// labelTail = "°C";
// }
// }
if (condition.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_PERCENT) {
labelTail = "%";
}
@ -198,7 +198,7 @@ export default function BinConditioningInteraction(props: Props) {
return (
<Grid key={i} container item xs={12} alignContent="center" alignItems="center">
<Grid item xs={12}>
{interactionConditionText(source, condition, false)}
{interactionConditionText(source, condition, false, user)}
</Grid>
<Grid item xs={12} style={{ marginBottom: 20 }}>
<Slider

View file

@ -87,9 +87,24 @@ export default function GrainNodeInteractions(props: Props) {
const [nodeHum, setNodeHum] = useState<number>();
const [nodeMoist, setNodeMoist] = useState<number | undefined>();
const [{ user, as }] = useGlobalState();
const tempDescriber = describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE);
const humDescriber = describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_PERCENT);
const moistureDescriber = describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_GRAIN_EMC);
const tempDescriber = describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE,
undefined,
undefined,
user);
const humDescriber = describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_PERCENT,
quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE,
undefined,
undefined,
user);
const moistureDescriber = describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_GRAIN_EMC,
quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE,
undefined,
undefined,
user);
const [topNode, setTopNode] = useState(false);
const [excluded, setExcluded] = useState(false);
const componentAPI = useComponentAPI();

View file

@ -288,7 +288,9 @@ if (!selectedDevice) return;
describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_PERCENT,
sensor.settings.type,
sensor.settings.subtype
sensor.settings.subtype,
undefined,
user
).toStored(hum)
)
});
@ -301,7 +303,9 @@ if (!selectedDevice) return;
let tempVal = describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
sensor.settings.type,
sensor.settings.subtype
sensor.settings.subtype,
undefined,
user
).toStored(temp);
let tempCondition = pond.InteractionCondition.create({
@ -385,7 +389,9 @@ if (!selectedDevice) return;
value: describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_PERCENT,
sensor.settings.type,
sensor.settings.subtype
sensor.settings.subtype,
undefined,
user
).toStored(humidityPreset)
});
conditions.push(fanConditionOne);
@ -397,7 +403,9 @@ if (!selectedDevice) return;
let tempVal = describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
sensor.settings.type,
sensor.settings.subtype
sensor.settings.subtype,
undefined,
user
).toStored(tempPreset);
let fanConditionTwo = pond.InteractionCondition.create({

View file

@ -67,7 +67,7 @@ export default function MeasurementsChart(props: Props) {
const [currentMax, setCurrentMax] = useState<number | string>("dataMax");
const [newChart, setNewChart] = useState(false);
const [xDomain, setXDomain] = useState<string[] | number[]>(["dataMin", "dataMax"]);
const [{ showErrors }, dispatch] = useGlobalState();
const [{ showErrors, user }, dispatch] = useGlobalState();
const isMobile = useMobile();
// const [zoomStart, setZoomStart] = useState<Moment>();
// const [zoomEnd, setZoomEnd] = useState<Moment>();
@ -123,7 +123,7 @@ export default function MeasurementsChart(props: Props) {
if (filters?.selectedInteractions?.includes(interaction.key())) {
interaction.settings.conditions.forEach((condition, j) => {
if (condition.measurementType === measurementType) {
let describer = describeMeasurement(condition.measurementType);
let describer = describeMeasurement(condition.measurementType, undefined, undefined, undefined, user);
selectedInteractions.push(
<ReferenceLine
key={interaction.key() + ":condition" + j}
@ -197,7 +197,9 @@ export default function MeasurementsChart(props: Props) {
let describer = describeMeasurement(
m.type,
component.settings.type,
component.settings.subtype
component.settings.subtype,
undefined,
user
);
let min: string | number = "dataMin";
let max: string | number = "dataMax";

View file

@ -145,7 +145,9 @@ export default function ComponentForm(props: Props) {
let describer = describeMeasurement(
primaryMeasurement(formComponent.settings.type),
formComponent.settings.type,
formComponent.settings.subtype
formComponent.settings.subtype,
undefined,
user
);
let offset = describer.toDisplay(formComponent.settings.calibrationOffset);
let formCoefficients: string[] = [];
@ -480,7 +482,9 @@ export default function ComponentForm(props: Props) {
f.component.settings.calibrationOffset = describeMeasurement(
primaryMeasurement(f.component.settings.type),
f.component.settings.type,
f.component.settings.subtype
f.component.settings.subtype,
undefined,
user
).toStored(+event.target.value);
}
setForm(f);
@ -493,7 +497,9 @@ export default function ComponentForm(props: Props) {
f.component.settings.calibrations[index].calibrationOffset = describeMeasurement(
primaryMeasurement(f.component.settings.type),
f.component.settings.type,
f.component.settings.subtype
f.component.settings.subtype,
undefined,
user
).toStored(+event.target.value);
}
setForm(f);
@ -731,7 +737,9 @@ export default function ComponentForm(props: Props) {
{describeMeasurement(
primaryMeasurement(component.settings.type),
component.settings.type,
component.settings.subtype
component.settings.subtype,
undefined,
user
).unit()}
</InputAdornment>
)
@ -823,7 +831,7 @@ export default function ComponentForm(props: Props) {
const describeSource = (measurementType: quack.MeasurementType): MeasurementDescriber => {
const { component } = form;
return describeMeasurement(measurementType, component.type(), component.subType());
return describeMeasurement(measurementType, component.type(), component.subType(), undefined, user);
};
const availableMeasurementTypes = (type: quack.ComponentType): quack.MeasurementType[] => {

View file

@ -210,7 +210,7 @@ class ExportDataSettings extends React.Component<Props, State> {
// }
formatMeasurements(measurements: Array<pond.Measurement>): Promise<Array<any>> {
const { device, component } = this.props;
const { device, component, user } = this.props;
return new Promise(function(resolve, reject) {
if (!measurements) reject("Invalid measurements");
@ -237,7 +237,9 @@ class ExportDataSettings extends React.Component<Props, State> {
let unit = describeMeasurement(
componentMeasurement.measurementType,
component.settings.type,
component.settings.subtype
component.settings.subtype,
undefined,
user
).unit();
let key = componentMeasurement.label + " (" + unit + ")";
row[key] = componentMeasurement.extract(measurement.measurement);

View file

@ -282,13 +282,13 @@ export default function GateGraphs(props: Props) {
if (um.values[0] && um.values[0].values.length > 1) {
return areaGraph(
um,
describeMeasurement(um.type, component.type(), component.subType()),
describeMeasurement(um.type, component.type(), component.subType(), undefined, user),
component.settings.smoothingAverages
);
} else {
return lineGraph(
um,
describeMeasurement(um.type, component.type(), component.subType()),
describeMeasurement(um.type, component.type(), component.subType(), undefined, user),
component.settings.smoothingAverages
);
}

View file

@ -195,7 +195,9 @@ export default function InteractionSettings(props: Props) {
let value = describeMeasurement(
condition.measurementType,
or(initialComponent, Component.create()).settings.type,
or(initialComponent, Component.create()).settings.subtype
or(initialComponent, Component.create()).settings.subtype,
undefined,
user
).toDisplay(condition.value);
rawConditionValues.push(value.toString());
});
@ -425,7 +427,7 @@ export default function InteractionSettings(props: Props) {
mappedComponents.get(componentIDToString(interaction.settings.source)),
Component.create()
);
return describeMeasurement(measurementType, source.settings.type, source.settings.subtype);
return describeMeasurement(measurementType, source.settings.type, source.settings.subtype, undefined, user);
};
const describeSink = (): MeasurementDescriber => {
@ -433,7 +435,9 @@ export default function InteractionSettings(props: Props) {
return describeMeasurement(
Measurement.boolean,
or(sink, Component.create()).settings.type,
or(sink, Component.create()).settings.subtype
or(sink, Component.create()).settings.subtype,
undefined,
user
);
};
@ -861,7 +865,7 @@ export default function InteractionSettings(props: Props) {
const conditionGroup = (index: number) => {
if (index >= numConditions) return;
let measurementType = interaction.settings.conditions[index].measurementType;
let source = describeSource(measurementType);
let source = describeSource(measurementType, );
let isBoolean = isBooleanValue(index);
return (
<React.Fragment key={index}>

View file

@ -71,7 +71,7 @@ interface Props {
export default function InteractionsOverview(props: Props) {
const classes = useStyles();
const [{as}] = useGlobalState();
const [{as, user}] = useGlobalState();
const interactionsAPI = useInteractionsAPI();
const { success, error } = useSnackbar();
const { device, component, components, permissions, refreshCallback } = props;
@ -118,12 +118,12 @@ export default function InteractionsOverview(props: Props) {
if (!conditions) return items;
conditions.forEach((condition: pond.IInteractionCondition, conditionIndex: number) => {
let measurementType = condition.measurementType;
let measurement = describeMeasurement(condition.measurementType, sourceType, sourceSubtype);
let measurement = describeMeasurement(condition.measurementType, sourceType, sourceSubtype, undefined, user);
items.push(
<Grid container size={{ sm: 12 }} key={conditionIndex} alignItems="center">
<Grid size={{ xs: 12, sm: 6 }}>
<Typography variant="caption" gutterBottom>
{interactionConditionText(source, condition, conditionIndex > 0)}
{interactionConditionText(source, condition, conditionIndex > 0, user)}
</Typography>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
@ -185,7 +185,7 @@ export default function InteractionsOverview(props: Props) {
let condition = conditions[conditionIndex];
let sourceType = source && source.settings.type;
let sourceSubtype = source && source.settings.subtype;
let describer = describeMeasurement(condition.measurementType, sourceType, sourceSubtype);
let describer = describeMeasurement(condition.measurementType, sourceType, sourceSubtype, undefined, user);
condition.value = describer.toStored(value);
updatedDirtyInteractions.set(interactionIndex, true);
}

View file

@ -3,8 +3,6 @@ import { quack } from "protobuf-ts/pond";
import { or } from "utils/types";
import { clone, cloneDeep } from "lodash";
import { Component } from "models";
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
import { extractGrainCable } from "pbHelpers/ComponentTypes";
export class CO2 {
public settings: pond.ComponentSettings = pond.ComponentSettings.create();

View file

@ -32,7 +32,7 @@ export class UnitMeasurement {
public static create(pb?: pond.UnitMeasurementsForComponent, user?: User): UnitMeasurement {
let my = new UnitMeasurement();
if (pb) {
let describer = describeMeasurement(pb.type, pb.componentType);
let describer = describeMeasurement(pb.type, pb.componentType, undefined, undefined, user);
let values = pb.values;
if (user) {
values = unitConversion(pb.values, pb.type, user);

View file

@ -6,6 +6,7 @@ import { pond, quack } from "protobuf-ts/pond";
import React, { useState } from "react";
import NewObjectInteraction from "./NewObjectInteraction";
import { Option } from "common/SearchSelect";
import { useGlobalState } from "providers";
export interface Alert {
conditions: pond.InteractionCondition[];
@ -20,10 +21,11 @@ interface Props {
export default function Alerts(props: Props){
const {alerts, addNew, permissions} = props
const [{user}] = useGlobalState();
// const [openNewAlert, setOpenNewAlert] = useState(false)
const readableCondition = (condition: pond.InteractionCondition) => {
let describer = describeMeasurement(condition.measurementType);
let describer = describeMeasurement(condition.measurementType, undefined, undefined, undefined, user);
let type = describer.label();
let comparison =
condition.comparison === quack.RelationalOperator.RELATIONAL_OPERATOR_EQUAL_TO

View file

@ -4,6 +4,7 @@ import { Component, Device, Interaction } from "models";
import { interactionResultText } from "pbHelpers/Interaction";
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";
import { pond, quack } from "protobuf-ts/pond";
import { useGlobalState } from "providers";
import React, { useEffect, useState } from "react";
export interface Control {
@ -23,6 +24,7 @@ interface Props {
export default function Controls(props: Props){
const { devices, controls, addNew, permissions } = props
const [{user}] = useGlobalState();
const [deviceControls, setDeviceControls] = useState<Map<number, Control[]>>(new Map())
const [openDeviceMenu, setOpenDeviceMenu] = useState(false)
const [anchor, setAnchor] = useState<null | HTMLElement>(null)
@ -45,7 +47,7 @@ export default function Controls(props: Props){
let conditions: string = ""
let firstSource = control.sourceComponents[0]
control.conditions.forEach((condition, index) => {
let describer = describeMeasurement(condition.measurementType, firstSource.type(), firstSource.subType());
let describer = describeMeasurement(condition.measurementType, firstSource.type(), firstSource.subType(), undefined, user);
let type = describer.label();
let comparison =
condition.comparison === quack.RelationalOperator.RELATIONAL_OPERATOR_EQUAL_TO

View file

@ -64,7 +64,7 @@ const useStyles = makeStyles((theme: Theme) => {
export default function NewObjectInteraction(props: Props){
const { open, onClose, device, linkedComponents, componentDevices } = props
const classes = useStyles()
const [{ as }] = useGlobalState();
const [{ as, user }] = useGlobalState();
const {openSnack} = useSnackbar();
const interactionsAPI = useInteractionsAPI();
const [newAlertComponentType, setNewAlertComponentType] = useState<quack.ComponentType>(
@ -249,7 +249,7 @@ export default function NewObjectInteraction(props: Props){
const measurementTypeMenuItems = () => {
return availableMeasurementTypes(newAlertComponentType).map(measurementType => (
<MenuItem key={measurementType} value={measurementType}>
{describeMeasurement(measurementType).label()}
{describeMeasurement(measurementType, undefined, undefined, undefined, user).label()}
</MenuItem>
));
};
@ -531,7 +531,9 @@ export default function NewObjectInteraction(props: Props){
return describeMeasurement(
Measurement.boolean,
or(sink, Component.create()).settings.type,
or(sink, Component.create()).settings.subtype
or(sink, Component.create()).settings.subtype,
undefined,
user
);
};

View file

@ -569,7 +569,11 @@ export default function Bins(props: Props) {
measurementType: quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
comparison: quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN,
value: describeMeasurement(
quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE
quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE,
undefined,
undefined,
undefined,
user
).toStored(bin.settings.highTemp)
}),
componentLocation: quack.ComponentID.create({

View file

@ -236,16 +236,16 @@ export function unitMeasurementSummary(
): Summary {
let vals: string[] = [];
convertedMeasurement.values.forEach(val => {
vals.push(val + describer.unit());
vals.push(val + convertedMeasurement.unit);
});
let v = vals.join(", ");
if (describer.enumerations().length > 0) {
v = describer.enumerations()[parseFloat(vals[0])];
}
return {
colour: describer.colour(),
label: describer.label(),
type: describer.type(),
colour: convertedMeasurement.colour,
label: convertedMeasurement.label,
type: convertedMeasurement.type,
value: v,
error: convertedMeasurement.error
};
@ -258,6 +258,8 @@ export function unitMeasurementSummaries(
): Summary[] {
let summaries: Summary[] = [];
measurements.measurementsFor.forEach(measurement => {
//the only reason the user doesnt need to be passed in here is because it is only used for enumerations,
//things like the unit and colour are in the measurement itself at this point
let describer = describeMeasurement(measurement.type, compType, subtype);
summaries.push(unitMeasurementSummary(measurement, describer));
});
@ -530,6 +532,7 @@ export function simpleLineChartData(
}
});
}
console.log(lineData)
return lineData;
}
@ -945,6 +948,15 @@ function getOverlayAreas(
return overlayAreas;
}
/**
* this function adds lines to victory graphs for interactions on the component
* DEPRECATED: we now use Recharts for our graphs
* @param componentType
* @param subtype
* @param interactionCondition
* @returns
*/
function createInteractionLine(
componentType: quack.ComponentType,
subtype: number,

View file

@ -1,4 +1,4 @@
import { Interaction, Component } from "models";
import { Interaction, Component, User } from "models";
import { pond } from "protobuf-ts/pond";
import { quack } from "protobuf-ts/quack";
import { or, notNull } from "utils/types";
@ -172,7 +172,8 @@ export const interactionResultText = (interaction: Interaction, sink?: Component
export const interactionConditionText = (
source: Component | undefined,
condition: pond.IInteractionCondition,
and: boolean
and: boolean,
user?: User
) => {
let comparison = "is exactly";
switch (condition.comparison) {
@ -189,7 +190,7 @@ export const interactionConditionText = (
if (!condition.measurementType) return "Unknown " + comparison + " " + condition.value;
let sourceType = source && source.settings.type;
let sourceSubtype = source && source.settings.subtype;
let measurement = describeMeasurement(condition.measurementType, sourceType, sourceSubtype);
let measurement = describeMeasurement(condition.measurementType, sourceType, sourceSubtype, undefined, user);
return (
(and ? "and " : "") +
measurement.label() +

View file

@ -694,11 +694,12 @@ export function describeMeasurement(
componentType: quack.ComponentType | null | undefined = quack.ComponentType
.COMPONENT_TYPE_INVALID,
componentSubtype: number = 0,
product?: pond.DeviceProduct
product?: pond.DeviceProduct,
user?: User
): MeasurementDescriber {
measurementType = measurementType
? measurementType
: quack.MeasurementType.MEASUREMENT_TYPE_INVALID;
componentType = componentType ? componentType : quack.ComponentType.COMPONENT_TYPE_INVALID;
return new MeasurementDescriber(measurementType, componentType, componentSubtype, product);
return new MeasurementDescriber(measurementType, componentType, componentSubtype, product, user);
}