diff --git a/i18n/en.pot b/i18n/en.pot
index 1f209e0b..019a902d 100644
--- a/i18n/en.pot
+++ b/i18n/en.pot
@@ -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"
diff --git a/src/components/sectionList/filters/filterSelectors/BooleanFilters.tsx b/src/components/sectionList/filters/filterSelectors/BooleanFilters.tsx
index 4cdf3b9c..de73d3ed 100644
--- a/src/components/sectionList/filters/filterSelectors/BooleanFilters.tsx
+++ b/src/components/sectionList/filters/filterSelectors/BooleanFilters.tsx
@@ -33,3 +33,21 @@ export const IgnoreApprovalFilter = () => {
/>
)
}
+
+export const CompulsoryFilter = () => {
+ return (
+
+ )
+}
+
+export const DataDimensionFilter = () => {
+ return (
+
+ )
+}
diff --git a/src/components/sectionList/filters/filterSelectors/DataElementFilter.tsx b/src/components/sectionList/filters/filterSelectors/DataElementFilter.tsx
new file mode 100644
index 00000000..0015f20e
--- /dev/null
+++ b/src/components/sectionList/filters/filterSelectors/DataElementFilter.tsx
@@ -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 (
+
+ setFilter(selected ? [selected] : undefined)
+ }
+ />
+ )
+}
diff --git a/src/components/sectionList/filters/filterSelectors/DataElementGroup.tsx b/src/components/sectionList/filters/filterSelectors/DataElementGroup.tsx
new file mode 100644
index 00000000..13aaed82
--- /dev/null
+++ b/src/components/sectionList/filters/filterSelectors/DataElementGroup.tsx
@@ -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 (
+
+ setFilter(selected ? [selected] : undefined)
+ }
+ />
+ )
+}
diff --git a/src/components/sectionList/filters/filterSelectors/DataElementGroupSet.tsx b/src/components/sectionList/filters/filterSelectors/DataElementGroupSet.tsx
new file mode 100644
index 00000000..a56f80db
--- /dev/null
+++ b/src/components/sectionList/filters/filterSelectors/DataElementGroupSet.tsx
@@ -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 (
+
+ setFilter(selected ? [selected] : undefined)
+ }
+ />
+ )
+}
diff --git a/src/components/sectionList/filters/filterSelectors/DynamicFilters.tsx b/src/components/sectionList/filters/filterSelectors/DynamicFilters.tsx
index 772da489..c73759c4 100644
--- a/src/components/sectionList/filters/filterSelectors/DynamicFilters.tsx
+++ b/src/components/sectionList/filters/filterSelectors/DynamicFilters.tsx
@@ -15,24 +15,34 @@ import {
ValueTypeSelectionFilter,
FormTypeFilter,
DataSetFilter,
+ DataElementGroupFilter,
+ DataElementGroupSetFilter,
+ DataElementFilter,
+ CompulsoryFilter,
+ DataDimensionFilter,
} from '.'
type FilterKeyToComponentMap = Partial>
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 = () => {
diff --git a/src/components/sectionList/filters/filterSelectors/index.ts b/src/components/sectionList/filters/filterSelectors/index.ts
index fa056f4d..a782dcc6 100644
--- a/src/components/sectionList/filters/filterSelectors/index.ts
+++ b/src/components/sectionList/filters/filterSelectors/index.ts
@@ -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'
diff --git a/src/lib/constants/translatedModelProperties.ts b/src/lib/constants/translatedModelProperties.ts
index 8916498e..05c22a01 100644
--- a/src/lib/constants/translatedModelProperties.ts
+++ b/src/lib/constants/translatedModelProperties.ts
@@ -6,27 +6,32 @@ const TRANSLATED_PROPERTY: Record = {
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) =>
diff --git a/src/lib/sectionList/filters/filterConfig.tsx b/src/lib/sectionList/filters/filterConfig.tsx
index 5593d716..a2347a13 100644
--- a/src/lib/sectionList/filters/filterConfig.tsx
+++ b/src/lib/sectionList/filters/filterConfig.tsx
@@ -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()
@@ -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)
diff --git a/src/lib/sectionList/filters/parseFiltersToQueryParams.ts b/src/lib/sectionList/filters/parseFiltersToQueryParams.ts
index 53bb0b47..b5e3419b 100644
--- a/src/lib/sectionList/filters/parseFiltersToQueryParams.ts
+++ b/src/lib/sectionList/filters/parseFiltersToQueryParams.ts
@@ -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),
}
diff --git a/src/lib/sectionList/listViews/sectionListViewsConfig.ts b/src/lib/sectionList/listViews/sectionListViewsConfig.ts
index 6c6403b7..7581fd79 100644
--- a/src/lib/sectionList/listViews/sectionListViewsConfig.ts
+++ b/src/lib/sectionList/listViews/sectionListViewsConfig.ts
@@ -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: {
diff --git a/src/pages/dataElements/List.tsx b/src/pages/dataElements/List.tsx
index 51c39765..e03292f8 100644
--- a/src/pages/dataElements/List.tsx
+++ b/src/pages/dataElements/List.tsx
@@ -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 &
- Partial
-
-type DataElements = ModelCollectionResponse
-
-type DataElementsResponse = WrapQueryResponse
-
-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(
- 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 (
-
-
-
- )
-}
+export const Component = DefaultSectionList