diff --git a/src/components/sectionList/filters/filterSelectors/IdentifiableFilter.tsx b/src/components/sectionList/filters/filterSelectors/IdentifiableFilter.tsx index 241fc7ef..75cf841a 100644 --- a/src/components/sectionList/filters/filterSelectors/IdentifiableFilter.tsx +++ b/src/components/sectionList/filters/filterSelectors/IdentifiableFilter.tsx @@ -3,13 +3,13 @@ import { Input, InputEventPayload } from '@dhis2/ui' import React, { useEffect, useState } from 'react' import { useDebounce, - IDENTIFIABLE_KEY, + IDENTIFIABLE_FILTER_KEY, useSectionListFilter, } from '../../../../lib' import css from './Filters.module.css' export const IdentifiableFilter = () => { - const [filter, setFilter] = useSectionListFilter(IDENTIFIABLE_KEY) + const [filter, setFilter] = useSectionListFilter(IDENTIFIABLE_FILTER_KEY) const [value, setValue] = useState(filter || '') const debouncedValue = useDebounce(value, 200) diff --git a/src/components/sectionList/filters/useFilterKeys.tsx b/src/components/sectionList/filters/useFilterKeys.tsx index 05c8c9f8..e19f165b 100644 --- a/src/components/sectionList/filters/useFilterKeys.tsx +++ b/src/components/sectionList/filters/useFilterKeys.tsx @@ -1,20 +1,11 @@ import { useMemo } from 'react' import { useSectionListFilters, - ParsedFilterParams, ConfigurableFilterKey, - IDENTIFIABLE_KEY, + IDENTIFIABLE_FILTER_KEY, } from '../../../lib' import { useModelListView } from '../listView' -export type FiltersWithValue = { - [FilterKey in ConfigurableFilterKey]: { - value: ParsedFilterParams[FilterKey] - label: string - filterKey: FilterKey - } -} - export const useFilterKeys = () => { const [filters] = useSectionListFilters() const { filters: viewFilters } = useModelListView() @@ -26,7 +17,7 @@ export const useFilterKeys = () => { .filter( ([filterKey, value]) => value !== undefined && - filterKey !== IDENTIFIABLE_KEY && + filterKey !== IDENTIFIABLE_FILTER_KEY && !viewFilterKeys.includes(filterKey as ConfigurableFilterKey) ) .map(([filterKey]) => filterKey) as ConfigurableFilterKey[] diff --git a/src/lib/constants/index.ts b/src/lib/constants/index.ts index 61de1c84..c700910f 100644 --- a/src/lib/constants/index.ts +++ b/src/lib/constants/index.ts @@ -2,4 +2,4 @@ export * from './sections' export * from './translatedModelConstants' export * from './translatedModelProperties' -export const IDENTIFIABLE_KEY = 'identifiable' +export const IDENTIFIABLE_FILTER_KEY = 'identifiable' diff --git a/src/lib/constants/sectionListViewsConfig.ts b/src/lib/constants/sectionListViewsConfig.ts deleted file mode 100644 index 899f1bed..00000000 --- a/src/lib/constants/sectionListViewsConfig.ts +++ /dev/null @@ -1,174 +0,0 @@ -import i18n from '@dhis2/d2-i18n' -import { uniqueBy } from '../utils' -import type { SectionName } from './sections' -import { getTranslatedProperty } from './translatedModelProperties' - -export interface ModelPropertyDescriptor { - label: string - path: string -} - -type ModelPropertyConfig = string | ModelPropertyDescriptor -interface ViewConfigPart { - available?: ReadonlyArray - overrideDefaultAvailable?: boolean - default?: ReadonlyArray -} - -interface ViewConfig { - columns: ViewConfigPart - filters: ViewConfigPart -} - -interface ResolvedViewConfigPart { - available: ReadonlyArray - default: ReadonlyArray -} -interface ResolvedViewConfig { - columns: ResolvedViewConfigPart - filters: ResolvedViewConfigPart -} - -// generic here is just used for "satisfies" below, for code-completion of future customizations -type SectionListViewConfig = { - [key in Key]?: ViewConfig -} - -const DESCRIPTORS = { - publicAccess: { path: 'sharing.public', label: i18n.t('Public access') }, -} satisfies Record - -// This is the default views, and can be overriden per section in modelListViewsConfig below -const defaultModelViewConfig = { - columns: { - available: [ - 'name', - 'shortName', - 'code', - 'created', - 'createdBy', - 'href', - 'id', - 'lastUpdatedBy', - DESCRIPTORS.publicAccess, - ], - default: ['name', 'sharing.public', 'lastUpdated'], - }, - filters: { - available: ['name'], - default: ['name'], - }, -} satisfies ViewConfig - -// this is the default views (eg. which columns and filters) to show in the List-page for each section -// Note: by default, the available columns are merged with columnsDefault.available above. -// If it's needed to override this for a section, set overrideDefaultAvailable to true -// and list all available columns in the available array below. -// Default-list will NOT be merged with columnsDefault.default - list all explicitly. -// elements in the default array implies they are also available, no need to list them in both. - -const modelListViewsConfig = { - dataElement: { - columns: { - available: [ - 'zeroIsSignificant', - 'categoryCombo', - // { - // label: i18n.t('Hello available public'), - // path: 'sharing.public', - // }, - ], - default: [ - 'name', - { label: i18n.t('Domain'), path: 'domainType' }, - { label: i18n.t('Value type'), path: 'valueType' }, - 'lastUpdated', - // 'sharing.public', - { label: i18n.t('Hello public'), path: 'sharing.public' }, - ], - }, - filters: { - default: ['name', 'domainType', 'valueType'], - available: ['zeroIsSignificant', 'categoryCombo'], - }, - }, -} satisfies SectionListViewConfig - -const toModelPropertyDescriptor = ( - propertyConfig: ModelPropertyConfig, - available?: ModelPropertyDescriptor[] -): ModelPropertyDescriptor => { - if (typeof propertyConfig === 'string') { - // simple descriptors can refer to previously defined descriptors - const availableDescriptor = available?.find( - (prop) => prop.path === propertyConfig - ) - - return ( - availableDescriptor || { - label: getTranslatedProperty(propertyConfig), - path: propertyConfig, - } - ) - } - return propertyConfig -} - -const resolveViewPart = (part: ViewConfigPart, type: keyof ViewConfig) => { - const mergedAvailableDescriptors = uniqueBy( - [ - part.available || [], - part.overrideDefaultAvailable - ? [] - : defaultModelViewConfig[type].available, - part.default || [], - ] - .flat() - .map((propConfig) => toModelPropertyDescriptor(propConfig)), - (prop) => prop.path - ) - const defaultPropConfig = - part.default || defaultModelViewConfig[type].default - const defaultDescriptors = defaultPropConfig.map((propConfig) => - toModelPropertyDescriptor(propConfig, mergedAvailableDescriptors) - ) - return { - available: mergedAvailableDescriptors, - default: defaultDescriptors, - } -} -// merge the default modelViewConfig with the modelViewsConfig for each section -const resolveListViewsConfig = (): SectionListViewConfig => { - const merged: SectionListViewConfig = {} - - Object.entries(modelListViewsConfig).forEach((viewConfig) => { - const [sectionName, sectionViewConfig] = viewConfig - merged[sectionName as SectionName] = { - columns: resolveViewPart(sectionViewConfig.columns, 'columns'), - filters: resolveViewPart(sectionViewConfig.filters, 'filters'), - } - }) - return merged -} - -const mergedModelViewsConfig = resolveListViewsConfig() -const resolvedDefaultConfig = { - columns: resolveViewPart(defaultModelViewConfig.columns, 'columns'), - filters: resolveViewPart(defaultModelViewConfig.filters, 'filters'), -} - -export const getViewConfigForSection = ( - sectionName: string -): ResolvedViewConfig => { - if (mergedModelViewsConfig[sectionName]) { - return mergedModelViewsConfig[sectionName] as ResolvedViewConfig - } - return resolvedDefaultConfig -} - -export const getColumnsForSection = ( - sectionName: string -): ResolvedViewConfig['columns'] => { - const view = getViewConfigForSection(sectionName) - return view.columns -} diff --git a/src/lib/sectionList/filters/filterConfig.tsx b/src/lib/sectionList/filters/filterConfig.tsx index cd05e885..54cc65e6 100644 --- a/src/lib/sectionList/filters/filterConfig.tsx +++ b/src/lib/sectionList/filters/filterConfig.tsx @@ -1,7 +1,7 @@ import { StringParam } from 'use-query-params' import { z } from 'zod' import { DataElement } from '../../../types/generated' -import { IDENTIFIABLE_KEY } from '../../constants' +import { IDENTIFIABLE_FILTER_KEY } from '../../constants' import { isValidUid, parsePublicAccessString } from '../../models' import { CustomDelimitedArrayParam } from './customParams' @@ -10,7 +10,7 @@ const zodArrayIds = z.array(z.string().refine((val) => isValidUid(val))) /* Zod schema for validation of the decoded params */ export const filterParamsSchema = z .object({ - [IDENTIFIABLE_KEY]: z.string(), + [IDENTIFIABLE_FILTER_KEY]: z.string(), aggregationType: z.array(z.nativeEnum(DataElement.aggregationType)), categoryCombo: zodArrayIds, dataSet: zodArrayIds, @@ -25,7 +25,7 @@ export const filterParamsSchema = z /* useQueryParams config-map object Mapping each filter to a config object that handles encoding/decoding */ export const filterQueryParamType = { - [IDENTIFIABLE_KEY]: StringParam, + [IDENTIFIABLE_FILTER_KEY]: StringParam, aggregationType: CustomDelimitedArrayParam, domainType: CustomDelimitedArrayParam, valueType: CustomDelimitedArrayParam, @@ -53,5 +53,8 @@ type QueryParamsConfigMap = { export type FilterKey = keyof ParsedFilterParams // Identifiable is not configurable, and is always shown in the list -export type ConfigurableFilterKey = Exclude +export type ConfigurableFilterKey = Exclude< + FilterKey, + typeof IDENTIFIABLE_FILTER_KEY +> export type FilterKeys = FilterKey[]