Skip to content

Commit

Permalink
refactor(filters): dynamic filter components
Browse files Browse the repository at this point in the history
  • Loading branch information
Birkbjo committed Jan 26, 2024
1 parent 4997272 commit ae75f5c
Show file tree
Hide file tree
Showing 18 changed files with 111 additions and 25 deletions.
3 changes: 1 addition & 2 deletions src/components/sectionList/SectionListWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export const SectionListWrapper = ({
error,
pager,
}: SectionListWrapperProps) => {
data
const { columns: headerColumns } = useModelListView()
const schema = useSchemaFromHandle()
const [selectedModels, setSelectedModels] = useState<Set<string>>(new Set())
Expand Down Expand Up @@ -78,7 +77,7 @@ export const SectionListWrapper = ({
return (
<div>
<SectionListTitle />
<FilterWrapper>{filterElement}</FilterWrapper>
<FilterWrapper />
<div className={css.listDetailsWrapper}>
<SectionListHeader />
<SectionList
Expand Down
31 changes: 31 additions & 0 deletions src/components/sectionList/filters/DynamicFilters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react'
import { ConfigurableFilterKey } from './../../../lib'
import {
AggregationTypeFilter,
DomainTypeSelectionFilter,
ValueTypeSelectionFilter,
} from './filterSelectors'
import { useFilterKeys } from './useFilterKeys'

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

const filterKeyToComponentMap: FilterKeyToComponentMap = {
domainType: DomainTypeSelectionFilter,
valueType: ValueTypeSelectionFilter,
aggregationType: AggregationTypeFilter,
}

export const DynamicFilters = () => {
const filterKeys = useFilterKeys()

return (
<>
{filterKeys.map((filterKey) => {
const FilterComponent = filterKeyToComponentMap[filterKey]
return FilterComponent ? (
<FilterComponent key={filterKey} />
) : null
})}
</>
)
}
6 changes: 6 additions & 0 deletions src/components/sectionList/filters/FilterWrapper.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.filterWrapper {
display: flex;
flex-wrap: wrap;
gap: 4px;
align-items: center;
}
11 changes: 5 additions & 6 deletions src/components/sectionList/filters/FilterWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import i18n from '@dhis2/d2-i18n'
import { Button } from '@dhis2/ui'
import React from 'react'
import { useSectionListFilters } from './../../../lib'
import css from './Filters.module.css'
import { IdentifiableFilter } from './IdentifiableFilter'
import { DynamicFilters } from './DynamicFilters'
import { IdentifiableFilter } from './filterSelectors/IdentifiableFilter'
import css from './FilterWrapper.module.css'

type FilterWrapperProps = React.PropsWithChildren

export const FilterWrapper = ({ children }: FilterWrapperProps) => {
export const FilterWrapper = () => {
const [, setFilters] = useSectionListFilters()

const handleClear = () => {
Expand All @@ -17,7 +16,7 @@ export const FilterWrapper = ({ children }: FilterWrapperProps) => {
return (
<div className={css.filterWrapper}>
<IdentifiableFilter />
{children}
<DynamicFilters />
<Button small onClick={handleClear}>
{i18n.t('Clear all filters')}
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { DOMAIN_TYPE, VALUE_TYPE } from '../../../lib'
import { AGGREGATION_TYPE, DOMAIN_TYPE, VALUE_TYPE } from '../../../../lib'
import { ConstantSelectionFilter } from './ConstantSelectionFilter'

export const DomainTypeSelectionFilter = () => {
Expand All @@ -22,3 +22,14 @@ export const ValueTypeSelectionFilter = () => {
/>
)
}

export const AggregationTypeFilter = () => {
return (
<ConstantSelectionFilter
label={'Aggregation type'}
filterKey="aggregationType"
constants={AGGREGATION_TYPE}
filterable
/>
)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import i18n from '@dhis2/d2-i18n'
import { SingleSelect, SingleSelectOption } from '@dhis2/ui'
import React from 'react'
import { FilterKey, useSectionListFilter } from '../../../lib'
import { SelectOnChangeObject } from '../../../types'
import { FilterKey, useSectionListFilter } from '../../../../lib'
import { SelectOnChangeObject } from '../../../../types'
import css from './Filters.module.css'

type ConstantSelectionFilterProps = {
Expand All @@ -19,7 +19,6 @@ export const ConstantSelectionFilter = ({
filterable,
}: ConstantSelectionFilterProps) => {
const [filter, setFilter] = useSectionListFilter(filterKey)

return (
<SingleSelect
className={css.constantSelectionFilter}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
useDebounce,
IDENTIFIABLE_KEY,
useSectionListFilter,
} from '../../../lib'
} from '../../../../lib'
import css from './Filters.module.css'

export const IdentifiableFilter = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ConstantFilters'
6 changes: 3 additions & 3 deletions src/components/sectionList/filters/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './ConstantSelectionFilter'
export * from './IdentifiableFilter'
export * from './ConstantFilters'
export * from './filterSelectors/ConstantSelectionFilter'
export * from './filterSelectors/IdentifiableFilter'
export * from './filterSelectors/ConstantFilters'
38 changes: 38 additions & 0 deletions src/components/sectionList/filters/useFilterKeys.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useMemo } from 'react'
import {
useSectionListFilters,
ParsedFilterParams,
ConfigurableFilterKey,
IDENTIFIABLE_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 views = useModelListView()
const viewFilters = views.filters
// combine filters and views, since filters in URL might not be selected for view
// but we should show them when they have a value
const filterKeys = useMemo(() => {
const viewFilterKeys = viewFilters.map(({ filterKey }) => filterKey)
const selectedFiltersNotInView = Object.entries(filters)
.filter(
([filterKey, value]) =>
value !== undefined &&
filterKey !== IDENTIFIABLE_KEY &&
!viewFilterKeys.includes(filterKey as ConfigurableFilterKey)
)
.map(([filterKey]) => filterKey) as ConfigurableFilterKey[]

return viewFilterKeys.concat(selectedFiltersNotInView)
}, [filters, viewFilters])
return filterKeys
}
1 change: 0 additions & 1 deletion src/lib/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export * from './sections'
export * from './translatedModelConstants'
export * from './translatedModelProperties'
export * from './sectionListView'

export const IDENTIFIABLE_KEY = 'identifiable'
2 changes: 1 addition & 1 deletion src/lib/sectionList/filters/filterConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const filterParamsSchema = z
categoryCombo: zodArrayIds,
dataSet: zodArrayIds,
domainType: z.array(z.nativeEnum(DataElement.domainType)),
valueType: z.array(z.string()),
valueType: z.array(z.nativeEnum(DataElement.valueType)),
})
.partial()

Expand Down
2 changes: 1 addition & 1 deletion src/lib/sectionList/filters/useSectionListFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
export const useSectionListFilters = () => {
const [filters, setFilterParams] = useQueryParams(filterQueryParamType)
const [, setPagingParams] = usePaginationQueryParams()

console.log({ filters })
const parsedFilters = useMemo(() => {
const parsed = filterParamsSchema.safeParse(filters)
if (parsed.success) {
Expand Down
1 change: 1 addition & 0 deletions src/lib/sectionList/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export {
useUpdatePaginationParams,
} from './usePaginationParams'
export * from './useParamsForDataQuery'
export * from './listViews'
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import i18n from '@dhis2/d2-i18n'
import type { ConfigurableFilterKey } from '../../sectionList/filters/'
import type { ConfigurableFilterKey } from '../filters'

export interface ModelPropertyDescriptor {
label: string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getTranslatedProperty } from '../../constants/translatedModelProperties'
import { uniqueBy } from '../../utils'
import { getTranslatedProperty } from '../translatedModelProperties'
import {
defaultModelViewConfig,
modelListViewsConfig,
Expand All @@ -23,7 +23,7 @@ interface ResolvedSectionListView {
[key: string]: ResolvedViewConfig
}

const toModelPropertyDescriptor = (
export const toModelPropertyDescriptor = (
propertyConfig: ModelPropertyConfig
): ModelPropertyDescriptor => {
if (typeof propertyConfig === 'string') {
Expand All @@ -35,7 +35,9 @@ const toModelPropertyDescriptor = (
return propertyConfig
}

const toFilterDescriptor = (propertyConfig: FilterConfig): FilterDescriptor => {
export const toFilterDescriptor = (
propertyConfig: FilterConfig
): FilterDescriptor => {
if (typeof propertyConfig === 'string') {
return {
label: getTranslatedProperty(propertyConfig),
Expand Down Expand Up @@ -111,7 +113,7 @@ const resolveListViewsConfig = () => {
return merged
}

const mergedModelViewsConfig = resolveListViewsConfig()
const resolvedModelViewsConfig = resolveListViewsConfig()
const resolvedDefaultConfig = {
columns: resolveColumnConfig(defaultModelViewConfig.columns),
filters: resolveFilterConfig(defaultModelViewConfig.filters),
Expand All @@ -120,7 +122,7 @@ const resolvedDefaultConfig = {
export const getViewConfigForSection = (
sectionName: string
): ResolvedViewConfig => {
const resolvedConfig = mergedModelViewsConfig[sectionName]
const resolvedConfig = resolvedModelViewsConfig[sectionName]
if (resolvedConfig) {
return resolvedConfig
}
Expand Down

0 comments on commit ae75f5c

Please sign in to comment.