Skip to content

Commit 4363124

Browse files
authored
Fix clearing optional dashboard filters (#2913) (#3003)
1 parent dbf1710 commit 4363124

4 files changed

Lines changed: 32 additions & 3 deletions

File tree

plugins/ui/apps/vue-mri-ui-lib/src/components/ShinyViewer/CompleteRequiredFiltersModal.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ import MessageBox from '../MessageBox.vue'
154154
import appButton from '@/lib/ui/app-button.vue'
155155
import ConceptSetTypeaheadField from './ConceptSetTypeaheadField.vue'
156156
import type { WizardFieldDefinition } from '@/utils/dashboardFlowUtils'
157-
import { isConditionField } from '@/utils/dashboardFlowUtils'
157+
import { isConditionField, normalizeWizardFieldValueForComparison } from '@/utils/dashboardFlowUtils'
158158
import InputParser from '@/lib/utils/InputParser'
159159
import RangeConstraintTokenDefinition from '@/lib/utils/RangeConstraintTokenDefinition'
160160
import RangeConstraintPatternDefinition from '@/lib/utils/RangeConstraintPatternDefinition'
@@ -460,7 +460,8 @@ function markFieldDirty(fieldId: string) {
460460
}
461461
462462
// For regular fields
463-
const hasChanged = currentValue !== initialValue
463+
const hasChanged =
464+
normalizeWizardFieldValueForComparison(currentValue) !== normalizeWizardFieldValueForComparison(initialValue)
464465
465466
if (hasChanged) {
466467
dirtyFields.add(fieldId)

plugins/ui/apps/vue-mri-ui-lib/src/composables/useDashboardFlow.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,12 @@ export function useDashboardFlow(
998998
}
999999
const rawValue = rawInput?.value ?? rawInput
10001000
if (rawValue === null || typeof rawValue === 'undefined' || String(rawValue).trim() === '') {
1001+
if (constraintType === 'text' || constraintType === 'conceptSet') {
1002+
return dispatch('updateConstraintValue', {
1003+
constraintId: constraint.id,
1004+
value: [],
1005+
})
1006+
}
10011007
return Promise.reject(new Error(`Missing value for ${constraint.props.name || constraint.id}`))
10021008
}
10031009
const finalDisplayValue = displayValue || rawInput?.displayName || String(rawValue)

plugins/ui/apps/vue-mri-ui-lib/src/utils/__tests__/dashboardFlowUtils.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { describe, expect, it } from 'vitest'
2-
import { getWizardFlow, isWizardVisibleOnSurface, parseNumericInput, validateRequiredFields } from '../dashboardFlowUtils'
2+
import {
3+
getWizardFlow,
4+
isWizardVisibleOnSurface,
5+
normalizeWizardFieldValueForComparison,
6+
parseNumericInput,
7+
validateRequiredFields,
8+
} from '../dashboardFlowUtils'
39

410
const createExpression = (operator: string, value: string | number) => ({
511
type: 'Expression' as const,
@@ -214,3 +220,15 @@ describe('wizard metadata helpers', () => {
214220
expect(getWizardFlow({ flow: 'table1-config' })).toBe('table1-config')
215221
})
216222
})
223+
224+
describe('wizard field value helpers', () => {
225+
it('treats null, undefined, and an empty string as the same empty form value', () => {
226+
expect(normalizeWizardFieldValueForComparison(null)).toBe('')
227+
expect(normalizeWizardFieldValueForComparison(undefined)).toBe('')
228+
expect(normalizeWizardFieldValueForComparison('')).toBe('')
229+
})
230+
231+
it('preserves non-empty field values', () => {
232+
expect(normalizeWizardFieldValueForComparison('FEMALE')).toBe('FEMALE')
233+
})
234+
})

plugins/ui/apps/vue-mri-ui-lib/src/utils/dashboardFlowUtils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ export interface RequiredFieldValidationResult {
100100
breakdown: FieldComparisonBreakdown[]
101101
}
102102

103+
export function normalizeWizardFieldValueForComparison(value: unknown): unknown {
104+
return value === null || typeof value === 'undefined' ? '' : value
105+
}
106+
103107
function getLastPathSegment(path: string): string {
104108
const tokens = path.split('.')
105109
return tokens[tokens.length - 1] || path

0 commit comments

Comments
 (0)