Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max min values #1396

Draft
wants to merge 7 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions src/client/app/components/meters/CreateMeterModalComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import { useTranslate } from '../../redux/componentHooks';
import TimeZoneSelect from '../TimeZoneSelect';
import TooltipHelpComponent from '../TooltipHelpComponent';
import TooltipMarkerComponent from '../TooltipMarkerComponent';
import { selectUnitDataById } from '../../redux/api/unitsApi';
import { DisableChecksType } from '../../types/redux/units';

interface CreateMeterModalProps {
onCreateMeter?: (meterIdentifier: string) => void; // Define the type of the callback function
Expand All @@ -55,6 +57,7 @@ export default function CreateMeterModalComponent(props: CreateMeterModalProps):
const [meterDetails, setMeterDetails] = useState(defaultValues);
const unitIsSelected = meterDetails.unitId !== -999;
const defaultGaphicUnitIsSelected = meterDetails.defaultGraphicUnit !== -999;
const unitsDataById = useAppSelector(selectUnitDataById);

const { compatibleGraphicUnits, incompatibleGraphicUnits, compatibleUnits } = useAppSelector(state =>
// Type assertion due to conflicting GPS Property
Expand Down Expand Up @@ -92,6 +95,22 @@ export default function CreateMeterModalComponent(props: CreateMeterModalProps):
const handleTimeZoneChange = (timeZone: string) => {
setMeterDetails({ ...meterDetails, ['timeZone']: timeZone });
};

const handleUnitChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedUnitId = Number(e.target.value);
const selectedUnit = unitsDataById[selectedUnitId];

if (selectedUnit) {
setMeterDetails(details => ({
...details,
unitId: selectedUnitId,
minVal: selectedUnit.minVal,
maxVal: selectedUnit.maxVal,
disableChecks: selectedUnit.disableChecks
}));
}
};

// Reset the state to default values
const resetState = () => {
setMeterDetails(defaultValues);
Expand Down Expand Up @@ -245,9 +264,7 @@ export default function CreateMeterModalComponent(props: CreateMeterModalProps):
</Label>
<Input id='unitId' name='unitId' type='select'
value={meterDetails.unitId}
onChange={e => {
handleNumberChange(e);
}}
onChange={handleUnitChange}
invalid={!unitIsSelected}>
<option value={-999} key={-999} hidden disabled>
{translate('select.unit')}
Expand Down Expand Up @@ -544,25 +561,25 @@ export default function CreateMeterModalComponent(props: CreateMeterModalProps):
<Row xs='1' lg='2'>
{/* minVal input */}
<Col><FormGroup>
<Label for='minVal'>{translate('meter.minVal')}</Label>
<Label for='minVal'>{translate('minVal')}</Label>
<Input id='minVal' name='minVal' type='number'
onChange={e => handleNumberChange(e)}
min={MIN_VAL}
max={meterDetails.maxVal}
defaultValue={meterDetails.minVal}
value={meterDetails.minVal}
invalid={meterDetails?.minVal < MIN_VAL || meterDetails?.minVal > meterDetails?.maxVal} />
<FormFeedback>
<FormattedMessage id="error.bounds" values={{ min: MIN_VAL, max: meterDetails.maxVal }} />
</FormFeedback>
</FormGroup></Col>
{/* maxVal input */}
<Col><FormGroup>
<Label for='maxVal'>{translate('meter.maxVal')}</Label>
<Label for='maxVal'>{translate('maxVal')}</Label>
<Input id='maxVal' name='maxVal' type='number'
onChange={e => handleNumberChange(e)}
min={meterDetails.minVal}
max={MAX_VAL}
defaultValue={meterDetails.maxVal}
value={meterDetails.maxVal}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change from defaultValue to value made it impossible to type in a negative value. The arrows still allow. This issue is on min, edit meter as well as edit unit.

invalid={meterDetails?.maxVal > MAX_VAL || meterDetails?.minVal > meterDetails?.maxVal} />
<FormFeedback>
<FormattedMessage id="error.bounds" values={{ min: meterDetails.minVal, max: MAX_VAL }} />
Expand Down Expand Up @@ -617,17 +634,14 @@ export default function CreateMeterModalComponent(props: CreateMeterModalProps):
</FormFeedback>
</FormGroup></Col>
<Col><FormGroup>
<Label for='disableChecks'>{translate('meter.disableChecks')}</Label>
<Label for='disableChecks'>{translate('disableChecks')}</Label>
<Input id='disableChecks' name='disableChecks' type='select'
defaultValue={meterDetails.disableChecks?.toString()}
onChange={e => handleBooleanChange(e)}>
{
Object.keys(TrueFalseType).map(key =>
<option value={key} key={key}>
{translate(`TrueFalseType.${key}`)}
</option>
)
}
value={meterDetails.disableChecks}
onChange={e => handleStringChange(e)}>
{Object.keys(DisableChecksType).map(key => {
return (<option value={key} key={key} >
{translate(`DisableChecksType.${key}`)}</option>);
})}
</Input>
</FormGroup></Col>
</Row>
Expand Down
45 changes: 35 additions & 10 deletions src/client/app/components/meters/EditMeterModalComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import '../../styles/modal.css';
import { tooltipBaseStyle } from '../../styles/modalStyle';
import { TrueFalseType } from '../../types/items';
import { MeterData, MeterTimeSortType, MeterType } from '../../types/redux/meters';
import { UnitRepresentType } from '../../types/redux/units';
import { DisableChecksType, UnitRepresentType } from '../../types/redux/units';
import { GPSPoint, isValidGPSInput } from '../../utils/calibration';
import { AreaUnitType } from '../../utils/getAreaUnitConversion';
import { getGPSString, nullToEmptyString } from '../../utils/input';
Expand Down Expand Up @@ -67,6 +67,17 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr

const [validMeter, setValidMeter] = useState(isValidMeter(localMeterEdits));

useEffect(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unclear on the relationship of this useEffect and handleUnitChange. They seem to do similar work. I tried commenting this out and it did not seem to matter. It is not in create unit. I may be missing something so let me know.

Also, a comment on what this is doing would be nice. For example, it is getting the min/max reading value from the unit to make that the starting value for the meter when a unit is selected.

const selectedUnit = unitDataById[localMeterEdits.unitId];
if (selectedUnit) {
setLocalMeterEdits(edits => ({
...edits,
minVal: selectedUnit.minVal,
maxVal: selectedUnit.maxVal
}));
}
}, [localMeterEdits.unitId, unitDataById]);

useEffect(() => { setValidMeter(isValidMeter(localMeterEdits)); }, [localMeterEdits]);
/* End State */

Expand All @@ -76,6 +87,20 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr
}
}, [localMeterEdits.cumulative]);

const handleUnitChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedUnitId = Number(e.target.value);
const selectedUnit = unitDataById[selectedUnitId];
if (selectedUnit) {
setLocalMeterEdits({
...localMeterEdits,
unitId: selectedUnitId,
minVal: selectedUnit.minVal,
maxVal: selectedUnit.maxVal,
disableChecks: selectedUnit.disableChecks
});
}
};

// Save changes
// Currently using the old functionality which is to compare inherited prop values to state values
// If there is a difference between props and state, then a change was made
Expand Down Expand Up @@ -279,7 +304,7 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr
name='unitId'
type='select'
value={localMeterEdits.unitId}
onChange={e => handleNumberChange(e)}>
onChange={handleUnitChange}>
{Array.from(compatibleUnits).map(unit => {
return (<option value={unit.id} key={unit.id}>{unit.identifier}</option>);
})}
Expand Down Expand Up @@ -599,7 +624,7 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr
<Row xs='1' lg='2'>
{/* minVal input */}
<Col><FormGroup>
<Label for='minVal'>{translate('meter.minVal')}</Label>
<Label for='minVal'>{translate('minVal')}</Label>
<Input
id='minVal'
name='minVal'
Expand All @@ -615,7 +640,7 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr
</FormGroup></Col>
{/* maxVal input */}
<Col><FormGroup>
<Label for='maxVal'>{translate('meter.maxVal')}</Label>
<Label for='maxVal'>{translate('maxVal')}</Label>
<Input
id='maxVal'
name='maxVal'
Expand Down Expand Up @@ -687,16 +712,16 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr
</FormGroup></Col>
{/* DisableChecks input */}
<Col><FormGroup>
<Label for='disableChecks'>{translate('meter.disableChecks')}</Label>
<Label for='disableChecks'>{translate('disableChecks')}</Label>
<Input
id='disableChecks'
name='disableChecks'
type='select'
value={localMeterEdits?.disableChecks?.toString()}
onChange={e => handleBooleanChange(e)}
invalid={localMeterEdits?.disableChecks && localMeterEdits.unitId === -99}>
{Object.keys(TrueFalseType).map(key => {
return (<option value={key} key={key}>{translate(`TrueFalseType.${key}`)}</option>);
value={localMeterEdits.disableChecks}
onChange={e => handleStringChange(e)}>
{Object.keys(DisableChecksType).map(key => {
return (<option value={key} key={key} >
{translate(`DisableChecksType.${key}`)}</option>);
})}
</Input>
</FormGroup></Col>
Expand Down
50 changes: 48 additions & 2 deletions src/client/app/components/unit/CreateUnitModalComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import '../../styles/modal.css';
import { TrueFalseType } from '../../types/items';
import TooltipMarkerComponent from '../TooltipMarkerComponent';
import TooltipHelpComponent from '../../components/TooltipHelpComponent';
import { UnitRepresentType, DisplayableType, UnitType } from '../../types/redux/units';
import { UnitRepresentType, DisplayableType, UnitType, DisableChecksType } from '../../types/redux/units';
import { tooltipBaseStyle } from '../../styles/modalStyle';
import { unitsApi } from '../../redux/api/unitsApi';
import { useTranslate } from '../../redux/componentHooks';
import { showSuccessNotification, showErrorNotification } from '../../utils/notifications';
import { MAX_VAL, MIN_VAL } from '../../redux/selectors/adminSelectors';

/**
* Defines the create unit modal form
Expand All @@ -38,7 +39,10 @@ export default function CreateUnitModalComponent() {
// The client code makes the id for the selected unit and default graphic unit be -99
// so it can tell it is not yet assigned and do the correct logic for that case.
// The units API expects these values to be undefined on call so that the database can assign their values.
id: -99
id: -99,
minVal: MIN_VAL,
maxVal: MAX_VAL,
disableChecks: DisableChecksType.reject_none
};

/* State */
Expand Down Expand Up @@ -267,6 +271,48 @@ export default function CreateUnitModalComponent() {
</FormFeedback>
</FormGroup></Col>
</Row>
<Row xs='1' lg='2'>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The min/max exist on create/edit unit pages but not in UnitsDetailComponent.tsx. I think that is fine but the "Edit Unit" button on that page should become "Details/Edit Unit" to mirror meter where it both shows more info and allows editing. I could not put a comment in that file so doing here.

{/* minVal input */}
<Col><FormGroup>
<Label for='minVal'>{translate('minVal')}</Label>
<Input id='minVal' name='minVal' type='number'
onChange={e => handleNumberChange(e)}
min={MIN_VAL}
max={state.maxVal}
defaultValue={state.minVal}
invalid={state?.minVal < MIN_VAL || state?.minVal > state?.maxVal} />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This invalid check conditions should be added to validUnit setting so the save is disabled as done for other checks.

<FormFeedback>
<FormattedMessage id="error.bounds" values={{ min: MIN_VAL, max: state.maxVal }} />
</FormFeedback>
</FormGroup></Col>
{/* maxVal input */}
<Col><FormGroup>
<Label for='maxVal'>{translate('maxVal')}</Label>
<Input id='maxVal' name='maxVal' type='number'
onChange={e => handleNumberChange(e)}
min={state.minVal}
max={MAX_VAL}
defaultValue={state.maxVal}
invalid={state?.maxVal > MAX_VAL || state?.minVal > state?.maxVal} />
<FormFeedback>
<FormattedMessage id="error.bounds" values={{ min: state.minVal, max: MAX_VAL }} />
</FormFeedback>
</FormGroup></Col>
</Row>
<Row xs='1' lg='2'>
{/* DisableChecks input */}
<Col><FormGroup>
<Label for='disableChecks'>{translate('disableChecks')}</Label>
<Input id='disableChecks' name='disableChecks' type='select'
onChange={e => handleStringChange(e)}
defaultValue={state.disableChecks}>
{Object.keys(DisableChecksType).map(key => {
return (<option value={key} key={key} >
{translate(`DisableChecksType.${key}`)}</option>);
})}
</Input>
</FormGroup></Col>
</Row>
{/* Note input */}
<FormGroup>
<Label for='note'>{translate('note')}</Label>
Expand Down
50 changes: 48 additions & 2 deletions src/client/app/components/unit/EditUnitModalComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import { useAppSelector } from '../../redux/reduxHooks';
import '../../styles/modal.css';
import { tooltipBaseStyle } from '../../styles/modalStyle';
import { TrueFalseType } from '../../types/items';
import { DisplayableType, UnitData, UnitRepresentType, UnitType } from '../../types/redux/units';
import { DisableChecksType, DisplayableType, UnitData, UnitRepresentType, UnitType } from '../../types/redux/units';
import { conversionArrow } from '../../utils/conversionArrow';
import { showErrorNotification, showSuccessNotification } from '../../utils/notifications';
import ConfirmActionModalComponent from '../ConfirmActionModalComponent';
import TooltipMarkerComponent from '../TooltipMarkerComponent';
import { MAX_VAL, MIN_VAL } from '../../redux/selectors/adminSelectors';

interface EditUnitModalComponentProps {
show: boolean;
Expand Down Expand Up @@ -193,7 +194,10 @@ export default function EditUnitModalComponent(props: EditUnitModalComponentProp
|| props.unit.preferredDisplay != state.preferredDisplay
|| props.unit.secInRate != state.secInRate
|| props.unit.suffix != state.suffix
|| props.unit.note != state.note;
|| props.unit.note != state.note
|| props.unit.minVal != state.minVal
|| props.unit.maxVal != state.maxVal
|| props.unit.disableChecks != state.disableChecks;
} else {
// Tell user that not going to update due to input issues.
showErrorNotification(`${translate('unit.input.error')}`);
Expand Down Expand Up @@ -418,6 +422,48 @@ export default function EditUnitModalComponent(props: EditUnitModalComponentProp
</FormFeedback>
</FormGroup></Col>
</Row>
<Row xs='1' lg='2'>
{/* minVal input */}
<Col><FormGroup>
<Label for='minVal'>{translate('minVal')}</Label>
<Input id='minVal' name='minVal' type='number'
onChange={e => handleNumberChange(e)}
min={MIN_VAL}
max={state.maxVal}
required value={state.minVal}
invalid={state?.minVal < MIN_VAL || state?.minVal > state?.maxVal} />
<FormFeedback>
<FormattedMessage id="error.bounds" values={{ min: MIN_VAL, max: state.maxVal }} />
</FormFeedback>
</FormGroup></Col>
{/* maxVal input */}
<Col><FormGroup>
<Label for='maxVal'>{translate('maxVal')}</Label>
<Input id='maxVal' name='maxVal' type='number'
onChange={e => handleNumberChange(e)}
min={state.minVal}
max={MAX_VAL}
required value={state.maxVal}
invalid={state?.maxVal > MAX_VAL || state?.minVal > state?.maxVal} />
<FormFeedback>
<FormattedMessage id="error.bounds" values={{ min: state.minVal, max: MAX_VAL }} />
</FormFeedback>
</FormGroup></Col>
</Row>
<Row xs='1' lg='2'>
{/* DisableChecks input */}
<Col><FormGroup>
<Label for='disableChecks'>{translate('disableChecks')}</Label>
<Input id='disableChecks' name='disableChecks' type='select'
onChange={e => handleStringChange(e)}
value={state.disableChecks}>
{Object.keys(DisableChecksType).map(key => {
return (<option value={key} key={key} >
{translate(`DisableChecksType.${key}`)}</option>);
})}
</Input>
</FormGroup></Col>
</Row>
{/* Note input */}
<FormGroup>
<Label for='note'>{translate('unit')}</Label>
Expand Down
4 changes: 2 additions & 2 deletions src/client/app/redux/selectors/adminSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { selectAllMeters, selectMeterById } from '../../redux/api/metersApi';
import { selectAdminPreferences } from '../../redux/slices/adminSlice';
import { ConversionData } from '../../types/redux/conversions';
import { MeterData, MeterTimeSortType } from '../../types/redux/meters';
import { UnitData, UnitType } from '../../types/redux/units';
import { DisableChecksType, UnitData, UnitType } from '../../types/redux/units';
import { unitsCompatibleWithUnit } from '../../utils/determineCompatibleUnits';
import { AreaUnitType } from '../../utils/getAreaUnitConversion';
import { noUnitTranslated, potentialGraphicUnits } from '../../utils/input';
Expand Down Expand Up @@ -312,7 +312,7 @@ export const selectDefaultCreateMeterValues = createAppSelector(
minDate: adminPreferences.defaultMeterMinimumDate,
maxDate: adminPreferences.defaultMeterMaximumDate,
maxError: adminPreferences.defaultMeterMaximumErrors,
disableChecks: adminPreferences.defaultMeterDisableChecks
disableChecks: DisableChecksType.reject_none
};
return defaultValues;
}
Expand Down
5 changes: 3 additions & 2 deletions src/client/app/redux/slices/adminSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { durationFormat } from '../../utils/durationFormat';
import { AreaUnitType } from '../../utils/getAreaUnitConversion';
import { preferencesApi } from '../api/preferencesApi';
import { selectOEDVersion } from '../../redux/api/versionApi';
import { DisableChecksType } from '../../types/redux/units';

export const defaultAdminState: AdminState = {
displayTitle: '',
Expand All @@ -34,7 +35,7 @@ export const defaultAdminState: AdminState = {
defaultMeterMaximumDate: moment(0).utc().add(5000, 'years').format('YYYY-MM-DD HH:mm:ssZ'),
defaultMeterReadingGap: 0,
defaultMeterMaximumErrors: 75,
defaultMeterDisableChecks: false,
defaultMeterDisableChecks: DisableChecksType.reject_none,
defaultHelpUrl: ''
};

Expand Down Expand Up @@ -127,7 +128,7 @@ export const adminSlice = createSlice({
state.defaultMeterMaximumErrors = action.payload;
state.submitted = false;
},
updateDefaultMeterDisableChecks: (state, action: PayloadAction<boolean>) => {
updateDefaultMeterDisableChecks: (state, action: PayloadAction<DisableChecksType>) => {
state.defaultMeterDisableChecks = action.payload;
state.submitted = false;
},
Expand Down
Loading
Loading