Skip to content

Commit

Permalink
fix(list): add additional list filters to dataElementGroup/Set
Browse files Browse the repository at this point in the history
  • Loading branch information
Birkbjo committed Dec 5, 2024
1 parent 8790d86 commit 0e4b181
Show file tree
Hide file tree
Showing 12 changed files with 164 additions and 92 deletions.
6 changes: 6 additions & 0 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,12 @@ msgstr "Advanced"
msgid "Set up the basic information for this Indicator Type."
msgstr "Set up the basic information for this Indicator Type."

msgid "Delete source indicator types"
msgstr "Delete source indicator types"

msgid "Merge"
msgstr "Merge"

msgid "Longitude"
msgstr "Longitude"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,21 @@ export const IgnoreApprovalFilter = () => {
/>
)
}

export const CompulsoryFilter = () => {
return (
<BooleanFilter
filterKey="compulsory"
label={getTranslatedProperty('compulsory')}
/>
)
}

export const DataDimensionFilter = () => {
return (
<BooleanFilter
filterKey="dataDimension"
label={getTranslatedProperty('dataDimension')}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import i18n from '@dhis2/d2-i18n'
import React from 'react'
import { useSectionListFilter } from '../../../../lib'
import { createFilterDataQuery } from './createFilterDataQuery'
import { ModelFilterSelect } from './ModelFilter'

const query = createFilterDataQuery('dataElements')

export const DataElementFilter = () => {
const [filter, setFilter] = useSectionListFilter('dataElement')

const selected = filter?.[0]

return (
<ModelFilterSelect
placeholder={i18n.t('Data element')}
query={query}
selected={selected}
onChange={({ selected }) =>
setFilter(selected ? [selected] : undefined)
}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import i18n from '@dhis2/d2-i18n'
import React from 'react'
import { useSectionListFilter } from '../../../../lib'
import { createFilterDataQuery } from './createFilterDataQuery'
import { ModelFilterSelect } from './ModelFilter'

const query = createFilterDataQuery('dataElementGroups')

export const DataElementGroupFilter = () => {
const [filter, setFilter] = useSectionListFilter('dataElementGroup')

const selected = filter?.[0]

return (
<ModelFilterSelect
placeholder={i18n.t('Data element group')}
query={query}
selected={selected}
onChange={({ selected }) =>
setFilter(selected ? [selected] : undefined)
}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import i18n from '@dhis2/d2-i18n'
import React from 'react'
import { useSectionListFilter } from '../../../../lib'
import { createFilterDataQuery } from './createFilterDataQuery'
import { ModelFilterSelect } from './ModelFilter'

const query = createFilterDataQuery('dataElementGroupSets')

export const DataElementGroupSetFilter = () => {
const [filter, setFilter] = useSectionListFilter('dataElementGroupSet')

const selected = filter?.[0]

return (
<ModelFilterSelect
placeholder={i18n.t('Data element group set')}
query={query}
selected={selected}
onChange={({ selected }) =>
setFilter(selected ? [selected] : undefined)
}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,34 @@ import {
ValueTypeSelectionFilter,
FormTypeFilter,
DataSetFilter,
DataElementGroupFilter,
DataElementGroupSetFilter,
DataElementFilter,
CompulsoryFilter,
DataDimensionFilter,
} from '.'

type FilterKeyToComponentMap = Partial<Record<ConfigurableFilterKey, React.FC>>

const filterKeyToComponentMap: FilterKeyToComponentMap = {
aggregationType: AggregationTypeFilter,
category: Categoryfilter,
formType: FormTypeFilter,
indicatorType: IndicatorFilter,
categoryOption: CategoryOptionFilter,
categoryCombo: CategoryComboFilter,
categoryOption: CategoryOptionFilter,
categoryOptionGroup: CategoryOptionGroupFilter,
domainType: DomainTypeSelectionFilter,
valueType: ValueTypeSelectionFilter,
aggregationType: AggregationTypeFilter,
publicAccess: PublicAccessFilter,
compulsory: CompulsoryFilter,
dataDimension: DataDimensionFilter,
dataDimensionType: DataDimensionTypeFilter,
ignoreApproval: IgnoreApprovalFilter,
dataElement: DataElementFilter,
dataElementGroup: DataElementGroupFilter,
dataElementGroupSet: DataElementGroupSetFilter,
dataSet: DataSetFilter,
domainType: DomainTypeSelectionFilter,
formType: FormTypeFilter,
ignoreApproval: IgnoreApprovalFilter,
indicatorType: IndicatorFilter,
publicAccess: PublicAccessFilter,
valueType: ValueTypeSelectionFilter,
}

export const DynamicFilters = () => {
Expand Down
3 changes: 3 additions & 0 deletions src/components/sectionList/filters/filterSelectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ export * from './BooleanFilters'
export * from './CategoryOptionFilter'
export * from './IndicatorFilter'
export * from './DataSetFilter'
export * from './DataElementGroupSet'
export * from './DataElementGroup'
export * from './DataElementFilter'
21 changes: 13 additions & 8 deletions src/lib/constants/translatedModelProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,32 @@ const TRANSLATED_PROPERTY: Record<string, string> = {
categoryCombo: i18n.t('Category combination'),
categoryOption: i18n.t('Category option'),
code: i18n.t('Code'),
compulsory: i18n.t('Compulsory'),
created: i18n.t('Created'),
createdBy: i18n.t('Created by'),
dataElement: i18n.t('Data element'),
dataElementGroup: i18n.t('Data element group'),
dataElementGroupSet: i18n.t('Data element group set'),
dataDimension: i18n.t('Data dimension'),
dataDimensionType: i18n.t('Data dimension type'),
dataSet: i18n.t('Data set'),
description: i18n.t('Description'),
domainType: i18n.t('Domain type'),
favorite: i18n.t('Favorite'),
formName: i18n.t('Form name'),
formType: i18n.t('Form type'),
href: i18n.t('API URL'),
id: i18n.t('Id'),
ignoreApproval: i18n.t('Ignore data approval'),
indicatorType: i18n.t('Indicator type'),
lastUpdatedBy: i18n.t('Last updated by'),
created: i18n.t('Created'),
domainType: i18n.t('Domain type'),
formType: i18n.t('Form type'),
dataSet: i18n.t('Data set'),
lastUpdated: i18n.t('Last updated'),
lastUpdatedBy: i18n.t('Last updated by'),
name: i18n.t('Name'),
sharing: i18n.t('Sharing'),
shortName: i18n.t('Short name'),
valueType: i18n.t('Value type'),
user: i18n.t('Owner'), // user refers to the owner of the object
valueType: i18n.t('Value type'),
zeroIsSignificant: i18n.t('Zero is significant'),
dataDimensionType: i18n.t('Data dimension type'),
ignoreApproval: i18n.t('Ignore data approval'),
}

const camelCaseToSentenceCase = (camelCase: string) =>
Expand Down
33 changes: 22 additions & 11 deletions src/lib/sectionList/filters/filterConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,27 @@ const zodArrayIds = z.array(z.string().refine((val) => isValidUid(val)))
export const filterParamsSchema = z
.object({
[IDENTIFIABLE_FILTER_KEY]: z.string(),

aggregationType: z.array(z.nativeEnum(DataElement.aggregationType)),
categoryCombo: zodArrayIds,
category: zodArrayIds,
formType: z.array(z.nativeEnum(DataSet.formType)),
categoryCombo: zodArrayIds,
categoryOption: zodArrayIds,
categoryOptionGroup: zodArrayIds,
compulsory: z.boolean(),
dataDimension: z.boolean(),
dataDimensionType: z.nativeEnum(Category.dataDimensionType),
dataElement: zodArrayIds,
dataElementGroup: zodArrayIds,
dataElementGroupSet: zodArrayIds,
dataSet: zodArrayIds,
domainType: z.array(z.nativeEnum(DataElement.domainType)),
formType: z.array(z.nativeEnum(DataSet.formType)),
ignoreApproval: z.boolean(),
indicatorType: zodArrayIds,
publicAccess: z.array(
z.string().refine((val) => parseAccessString(val) !== null)
),
valueType: z.array(z.nativeEnum(DataElement.valueType)),
dataDimensionType: z.nativeEnum(Category.dataDimensionType),
ignoreApproval: z.boolean(),
indicatorType: zodArrayIds,
})
.partial()

Expand All @@ -35,18 +41,23 @@ Mapping each filter to a config object that handles encoding/decoding */
export const filterQueryParamType = {
[IDENTIFIABLE_FILTER_KEY]: StringParam,
aggregationType: CustomDelimitedArrayParam,
domainType: CustomDelimitedArrayParam,
valueType: CustomDelimitedArrayParam,
dataSet: CustomDelimitedArrayParam,
category: CustomDelimitedArrayParam,
formType: CustomDelimitedArrayParam,
categoryOption: CustomDelimitedArrayParam,
categoryCombo: CustomDelimitedArrayParam,
categoryOption: CustomDelimitedArrayParam,
categoryOptionGroup: CustomDelimitedArrayParam,
publicAccess: CustomDelimitedArrayParam,
compulsory: BooleanParam,
dataDimension: BooleanParam,
dataDimensionType: StringParam,
dataElement: CustomDelimitedArrayParam,
dataElementGroup: CustomDelimitedArrayParam,
dataElementGroupSet: CustomDelimitedArrayParam,
dataSet: CustomDelimitedArrayParam,
domainType: CustomDelimitedArrayParam,
formType: CustomDelimitedArrayParam,
ignoreApproval: BooleanParam,
indicatorType: CustomDelimitedArrayParam,
publicAccess: CustomDelimitedArrayParam,
valueType: CustomDelimitedArrayParam,
} as const satisfies QueryParamsConfigMap

export const validFilterKeys = Object.keys(filterQueryParamType)
Expand Down
3 changes: 3 additions & 0 deletions src/lib/sectionList/filters/parseFiltersToQueryParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ const filterToQueryParamMap: FilterToQueryParamsMap = {
section.name === SchemaName.dataElement
? inFilter('dataSetElements.dataSet.id', value)
: defaultFilter('dataSet', value),
dataElementGroup: (value) => inFilter('dataElementGroups.id', value),
dataElement: (value) => inFilter('dataElements.id', value),
dataElementGroupSet: (value) => inFilter('groupSets.id', value),
publicAccess: (value) => inFilter('sharing.public', value),
}

Expand Down
9 changes: 7 additions & 2 deletions src/lib/sectionList/listViews/sectionListViewsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,18 @@ export const modelListViewsConfig = {
columns: {
available: [DESCRIPTORS.shortName],
},
filters: {},
filters: {
default: ['dataElement', 'dataElementGroupSet'],
},
},
dataElementGroupSet: {
columns: {
available: [DESCRIPTORS.shortName],
},
filters: {},
filters: {
available: ['compulsory', 'dataDimension'],
default: ['dataElementGroup'],
},
},
dataSet: {
columns: {
Expand Down
65 changes: 2 additions & 63 deletions src/pages/dataElements/List.tsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,3 @@
import { useDataQuery } from '@dhis2/app-runtime'
import { SharingDialog } from '@dhis2/ui'
import React, { useEffect } from 'react'
import { SectionListWrapper } from '../../components'
import { useModelListView } from '../../components/sectionList/listView'
import {
useSchemaFromHandle,
useParamsForDataQuery,
DEFAULT_FIELD_FILTERS,
DefaultFields,
} from '../../lib/'
import { getFieldFilter } from '../../lib/models/path'
import { Query, WrapQueryResponse } from '../../types'
import { DataElement, ModelCollectionResponse } from '../../types/models'
import { DefaultSectionList } from '../DefaultSectionList'

type FilteredDataElement = Pick<DataElement, DefaultFields> &
Partial<DataElement>

type DataElements = ModelCollectionResponse<FilteredDataElement, 'dataElements'>

type DataElementsResponse = WrapQueryResponse<DataElements>

const query: Query = {
result: {
resource: 'dataElements',
params: (params) => params,
},
}

export const Component = () => {
const { columns, query: listViewQuery } = useModelListView()
const initialParams = useParamsForDataQuery()
const schema = useSchemaFromHandle()
const { refetch, error, data } = useDataQuery<DataElementsResponse>(
query,
// refetched on mount by effect below
{ lazy: true }
)

useEffect(() => {
// wait to fetch until selected-columns are loaded
// so we dont fetch data multiple times
if (listViewQuery.isLoading) {
return
}
refetch({
...initialParams,
fields: columns
.map((column) => getFieldFilter(schema, column.path))
.concat(DEFAULT_FIELD_FILTERS),
})
}, [refetch, initialParams, columns, listViewQuery.isLoading, schema])

return (
<div>
<SectionListWrapper
error={error}
data={data?.result.dataElements}
pager={data?.result.pager}
refetch={refetch}
/>
</div>
)
}
export const Component = DefaultSectionList

0 comments on commit 0e4b181

Please sign in to comment.