Skip to content

Commit

Permalink
fix(validator): limits as warning instead of error
Browse files Browse the repository at this point in the history
  • Loading branch information
Birkbjo committed Sep 25, 2023
1 parent f80d67c commit 6da2989
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 18 deletions.
15 changes: 11 additions & 4 deletions src/data-workspace/data-entry-cell/data-entry-cell.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
z-index: 1;
}


.highlighted.active {
outline-color: var(--theme-focus) !important;
}
Expand All @@ -56,6 +55,15 @@
);
}

.warning:not(.active) {
background: var(--colors-yellow100);
outline: 1px solid var(--colors-red600);
}

.warning:hover {
background: var(--colors-yellow200);
}

.invalid:not(.active) {
background: var(--colors-red200);
outline: 1px solid var(--colors-red600);
Expand All @@ -72,7 +80,6 @@
background: #d8eeda;
}


.topRightIndicator {
position: absolute;
top: 0;
Expand Down Expand Up @@ -111,6 +118,6 @@

@media print {
.hideForPrint {
composes: hideForPrint from '../../app/app.css'
composes: hideForPrint from '../../app/app.css';
}
}
}
12 changes: 9 additions & 3 deletions src/data-workspace/data-entry-cell/inner-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
useDataValueParams,
useValueStore,
useSyncErrorsStore,
useEntryFormStore,
} from '../../shared/index.js'
import styles from './data-entry-cell.module.css'
import { ValidationTooltip } from './validation-tooltip.js'
Expand Down Expand Up @@ -94,22 +95,27 @@ export function InnerWrapper({
const clearSyncError = useSyncErrorsStore(
(state) => state.clearErrorByDataValueParams
)
const warning = useEntryFormStore((state) => state.getWarning(fieldname))
const fieldErrorMessage = error ?? warning

const errorMessage =
error && syncError ? (
<div className={styles.validationTooltipMessage}>
<div>{error}</div>
<div>{fieldErrorMessage}</div>
<div>{syncError.displayMessage}</div>
</div>
) : (
error ?? syncError?.displayMessage
fieldErrorMessage ?? syncError?.displayMessage
)

const valueSynced = data.lastSyncedValue === value
const showSynced = dirty && valueSynced
// todo: maybe use mutation state to improve this style handling
// see https://dhis2.atlassian.net/browse/TECH-1316
const cellStateClassName = invalid
? styles.invalid
: warning
? styles.warning
: activeMutations === 0 && showSynced
? styles.synced
: null
Expand Down Expand Up @@ -137,7 +143,7 @@ export function InnerWrapper({
<ValidationTooltip
fieldname={fieldname}
active={active}
invalid={invalid || !!syncError}
invalid={warning || invalid || !!syncError}
content={errorMessage}
>
<div
Expand Down
26 changes: 23 additions & 3 deletions src/data-workspace/inputs/generic-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ import { useField } from 'react-final-form'
import {
NUMBER_TYPES,
VALUE_TYPES,
useEntryFormStore,
useSetDataValueMutation,
} from '../../shared/index.js'
import { useMinMaxLimits } from '../use-min-max-limits.js'
import styles from './inputs.module.css'
import { InputPropTypes } from './utils.js'
import { validateByValueTypeWithLimits } from './validators.js'
import {
validateByValueType,
limitValidator,

Check failure on line 16 in src/data-workspace/inputs/generic-input.js

View workflow job for this annotation

GitHub Actions / lint

limitValidator not found in './validators.js'

Check failure on line 16 in src/data-workspace/inputs/generic-input.js

View workflow job for this annotation

GitHub Actions / lint

'limitValidator' is defined but never used
warningValidateByValueType,
} from './validators.js'

const htmlTypeAttrsByValueType = {
[VALUE_TYPES.DATE]: 'date',
Expand Down Expand Up @@ -46,9 +51,24 @@ export const GenericInput = ({
return value.trim()
}
}
const setWarning = useEntryFormStore((state) => state.setWarning)

const { input, meta } = useField(fieldname, {
validate: validateByValueTypeWithLimits(valueType, limits),
subscription: { value: true, dirty: true, valid: true, data: true },
validate: (value) => {
const warningValidator = warningValidateByValueType(
valueType,
limits
)
const warningValidationResult = warningValidator(value)
setWarning(fieldname, warningValidationResult)
return validateByValueType(valueType, limits)(value)
},
subscription: {
value: true,
dirty: true,
valid: true,
data: true,
},
format: formatValue,
formatOnBlur: true,
// This is required to ensure form is validated on first page load
Expand Down
8 changes: 7 additions & 1 deletion src/data-workspace/inputs/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,19 @@ export const validatorsByValueType = {
[VALUE_TYPES.URL]: url,
}

export const validateByValueTypeWithLimits = (valueType, limits) => {
export const validateByValueType = (valueType) => {
const validators = []

if (validatorsByValueType[valueType]) {
validators.push(validatorsByValueType[valueType])
}

return composeValidators(...validators)
}

export const warningValidateByValueType = (valueType, limits) => {
const validators = []

if (
CAN_HAVE_LIMITS_TYPES.includes(valueType) &&
Number.isFinite(limits?.min) &&
Expand Down
25 changes: 18 additions & 7 deletions src/shared/stores/entry-form-store.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import { setIn, getIn } from 'final-form'
import create from 'zustand'

import { devtools } from 'zustand/middleware'
const inititalState = {
errors: {},
warnings: {},
}

export const useEntryFormStore = create((set, get) => ({
...inititalState,
setErrors: (errors) => set({ errors: errors ?? {} }),
getErrors: () => get().errors,
getNumberOfErrors: () => countLeaves(get().getErrors()),
}))
export const useEntryFormStore = create(
devtools((set, get) => ({
...inititalState,
setErrors: (errors) => set({ errors: errors ?? {} }),
getErrors: () => get().errors,
getNumberOfErrors: () => countLeaves(get().getErrors()),
getWarnings: () => get().warnings,
getWarning: (fieldname) => getIn(get().getWarnings(), fieldname),
setWarning: (fieldname, warning) => {
const warnings = get().getWarnings() || {}
const newWarnings = setIn(warnings, fieldname, warning)
set({ warnings: newWarnings })
},
}))
)

// errors object is the same shape as form-Values
// eg. { [dataElementId] : {
Expand Down

0 comments on commit 6da2989

Please sign in to comment.