Skip to content

Commit

Permalink
feat: add simple select input
Browse files Browse the repository at this point in the history
  • Loading branch information
pl-buiquang committed Dec 5, 2024
1 parent 4669c0f commit d79cd5b
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/__tests__/data/cohortCreation/documentCriteria.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const completeDocumentCriteria: DocumentDataType = {
docStatuses: [DocumentStatuses.FINAL, DocumentStatuses.PRELIMINARY],
docType: ['crh-j', 'crh-chir'],
search: 'cancer',
searchBy: [SearchByTypes.TEXT],
searchBy: SearchByTypes.TEXT,
encounterService: [
{
above_levels_ids: '8312002244',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,17 @@ const replaceTime = (date?: string) => {
return date?.replace('T00:00:00Z', '') ?? null
}

const unbuildSelect = (value: string, existingValue?: string[]) => {
const unbuildMultiSelect = (value: string, existingValue?: string[]) => {
const values = value ? value.split(',').map((v) => v.trim()) : null
return [...(existingValue || []), ...(values || [])]
}

const buildSelect = (criterion: string[] | null, hierarchyUrl?: string) => {
return criterion && criterion.length > 0
? criterion.map((item) => (hierarchyUrl ? `${hierarchyUrl}|${item}` : item)).reduce(searchReducer, '')
: ''
const buildSelect = (criterion: string[] | string | null, hierarchyUrl?: string) => {
if (!criterion) {
return ''
}
const values = Array.isArray(criterion) ? criterion : [criterion]
return values.map((item) => (hierarchyUrl ? `${hierarchyUrl}|${item}` : item)).reduce(searchReducer, '')
}

const buildLabelObjectFilter = (
Expand Down Expand Up @@ -226,10 +228,10 @@ const buildNumberComparatorFilter = (
return `${comparatorToFilter(numberAndComparator.comparator)}${numberAndComparator.value}`
}

const buildWithDocumentFilter = (withDocument: string[], daysOfDelay: number | null) => {
if (withDocument && withDocument.length === 1 && withDocument.at(0) !== DocumentAttachmentMethod.NONE) {
const buildWithDocumentFilter = (withDocument: string | null, daysOfDelay: number | null) => {
if (withDocument !== DocumentAttachmentMethod.NONE) {
return `${
withDocument.at(0) === DocumentAttachmentMethod.ACCESS_NUMBER
withDocument === DocumentAttachmentMethod.ACCESS_NUMBER
? DocumentAttachmentMethod.ACCESS_NUMBER
: `INFERENCE_TEMPOREL${daysOfDelay ? `_${daysOfDelay}_J` : ''}`
}`
Expand All @@ -256,7 +258,7 @@ const parseDocumentAttachment = (value: string) => {
}

const unbuildDocumentAttachment = (value: string) => {
return [parseDocumentAttachment(value).documentAttachmentMethod]
return parseDocumentAttachment(value).documentAttachmentMethod
}

const unbuildDaysOfDelay = (value: string) => {
Expand All @@ -281,7 +283,7 @@ export const UNBUILD_MAPPERS = {
existingValue: DataTypes,
fhirkey: string,
args: Array<DataTypes>
) => Promise.resolve(unbuildSelect(val, existingValue as string[])),
) => Promise.resolve(unbuildMultiSelect(val, existingValue as string[])),
unbuildEncounterService: async (
val: string,
deid: boolean,
Expand Down Expand Up @@ -319,7 +321,7 @@ export const UNBUILD_MAPPERS = {
fhirkey: string,
args: Array<DataTypes>
) => {
return Promise.resolve([fhirkey])
return Promise.resolve(fhirkey)
},
unbuildDocumentAttachment: async (
val: string,
Expand Down Expand Up @@ -364,10 +366,6 @@ export const BUILD_MAPPERS = {
buildComparator: (val: DataTypes, key: FhirKey, deidentified: boolean, args: Array<DataTypes | BuilderMethod>) =>
buildNumberComparatorFilter(val as NumberAndComparatorDataType, args[0] as string),
buildWithDocument: (val: DataTypes, key: FhirKey, deidentified: boolean, args: Array<DataTypes | BuilderMethod>) =>
buildWithDocumentFilter(val as string[], args[0] as number | null),
// utility meta functions
skipIf: (val: DataTypes, key: FhirKey, deidentified: boolean, args: Array<DataTypes | BuilderMethod>) => {
return args[1] === args[2] ? undefined : (args[0] as BuilderMethod)(val, key, deidentified, args.slice(3))
},
buildWithDocumentFilter(val as string, args[0] as number | null),
noop: (val: DataTypes, key: FhirKey, deidentified: boolean, args: Array<DataTypes | BuilderMethod>) => undefined
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,12 @@ const chipForDateLabel = (dateRange: NewDurationRangeType, word?: string) => {
)
}

const getSearchDocumentLabel = (value: string, searchBy: LabelObject[]) => {
const loc = searchBy && searchBy.find((l) => l.id === SearchByTypes.TEXT) ? 'document' : 'titre du document'
const getSearchDocumentLabel = (value: string, searchBy: string | null) => {
const loc = searchBy === SearchByTypes.DESCRIPTION ? 'titre du document' : 'document'
return `Contient "${value}" dans le ${loc}`
}

const getDocumentTypesLabel = (values: string[]) => {
const allTypes = new Set(allDocTypes.docTypes.map((docType) => docType.type))
const typeGroups = allDocTypes.docTypes.reduce((acc, docType) => {
acc[docType.type] = acc[docType.type] ? [...acc[docType.type], docType.code] : [docType.code]
return acc
Expand Down Expand Up @@ -121,8 +120,7 @@ const getIdsListLabels = (values: string, name: string) => {
return `Contient les ${name} : ${labels}`
}

const getAttachmentMethod = (value: string[], daysOfDelay: string | null) => {
const documentAttachementMethod = value.at(0)
const getAttachmentMethod = (documentAttachementMethod: string, daysOfDelay: string | null) => {
if (documentAttachementMethod === DocumentAttachmentMethod.INFERENCE_TEMPOREL) {
return `Rattachement aux documents par ${DocumentAttachmentMethodLabel.INFERENCE_TEMPOREL.toLocaleLowerCase()}${
daysOfDelay !== '' && daysOfDelay !== null ? ` de ${daysOfDelay} jour(s)` : ''
Expand Down Expand Up @@ -163,14 +161,16 @@ const getLabelsForAutoCompleteItem = (
}

const chipFromAutoComplete = (
val: string[] | null,
val: string[] | string | null,
item: AutoCompleteItem,
valueSets: ValueSetStore,
label?: string,
prependCode?: boolean
) => {
if (val === null) return null
const values = Array.isArray(val) ? val : [val]
return chipFromLabelObject(
(val as string[]).map((v) => ({ id: v, label: v })),
values.map((v) => ({ id: v, label: v })),
item,
getLabelsForAutoCompleteItem,
valueSets,
Expand Down Expand Up @@ -251,7 +251,13 @@ export const CHIPS_DISPLAY_METHODS = {
valueSets: ValueSetStore,
args: Array<ChipDisplayMethod | DataTypes>
) =>
chipFromAutoComplete(val as string[], item as AutoCompleteItem, valueSets, args[0] as string, args[1] as boolean),
chipFromAutoComplete(
val as string[] | string,
item as AutoCompleteItem,
valueSets,
args[0] as string,
args[1] as boolean
),
executiveUnit: (
val: DataTypes,
item: GenericCriteriaItem,
Expand Down Expand Up @@ -282,13 +288,13 @@ export const CHIPS_DISPLAY_METHODS = {
item: GenericCriteriaItem,
valueSets: ValueSetStore,
args: Array<ChipDisplayMethod | DataTypes>
) => getAttachmentMethod(val as string[], args[0] as string),
) => getAttachmentMethod(val as string, args[0] as string),
getSearchDocumentLabel: (
val: DataTypes,
item: GenericCriteriaItem,
valueSets: ValueSetStore,
args: Array<ChipDisplayMethod | DataTypes>
) => getSearchDocumentLabel(val as string, args[0] as LabelObject[]),
) => getSearchDocumentLabel(val as string, args[0] as string),
getDocumentTypesLabel: (
val: DataTypes,
item: GenericCriteriaItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const DEFAULT_BUILD_METHOD: Record<CriteriaFormItemType, BuilderMethod> = {
calendarRange: BUILD_MAPPERS.buildDate,
durationRange: BUILD_MAPPERS.buildDuration,
text: BUILD_MAPPERS.buildSearch,
select: BUILD_MAPPERS.buildSelect,
autocomplete: BUILD_MAPPERS.buildSelect,
number: BUILD_MAPPERS.buildSearch,
executiveUnit: BUILD_MAPPERS.buildLabelObject,
Expand All @@ -155,6 +156,7 @@ const DEFAULT_UNBUILD_METHOD: Record<
calendarRange: UNBUILD_MAPPERS.unbuildDate,
durationRange: UNBUILD_MAPPERS.unbuildDuration,
text: UNBUILD_MAPPERS.unbuildSearch,
select: UNBUILD_MAPPERS.unbuildSearch,
autocomplete: UNBUILD_MAPPERS.unbuildSelect,
number: UNBUILD_MAPPERS.unbuildSearch,
executiveUnit: UNBUILD_MAPPERS.unbuildEncounterService,
Expand All @@ -171,6 +173,7 @@ const DEFAULT_CHIPS_DISPLAY_METHODS: Record<CriteriaFormItemType, ChipDisplayMet
calendarRange: CHIPS_DISPLAY_METHODS.calendarRange,
durationRange: CHIPS_DISPLAY_METHODS.durationRange,
text: CHIPS_DISPLAY_METHODS.raw,
select: CHIPS_DISPLAY_METHODS.autocomplete,
autocomplete: CHIPS_DISPLAY_METHODS.autocomplete,
number: CHIPS_DISPLAY_METHODS.raw,
executiveUnit: CHIPS_DISPLAY_METHODS.executiveUnit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import DurationRange from 'components/ui/Inputs/DurationRange'
import { IndeterminateCheckBoxOutlined } from '@mui/icons-material'
import { CriteriaLabel } from 'components/ui/CriteriaLabel'
import { Comparators } from 'types/requestCriterias'
import SimpleSelect from 'components/ui/Inputs/SimpleSelect'

/************************************************************************************/
/* Criteria Form Item Renderer */
Expand Down Expand Up @@ -111,6 +112,16 @@ const FORM_ITEM_RENDERER: { [key in CriteriaFormItemType]: CriteriaFormItemView<
}
/>
),
select: (props) => {
return (
<SimpleSelect
value={props.value}
label={props.definition.label}
options={props.definition.choices}
onChange={(val) => props.updateData(val)}
/>
)
},
autocomplete: (props) => {
const arrayPropValue = isArray(props.value) ? props.value : [props.value]
const codeSystem = props.getValueSetOptions(props.definition.valueSetId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ export type CalendarItem = BaseCriteriaItem &
withOptionIncludeNull?: boolean
}

export type SelectItem = BaseCriteriaItem & {
type: 'select'
choices: LabelObject[]
}

export type AutoCompleteItem = BaseCriteriaItem & {
type: 'autocomplete'
noOptionsText: string
Expand Down Expand Up @@ -137,6 +142,7 @@ export type TextWithCheckItem = BaseCriteriaItem &
// Union of all criteria item types
export type CriteriaItems =
| CalendarItem
| SelectItem
| AutoCompleteItem
| ExecutiveUnitItem
| TextWithCheckItem
Expand Down Expand Up @@ -192,6 +198,7 @@ export type DataTypeMapping = {
calendarRange: CriteriaTypeMapping<CalendarItem, NewDurationRangeType>
durationRange: CriteriaTypeMapping<DurationItem, NewDurationRangeType>
text: CriteriaTypeMapping<TextCriteriaItem, string>
select: CriteriaTypeMapping<SelectItem, string>
autocomplete: CriteriaTypeMapping<AutoCompleteItem, string[]>
number: CriteriaTypeMapping<NumberCriteriaItem, number>
executiveUnit: CriteriaTypeMapping<ExecutiveUnitItem, Hierarchy<ScopeElement, string>[]>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type DocumentDataType = CommonCriteriaData &
WithEncounterStatusDataType & {
type: CriteriaType.DOCUMENTS
search: string
searchBy: string[] | null
searchBy: string | null
docType: string[] | null
docStatuses: string[] | null
}
Expand All @@ -36,7 +36,7 @@ export const form: () => CriteriaForm<DocumentDataType> = () => ({
encounterEndDate: null,
encounterStatus: [],
search: '',
searchBy: [SearchByTypes.TEXT],
searchBy: SearchByTypes.TEXT,
docType: null,
docStatuses: null
},
Expand All @@ -58,11 +58,9 @@ export const form: () => CriteriaForm<DocumentDataType> = () => ({
},
{
valueKey: 'searchBy',
type: 'autocomplete',
type: 'select',
label: 'Rechercher dans :',
valueSetId: 'docSearchBy',
singleChoice: true,
valueSetData: [
choices: [
{ id: SearchByTypes.TEXT, label: 'Corps du document' },
{ id: SearchByTypes.DESCRIPTION, label: 'Titre du document' }
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
WithEncounterDateDataType,
WithEncounterStatusDataType
} from '../CriteriaForm/types'
import { DocumentAttachmentMethod } from 'types/searchCriterias'
import { DocumentAttachmentMethod, DocumentAttachmentMethodLabel } from 'types/searchCriterias'
import { getConfig } from 'config'
import { SourceType } from 'types/scope'

Expand All @@ -22,7 +22,7 @@ export type ImagingDataType = CommonCriteriaData &
studyProcedure: string
numberOfSeries: NumberAndComparatorDataType
numberOfIns: NumberAndComparatorDataType
withDocument: string[]
withDocument: string
daysOfDelay: string | null
studyUid: string
seriesDate: NewDurationRangeType | null
Expand Down Expand Up @@ -53,7 +53,7 @@ export const form: () => CriteriaForm<ImagingDataType> = () => ({
studyProcedure: '',
numberOfSeries: { value: 1, comparator: Comparators.GREATER_OR_EQUAL },
numberOfIns: { value: 1, comparator: Comparators.GREATER_OR_EQUAL },
withDocument: [DocumentAttachmentMethod.NONE],
withDocument: DocumentAttachmentMethod.NONE,
daysOfDelay: null,
studyUid: '',
seriesDate: null,
Expand Down Expand Up @@ -166,13 +166,22 @@ export const form: () => CriteriaForm<ImagingDataType> = () => ({
},
{
valueKey: 'withDocument',
type: 'autocomplete',
type: 'select',
label: 'Méthode de rattachement à un document',
extraLabel: () => 'Méthode de rattachement à un document',
valueSetId: 'documentAttachementMethod',
singleChoice: true,
valueSetData: getConfig().features.imaging.valueSets.documentAttachementMethod.data,
noOptionsText: 'Veuillez entrer une méthode de rattachement',
choices: [
{
id: DocumentAttachmentMethod.NONE,
label: DocumentAttachmentMethodLabel.NONE
},
{
id: DocumentAttachmentMethod.ACCESS_NUMBER,
label: DocumentAttachmentMethodLabel.ACCESS_NUMBER
},
{
id: DocumentAttachmentMethod.INFERENCE_TEMPOREL,
label: DocumentAttachmentMethodLabel.INFERENCE_TEMPOREL
}
],
buildInfo: {
fhirKey: ImagingParamsKeys.WITH_DOCUMENT,
buildMethod: 'buildWithDocument',
Expand Down
28 changes: 28 additions & 0 deletions src/components/ui/Inputs/SimpleSelect/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react'
import { FormControl, InputLabel, Select, MenuItem } from '@mui/material'
import { LabelObject } from 'types/searchCriterias'

type SimpleSelectProps = {
label?: string
value: string
onChange: (value: string) => void
options: LabelObject[]
}

const SimpleSelect = (props: SimpleSelectProps) => {
const { label, value, onChange } = props
return (
<FormControl variant="outlined" style={{ width: '100%' }}>
{label && <InputLabel>{label}</InputLabel>}
<Select value={value} onChange={(event) => onChange(event.target.value)} variant="outlined" label={label}>
{props.options.map((option) => (
<MenuItem key={option.id} value={option.id}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
)
}

export default SimpleSelect
20 changes: 1 addition & 19 deletions src/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ type AppConfig = {
enabled: boolean
valueSets: {
imagingModalities: ValueSetConfig
documentAttachementMethod: ValueSetConfig
}
extensions: {
imagingStudyUidUrl: string
Expand Down Expand Up @@ -249,24 +248,7 @@ let config: AppConfig = {
imaging: {
enabled: true,
valueSets: {
imagingModalities: { url: '' },
documentAttachementMethod: {
url: 'documentAttachementMethod',
data: [
{
id: DocumentAttachmentMethod.NONE,
label: DocumentAttachmentMethodLabel.NONE
},
{
id: DocumentAttachmentMethod.ACCESS_NUMBER,
label: DocumentAttachmentMethodLabel.ACCESS_NUMBER
},
{
id: DocumentAttachmentMethod.INFERENCE_TEMPOREL,
label: DocumentAttachmentMethodLabel.INFERENCE_TEMPOREL
}
]
}
imagingModalities: { url: '' }
},
extensions: {
imagingStudyUidUrl: ''
Expand Down

0 comments on commit d79cd5b

Please sign in to comment.