-
Notifications
You must be signed in to change notification settings - Fork 365
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
base: development
Are you sure you want to change the base?
Max min values #1396
Changes from 21 commits
92afc55
8953030
4edc46d
c29b70c
a9380c9
e72f18e
fb0b593
99f5de5
55a44d8
500c00e
d162834
1b3a182
b4f9431
ca4f316
788a59e
057b53f
00870ec
1851023
8523554
996bb4d
587ab18
5ae6979
66781a4
3d31689
9ffcc01
81d3655
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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'; | ||
|
@@ -67,6 +67,19 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr | |
|
||
const [validMeter, setValidMeter] = useState(isValidMeter(localMeterEdits)); | ||
|
||
// Ensure `minVal`, `maxVal` and `disableChecks` are set based on the unit on load | ||
useEffect(() => { | ||
huss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const selectedUnit = unitDataById[localMeterEdits.unitId]; | ||
if (selectedUnit) { | ||
setLocalMeterEdits(edits => ({ | ||
...edits, | ||
minVal: selectedUnit.minVal, | ||
maxVal: selectedUnit.maxVal, | ||
disableChecks: selectedUnit.disableChecks | ||
})); | ||
} | ||
}, [localMeterEdits.unitId]); | ||
|
||
useEffect(() => { setValidMeter(isValidMeter(localMeterEdits)); }, [localMeterEdits]); | ||
/* End State */ | ||
|
||
|
@@ -76,6 +89,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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think min/maxVal nor disableChecks needs to be set here since the useEffect above fires when unitId is updated. |
||
}); | ||
} | ||
}; | ||
|
||
// 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 | ||
|
@@ -279,7 +306,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>); | ||
})} | ||
|
@@ -599,7 +626,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('min.value')}</Label> | ||
<Input | ||
id='minVal' | ||
name='minVal' | ||
|
@@ -615,7 +642,7 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr | |
</FormGroup></Col> | ||
{/* maxVal input */} | ||
<Col><FormGroup> | ||
<Label for='maxVal'>{translate('meter.maxVal')}</Label> | ||
<Label for='maxVal'>{translate('max.value')}</Label> | ||
<Input | ||
id='maxVal' | ||
name='maxVal' | ||
|
@@ -687,16 +714,16 @@ export default function EditMeterModalComponent(props: EditMeterModalComponentPr | |
</FormGroup></Col> | ||
{/* DisableChecks input */} | ||
<Col><FormGroup> | ||
<Label for='disableChecks'>{translate('meter.disableChecks')}</Label> | ||
<Label for='disableChecks'>{translate('disable.checks')}</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> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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'; | ||
import { LineGraphRates } from '../../types/redux/graph'; | ||
import { customRateValid, isCustomRate } from '../../utils/unitInput'; | ||
|
||
|
@@ -41,7 +42,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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think per other comments this should be reject all. |
||
}; | ||
|
||
/* State */ | ||
|
@@ -72,6 +76,10 @@ export default function CreateUnitModalComponent() { | |
setState({ ...state, [e.target.name]: JSON.parse(e.target.value) }); | ||
}; | ||
|
||
const handleNumberChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
setState({ ...state, [e.target.name]: Number(e.target.value) }); | ||
}; | ||
|
||
/** | ||
* Updates the rate (both custom and regular state) including setting if custom. | ||
* @param newRate The new rate to set. | ||
|
@@ -125,13 +133,15 @@ export default function CreateUnitModalComponent() { | |
|
||
// Keeps canSave state up to date. Checks if valid and if edit made. | ||
useEffect(() => { | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove blank line. |
||
// This checks: | ||
// - Name cannot be blank | ||
// - If type of unit is suffix there must be a suffix | ||
// - The rate is set so not the custom input value. This happens if select custom value but don't input with enter. | ||
// - The custom rate is a positive integer | ||
const validUnit = state.name !== '' && | ||
(state.typeOfUnit !== UnitType.suffix || state.suffix !== '') && state.secInRate !== Number(CUSTOM_INPUT) | ||
&& (state?.minVal < MIN_VAL || state?.minVal > state?.maxVal) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. First, edit unit does not have this logic on min/max but should. Second, I think the logic is off. I made it |
||
&& customRateValid(Number(state.secInRate)); | ||
setCanSave(validUnit); | ||
}, [state]); | ||
|
@@ -423,19 +433,59 @@ export default function CreateUnitModalComponent() { | |
</FormGroup> | ||
</Col> | ||
</Row> | ||
<Row xs='1' lg='2'> | ||
{/* minVal input */} | ||
<Col><FormGroup> | ||
<Label for='minVal'>{translate('min.val')}</Label> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be |
||
<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} /> | ||
<FormFeedback> | ||
<FormattedMessage id="error.bounds" values={{ min: MIN_VAL, max: state.maxVal }} /> | ||
</FormFeedback> | ||
</FormGroup></Col> | ||
{/* maxVal input */} | ||
<Col><FormGroup> | ||
<Label for='maxVal'>{translate('max.value')}</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('disable.checks')}</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> | ||
<Label for='note'>{translate('note')}</Label> | ||
<Input | ||
id="note" | ||
name="note" | ||
type="textarea" | ||
value={state.note} | ||
id='note' | ||
name='note' | ||
type='textarea' | ||
onChange={e => handleStringChange(e)} | ||
/> | ||
value={state.note} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. value seems above onChange in other places so maybe put back above it. |
||
</FormGroup> | ||
</Container> | ||
</ModalBody> | ||
</Container></ModalBody> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ModalBody is a tag own its on line when started so probably should put this on a separate line as it was before. |
||
<ModalFooter> | ||
{/* Hides the modal */} | ||
<Button color="secondary" onClick={handleClose}> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the design doc called for removing min, max and this since it is now controlled by the unit for the default. Note this will change the DB and other files. I did a quick search and they probably are not used anywhere so hopefully removing does not cause issues.