Skip to content

Commit

Permalink
feat: add filter panel to single deposition page (#1030)
Browse files Browse the repository at this point in the history
#923 

note that applying filters will not filter the results until #920 and
will merely update the search params
  • Loading branch information
kne42 authored Aug 16, 2024
1 parent 4d06b14 commit d378e7c
Show file tree
Hide file tree
Showing 19 changed files with 248 additions and 112 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import { GeneOntologyFilter } from 'app/components/AnnotationFilter/GeneOntologyFilter'
import {
AnnotatedObjectNameFilter,
AnnotatedObjectShapeTypeFilter,
FilterSection,
} from 'app/components/Filters'
import { useDatasets } from 'app/hooks/useDatasets'
import { useDatasetsFilterData } from 'app/hooks/useDatasetsFilterData'
import { useI18n } from 'app/hooks/useI18n'

export function AnnotationMetadataFilterSection() {
const { objectNames, objectShapeTypes } = useDatasets()
export function AnnotationMetadataFilterSection({
depositionPageVariant,
}: {
depositionPageVariant?: boolean
}) {
const { objectNames, objectShapeTypes } = useDatasetsFilterData()

const { t } = useI18n()

return (
<FilterSection title={t('annotationMetadata')} border={false}>
{depositionPageVariant && (
<p className="text-sds-body-xxs leading-sds-body-xxs text-sds-gray-500 pl-sds-s">
{t('depositionAnnotationsOnly')}
</p>
)}

<AnnotatedObjectNameFilter
allObjectNames={objectNames}
label={t('objectName')}
/>

{depositionPageVariant && <GeneOntologyFilter />}

<AnnotatedObjectShapeTypeFilter allObjectShapeTypes={objectShapeTypes} />
</FilterSection>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ErrorBoundary } from 'app/components/ErrorBoundary'
import { FilterPanel } from 'app/components/Filters'

import { ErrorBoundary } from '../ErrorBoundary'
import { AnnotationMetadataFilterSection } from './AnnotationMetadataFilterSection'
import { HardwareFilterSection } from './HardwareFilterSection'
import { IncludedContentsFilterSection } from './IncludedContentsFilterSection'
Expand All @@ -9,11 +9,19 @@ import { SampleAndExperimentFilterSection } from './SampleAndExperimentFilterSec
import { TiltSeriesMetadataFilterSection } from './TiltSeriesMetadataFilterSection'
import { TomogramMetadataFilterSection } from './TomogramMetadataFilterSection'

export function DatasetFilter() {
export function DatasetFilter({
depositionPageVariant,
}: {
depositionPageVariant?: boolean
}) {
const filters = [
{
logId: 'included-contents-filter',
filter: <IncludedContentsFilterSection />,
filter: (
<IncludedContentsFilterSection
depositionPageVariant={depositionPageVariant}
/>
),
},
{
logId: 'name-or-id-filter',
Expand All @@ -37,7 +45,11 @@ export function DatasetFilter() {
},
{
logId: 'annotation-metadata-filter',
filter: <AnnotationMetadataFilterSection />,
filter: (
<AnnotationMetadataFilterSection
depositionPageVariant={depositionPageVariant}
/>
),
},
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { useMemo } from 'react'

import { FilterSection, SelectFilter } from 'app/components/Filters'
import { QueryParams } from 'app/constants/query'
import { useDatasets } from 'app/hooks/useDatasets'
import { useDatasetsFilterData } from 'app/hooks/useDatasetsFilterData'
import { useFilter } from 'app/hooks/useFilter'
import { i18n } from 'app/i18n'
import { BaseFilterOption } from 'app/types/filter'

export function HardwareFilterSection() {
const { cameraManufacturers } = useDatasets()
const { cameraManufacturers } = useDatasetsFilterData()

const cameraManufacturerOptions = useMemo(
() => cameraManufacturers.map<BaseFilterOption>((value) => ({ value })),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ const NUMBER_OF_RUN_OPTIONS: NumberOfRunsFilterOption[] = [
const AVAILABLE_FILES_CLASS_NAME = 'select-available-files'
const MEETS_ALL_LABEL_ID = 'meets-all'

export function IncludedContentsFilterSection() {
export function IncludedContentsFilterSection({
depositionPageVariant,
}: {
depositionPageVariant?: boolean
}) {
const {
updateValue,
includedContents: { availableFiles, numberOfRuns },
Expand Down Expand Up @@ -95,7 +99,9 @@ export function IncludedContentsFilterSection() {

return (
<FilterSection title={i18n.includedContents}>
<GroundTruthAnnotationFilter />
<GroundTruthAnnotationFilter
depositionPageVariant={depositionPageVariant}
/>

<SelectFilter
multiple
Expand All @@ -121,6 +127,13 @@ export function IncludedContentsFilterSection() {
option ? JSON.stringify(option.value) : null,
)
}
details={
depositionPageVariant ? (
<p className="text-sds-body-xxs leading-sds-body-xxs text-sds-gray-500">
{t('withDepositionData')}
</p>
) : undefined
}
/>
</FilterSection>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMemo } from 'react'

import { FilterSection, SelectFilter } from 'app/components/Filters'
import { QueryParams } from 'app/constants/query'
import { useDatasets } from 'app/hooks/useDatasets'
import { useDatasetsFilterData } from 'app/hooks/useDatasetsFilterData'
import { useFilter } from 'app/hooks/useFilter'
import { i18n } from 'app/i18n'
import { BaseFilterOption } from 'app/types/filter'
Expand All @@ -12,7 +12,7 @@ export function SampleAndExperimentFilterSection() {
updateValue,
sampleAndExperimentConditions: { organismNames },
} = useFilter()
const { organismNames: allOrganismNames } = useDatasets()
const { organismNames: allOrganismNames } = useDatasetsFilterData()

const organismNameOptions = useMemo(
() => allOrganismNames.map<BaseFilterOption>((name) => ({ value: name })),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMemo } from 'react'

import { FilterSection, SelectFilter } from 'app/components/Filters'
import { QueryParams } from 'app/constants/query'
import { useDatasets } from 'app/hooks/useDatasets'
import { useDatasetsFilterData } from 'app/hooks/useDatasetsFilterData'
import { useFilter } from 'app/hooks/useFilter'
import { i18n } from 'app/i18n'
import {
Expand Down Expand Up @@ -36,7 +36,8 @@ export function TomogramMetadataFilterSection() {
)!
}, [fiducialAlignmentStatus])

const { reconstructionMethods, reconstructionSoftwares } = useDatasets()
const { reconstructionMethods, reconstructionSoftwares } =
useDatasetsFilterData()

const reconstructionMethodOptions = useMemo(
() => reconstructionMethods.map<BaseFilterOption>((value) => ({ value })),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { cns } from 'app/utils/cns'
import styles from './Filters.module.css'

export function BooleanFilter({
caption,
label,
onChange,
value,
}: {
caption?: string
label: string
onChange(value: boolean): void
value: boolean
Expand All @@ -19,6 +21,7 @@ export function BooleanFilter({
checked={value}
onChange={(event) => onChange(event.target.checked)}
label={label}
caption={caption}
/>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,36 @@ import { useI18n } from 'app/hooks/useI18n'

import { BooleanFilter } from './BooleanFilter'

export function GroundTruthAnnotationFilter() {
export function GroundTruthAnnotationFilter({
depositionPageVariant,
}: {
depositionPageVariant?: boolean
}) {
const { t } = useI18n()
const {
updateValue,
includedContents: { isGroundTruthEnabled },
} = useFilter()

return (
<BooleanFilter
label={t('groundTruthAnnotation')}
onChange={(value) =>
updateValue(QueryParams.GroundTruthAnnotation, value ? 'true' : null)
}
value={isGroundTruthEnabled}
/>
<>
<BooleanFilter
label={t('groundTruthAnnotation')}
onChange={(value) =>
updateValue(QueryParams.GroundTruthAnnotation, value ? 'true' : null)
}
value={isGroundTruthEnabled}
// FIXME: once sds upgraded to 0.20.x uncomment this
// caption={
// depositionPageVariant ? t('depositionAnnotationsOnly') : undefined
// }
/>
{/* FIXME: once sds upgraded to 0.20.x delete below line and remove fragment wrapper */}
{depositionPageVariant && (
<p className="pl-[32px] text-sds-body-xxs leading-sds-body-xxs text-sds-gray-500">
{t('depositionAnnotationsOnly')}
</p>
)}
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
Value,
} from '@czi-sds/components'
import { isArray, isEqual } from 'lodash-es'
import { useCallback, useMemo } from 'react'
import { ReactNode, useCallback, useMemo } from 'react'

import { BaseFilterOption } from 'app/types/filter'
import { cns } from 'app/utils/cns'
Expand All @@ -20,6 +20,7 @@ export function SelectFilter<
Multiple extends boolean = false,
>({
className,
details,
groupBy: groupByProp,
label,
multiple,
Expand All @@ -31,6 +32,7 @@ export function SelectFilter<
value,
}: {
className?: string
details?: ReactNode
groupBy?: (option: Value<Option, Multiple>) => string
label: string
multiple?: Multiple
Expand Down Expand Up @@ -109,6 +111,15 @@ export function SelectFilter<
className: cns(popperClassName, multiple && styles.popper),
},
}}
InputDropdownProps={
details
? {
value: details,
sdsStyle: 'minimal',
sdsType: 'label',
}
: undefined
}
onChange={(nextOptions) => {
if (isEqual(nextOptions, sdsValue)) {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,30 +63,6 @@ const GET_DATASETS_DATA_QUERY = gql(`
count
}
}
organism_names: datasets(distinct_on: organism_name) {
organism_name
}
camera_manufacturers: tiltseries(distinct_on: camera_manufacturer) {
camera_manufacturer
}
reconstruction_methods: tomograms(distinct_on: reconstruction_method) {
reconstruction_method
}
reconstruction_softwares: tomograms(distinct_on: reconstruction_software) {
reconstruction_software
}
object_names: annotations(distinct_on: object_name) {
object_name
}
object_shape_types: annotation_files(distinct_on: shape_type) {
shape_type
}
}
`)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { ApolloClient, NormalizedCacheObject } from '@apollo/client'

import { gql } from 'app/__generated__'
import { Datasets_Bool_Exp } from 'app/__generated__/graphql'

const GET_DATASETS_FILTER_DATA_QUERY = gql(`
query GetDatasetsFilterData(
$filter: datasets_bool_exp,
) {
organism_names: datasets(where: $filter, distinct_on: organism_name) {
organism_name
}
camera_manufacturers: tiltseries(distinct_on: camera_manufacturer) {
camera_manufacturer
}
reconstruction_methods: tomograms(distinct_on: reconstruction_method) {
reconstruction_method
}
reconstruction_softwares: tomograms(distinct_on: reconstruction_software) {
reconstruction_software
}
object_names: annotations(distinct_on: object_name) {
object_name
}
object_shape_types: annotation_files(distinct_on: shape_type) {
shape_type
}
}
`)

export async function getDatasetsFilterData({
client,
filter = {},
}: {
client: ApolloClient<NormalizedCacheObject>
filter: Datasets_Bool_Exp
}) {
const start = performance.now()

const results = await client.query({
query: GET_DATASETS_FILTER_DATA_QUERY,
variables: {
filter,
},
})

const end = performance.now()
// eslint-disable-next-line no-console
console.log(`getDatasetsFilterData query perf: ${end - start}ms`)

return results
}
Loading

0 comments on commit d378e7c

Please sign in to comment.