From 3cdf5558a61f0c7eec30b20cd185f8c2da1b3182 Mon Sep 17 00:00:00 2001 From: John Conroy Date: Tue, 8 Oct 2024 19:58:24 -0400 Subject: [PATCH] Add agg sorting options --- .../js/components/search/Facets/TermFacet.tsx | 35 +++++++++++++++---- .../static/js/components/search/Search.tsx | 14 +++----- .../components/search/fieldConfigurations.ts | 2 +- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/context/app/static/js/components/search/Facets/TermFacet.tsx b/context/app/static/js/components/search/Facets/TermFacet.tsx index a4922854f7..6e328f07e6 100644 --- a/context/app/static/js/components/search/Facets/TermFacet.tsx +++ b/context/app/static/js/components/search/Facets/TermFacet.tsx @@ -9,7 +9,7 @@ import { AggregationsBuckets } from '@elastic/elasticsearch/lib/api/types'; import { TooltipIconButton } from 'js/shared-styles/buttons/TooltipButton'; import { trackEvent } from 'js/helpers/trackers'; -import { useSearch } from '../Search'; +import { useSearch, HierarchichalBucket, InnerBucket } from '../Search'; import { isTermFilter, useSearchStore, TermValues, isHierarchicalFilter, isTermFacet } from '../store'; import { StyledCheckBoxBlankIcon, @@ -21,7 +21,7 @@ import { HierarchicalAccordionSummary, } from './style'; import FacetAccordion from './FacetAccordion'; -import { getFieldLabel, getTransformedFieldalue } from '../fieldConfigurations'; +import { getFieldLabel, getFieldValueSort, getTransformedFieldalue } from '../fieldConfigurations'; interface CheckboxItem { label: string; @@ -33,11 +33,32 @@ interface CheckboxItem { field: string; } -function getBucketKey(bucket: { key: string; key_as_string?: string; doc_count: number }) { +type Bucket = HierarchichalBucket | InnerBucket; + +function getBucketKey(bucket: InnerBucket) { const { key, key_as_string } = bucket; return key_as_string ?? key; } +const sortFunctions: Record<'asc' | 'desc' | 'count', (a: Bucket, b: Bucket) => number> = { + count: ({ doc_count: a }, { doc_count: b }) => b - a, + asc: (a, b) => getBucketKey(a).localeCompare(getBucketKey(b)), + desc: (a, b) => getBucketKey(b).localeCompare(getBucketKey(a)), +}; + +function sortBuckets({ + field, + buckets, + sort, +}: { + field: string; + buckets: T[]; + sort?: 'asc' | 'desc' | 'count'; +}): T[] { + const sortFn = sortFunctions[sort ?? getFieldValueSort(field)]; + return buckets.sort(sortFn); +} + type TermLabelCount = Omit; export function TermLabelAndCount({ label, count, active }: TermLabelCount) { @@ -148,7 +169,7 @@ function TermFacetContent({ filter, field }: { filter: TermValues; field: string const title = getFieldLabel(field); return ( - {aggBuckets.map((bucket) => { + {sortBuckets({ field, buckets: aggBuckets }).map((bucket) => { const key = getBucketKey(bucket); return ( ; + childBuckets?: AggregationsBuckets; }) { const [expanded, setExpanded] = useState(false); const toggleExpanded = useCallback(() => { @@ -281,7 +302,7 @@ export function HierarchicalTermFacetItem({ /> - {childBuckets.map(({ key, doc_count }) => ( + {sortBuckets({ buckets: childBuckets, field: parentField }).map(({ key, doc_count }) => ( - {parentBuckets.map((bucket) => { + {sortBuckets({ buckets: parentBuckets, field: parentField }).map((bucket) => { const key = getBucketKey(bucket); return ( >>> - > ->; +export type HierarchichalBucket = InnerBucket & Partial>>; + +type Aggregations = Record>>; export function useSearch() { const { endpoint, swrConfig = {}, ...rest }: SearchStoreState = useSearchStore(); diff --git a/context/app/static/js/components/search/fieldConfigurations.ts b/context/app/static/js/components/search/fieldConfigurations.ts index 7e91d29c62..612d85d51f 100644 --- a/context/app/static/js/components/search/fieldConfigurations.ts +++ b/context/app/static/js/components/search/fieldConfigurations.ts @@ -10,7 +10,7 @@ function mapProcessingType(label: string) { const fieldConfigurationsMap: Record< string, - { label?: string; valueTransformations?: ((label: string) => string)[]; valueSort?: 'asc' | 'dsc' | 'count' } + { label?: string; valueTransformations?: ((label: string) => string)[]; valueSort?: 'asc' | 'desc' | 'count' } > = { age_value: { label: 'Donor Age' }, analyte_class: { label: 'Analyte Class', valueTransformations: [capitalizeString] },