-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#25 Implements the browse all filters component for the browse all page. Overall the implementation of the filters works keeping state in sync with the query parameters. This is ideal because it: 1. Makes the application "stateless" - Even though state is stored in the query parameters, the application itself does not rely on any local state to have the filters working 1. Allows us to create permalinks of the filter page with every filter specified - Since the data is stored in the URL, opening the URL in another tab will init the local data with the query parameters, effectively creating a permalink 1. Leverages browser history API - This will allow us to go back / forward in the browser since the filter state is stored in query parameters The components implemented in `components/Filters` should be generic enough to be used in other places as well, so it should be straightforward to re-use the components when we implement filters on other pages. ## Demo ### Filters demo https://github.com/chanzuckerberg/cryoet-data-portal/assets/2176050/74db52b9-ddb6-4819-9409-79a7c3e33281 ### No results page <img width="565" alt="image" src="https://github.com/chanzuckerberg/cryoet-data-portal/assets/2176050/18b613c2-a09e-4e3d-9504-1187e0296347">
- Loading branch information
1 parent
ed7b04e
commit f85c4fe
Showing
44 changed files
with
1,714 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import { DeepPartial } from 'utility-types' | ||
|
||
import { Dataset_Authors, Datasets } from 'app/__generated__/graphql' | ||
import { RecursivePartial } from 'app/utils/RecursivePartial' | ||
|
||
export type DatasetType = RecursivePartial<Datasets> & { | ||
authors_with_affiliation?: RecursivePartial<Dataset_Authors>[] | ||
export type DatasetType = DeepPartial<Datasets> & { | ||
authors_with_affiliation?: DeepPartial<Dataset_Authors>[] | ||
} |
82 changes: 82 additions & 0 deletions
82
...end/packages/data-portal/app/components/DatasetFilter/AnnotationMetadataFilterSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { useSearchParams } from '@remix-run/react' | ||
import { useMemo } from 'react' | ||
|
||
import { FilterSection, SelectFilter } from 'app/components/Filters' | ||
import { DatasetFilterQueryParams } from 'app/constants/query' | ||
import { useDatasets } from 'app/hooks/useDatasets' | ||
import { i18n } from 'app/i18n' | ||
import { BaseFilterOption } from 'app/types/filter' | ||
|
||
export function AnnotationMetadataFilterSection() { | ||
const { objectNames, objectShapeTypes } = useDatasets() | ||
const [searchParams, setSearchParams] = useSearchParams() | ||
|
||
const objectNameOptions = useMemo( | ||
() => objectNames.map<BaseFilterOption>((value) => ({ value })), | ||
[objectNames], | ||
) | ||
|
||
const objectNameValue = useMemo<BaseFilterOption[]>( | ||
() => | ||
searchParams | ||
.getAll(DatasetFilterQueryParams.ObjectName) | ||
.map((value) => ({ value })), | ||
[searchParams], | ||
) | ||
|
||
const objectShapeTypeOptions = useMemo( | ||
() => objectShapeTypes.map<BaseFilterOption>((value) => ({ value })), | ||
[objectShapeTypes], | ||
) | ||
|
||
const objectShapeTypeValue = useMemo<BaseFilterOption[]>( | ||
() => | ||
searchParams | ||
.getAll(DatasetFilterQueryParams.ObjectShapeType) | ||
.map((value) => ({ value })), | ||
[searchParams], | ||
) | ||
|
||
return ( | ||
<FilterSection title={i18n.annotationMetadata}> | ||
<SelectFilter | ||
multiple | ||
options={objectNameOptions} | ||
value={objectNameValue} | ||
label={i18n.objectName} | ||
onChange={(options) => | ||
setSearchParams((prev) => { | ||
prev.delete(DatasetFilterQueryParams.ObjectName) | ||
|
||
options?.forEach((option) => | ||
prev.append(DatasetFilterQueryParams.ObjectName, option.value), | ||
) | ||
|
||
return prev | ||
}) | ||
} | ||
/> | ||
|
||
<SelectFilter | ||
multiple | ||
options={objectShapeTypeOptions} | ||
value={objectShapeTypeValue} | ||
label={i18n.objectShapeType} | ||
onChange={(options) => | ||
setSearchParams((prev) => { | ||
prev.delete(DatasetFilterQueryParams.ObjectShapeType) | ||
|
||
options?.forEach((option) => | ||
prev.append( | ||
DatasetFilterQueryParams.ObjectShapeType, | ||
option.value, | ||
), | ||
) | ||
|
||
return prev | ||
}) | ||
} | ||
/> | ||
</FilterSection> | ||
) | ||
} |
24 changes: 24 additions & 0 deletions
24
frontend/packages/data-portal/app/components/DatasetFilter/DatasetFilter.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Filters } from 'app/components/Filters' | ||
import { i18n } from 'app/i18n' | ||
|
||
import { AnnotationMetadataFilterSection } from './AnnotationMetadataFilterSection' | ||
import { HardwareFilterSection } from './HardwareFilterSection' | ||
import { IncludedContentsFilterSection } from './IncludedContentsFilterSection' | ||
import { NameOrIdFilterSection } from './NameOrIdFilterSection' | ||
import { SampleAndExperimentFilterSection } from './SampleAndExperimentFilterSection' | ||
import { TiltSeriesMetadataFilterSection } from './TiltSeriesMetadataFilterSection' | ||
import { TomogramMetadataFilterSection } from './TomogramMetadataFilterSection' | ||
|
||
export function DatasetFilter() { | ||
return ( | ||
<Filters title={i18n.filterBy}> | ||
<IncludedContentsFilterSection /> | ||
<NameOrIdFilterSection /> | ||
<SampleAndExperimentFilterSection /> | ||
<HardwareFilterSection /> | ||
<TiltSeriesMetadataFilterSection /> | ||
<TomogramMetadataFilterSection /> | ||
<AnnotationMetadataFilterSection /> | ||
</Filters> | ||
) | ||
} |
39 changes: 39 additions & 0 deletions
39
frontend/packages/data-portal/app/components/DatasetFilter/HardwareFilterSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { useMemo } from 'react' | ||
|
||
import { FilterSection, SelectFilter } from 'app/components/Filters' | ||
import { DatasetFilterQueryParams } from 'app/constants/query' | ||
import { useDatasetFilter } from 'app/hooks/useDatasetFilter' | ||
import { useDatasets } from 'app/hooks/useDatasets' | ||
import { i18n } from 'app/i18n' | ||
import { BaseFilterOption } from 'app/types/filter' | ||
|
||
export function HardwareFilterSection() { | ||
const { cameraManufacturers } = useDatasets() | ||
|
||
const cameraManufacturerOptions = useMemo( | ||
() => cameraManufacturers.map<BaseFilterOption>((value) => ({ value })), | ||
[cameraManufacturers], | ||
) | ||
|
||
const { | ||
updateValue, | ||
hardware: { cameraManufacturer }, | ||
} = useDatasetFilter() | ||
|
||
const cameraManufacturerValue = useMemo<BaseFilterOption | null>(() => { | ||
return cameraManufacturer ? { value: cameraManufacturer } : null | ||
}, [cameraManufacturer]) | ||
|
||
return ( | ||
<FilterSection title={i18n.hardware}> | ||
<SelectFilter | ||
options={cameraManufacturerOptions} | ||
value={cameraManufacturerValue} | ||
label={i18n.cameraManufacturer} | ||
onChange={(option) => | ||
updateValue(DatasetFilterQueryParams.CameraManufacturer, option) | ||
} | ||
/> | ||
</FilterSection> | ||
) | ||
} |
94 changes: 94 additions & 0 deletions
94
frontend/packages/data-portal/app/components/DatasetFilter/IncludedContentsFilterSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { useMemo } from 'react' | ||
|
||
import { | ||
BooleanFilter, | ||
FilterSection, | ||
SelectFilter, | ||
} from 'app/components/Filters' | ||
import { DatasetFilterQueryParams } from 'app/constants/query' | ||
import { useDatasetFilter } from 'app/hooks/useDatasetFilter' | ||
import { i18n } from 'app/i18n' | ||
import { | ||
AvailableFilesFilterOption, | ||
NumberOfRunsFilterOption, | ||
} from 'app/types/filter' | ||
|
||
const NUMBER_OF_RUN_OPTIONS: NumberOfRunsFilterOption[] = [ | ||
{ value: '>1' }, | ||
{ value: '>5' }, | ||
{ value: '>10' }, | ||
{ value: '>20' }, | ||
{ value: '>100' }, | ||
] | ||
|
||
const AVAILABLE_FILES_OPTIONS: AvailableFilesFilterOption[] = [ | ||
{ value: 'raw-frames', label: i18n.rawFrames }, | ||
{ value: 'tilt-series', label: i18n.tiltSeries }, | ||
{ value: 'tilt-series-alignment', label: i18n.tiltSeriesAlignment }, | ||
{ value: 'tomogram', label: i18n.tomogram }, | ||
] | ||
|
||
export function IncludedContentsFilterSection() { | ||
const { | ||
updateValue, | ||
includedContents: { isGroundTruthEnabled, availableFiles, numberOfRuns }, | ||
} = useDatasetFilter() | ||
|
||
const availableFilesOptions = useMemo( | ||
() => | ||
availableFiles | ||
.map( | ||
(option) => | ||
AVAILABLE_FILES_OPTIONS.find(({ value }) => value === option) ?? | ||
null, | ||
) | ||
.filter((option): option is AvailableFilesFilterOption => !!option), | ||
[availableFiles], | ||
) | ||
|
||
const numberOfRunsOptions = useMemo( | ||
() => | ||
numberOfRuns | ||
? NUMBER_OF_RUN_OPTIONS.find(({ value }) => value === numberOfRuns) ?? | ||
null | ||
: null, | ||
[numberOfRuns], | ||
) | ||
|
||
return ( | ||
<FilterSection title={i18n.includedContents}> | ||
<BooleanFilter | ||
label={i18n.groundTruthAnnotation} | ||
onChange={(value) => | ||
updateValue( | ||
DatasetFilterQueryParams.GroundTruthAnnotation, | ||
value ? 'true' : null, | ||
) | ||
} | ||
value={isGroundTruthEnabled} | ||
/> | ||
|
||
<SelectFilter | ||
multiple | ||
options={AVAILABLE_FILES_OPTIONS} | ||
value={availableFilesOptions} | ||
label={i18n.availableFiles} | ||
onChange={(options) => | ||
updateValue(DatasetFilterQueryParams.AvailableFiles, options) | ||
} | ||
/> | ||
|
||
<SelectFilter | ||
options={NUMBER_OF_RUN_OPTIONS} | ||
value={numberOfRunsOptions} | ||
label={i18n.numberOfRuns} | ||
onChange={(option) => | ||
updateValue( | ||
DatasetFilterQueryParams.NumberOfRuns, | ||
option ? JSON.stringify(option.value) : null, | ||
) | ||
} | ||
/> | ||
</FilterSection> | ||
) | ||
} |
47 changes: 47 additions & 0 deletions
47
frontend/packages/data-portal/app/components/DatasetFilter/NameOrIdFilterSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { | ||
FilterSection, | ||
InputFilterData, | ||
MultiInputFilter, | ||
} from 'app/components/Filters' | ||
import { DatasetFilterQueryParams } from 'app/constants/query' | ||
import { i18n } from 'app/i18n' | ||
|
||
const DATASET_ID_FILTERS: InputFilterData[] = [ | ||
{ | ||
id: 'portal-id-input', | ||
label: `${i18n.portalIdBlank}:`, | ||
queryParam: DatasetFilterQueryParams.PortalId, | ||
}, | ||
{ | ||
id: 'empiar-id-input', | ||
label: `${i18n.empiarID}:`, | ||
queryParam: DatasetFilterQueryParams.EmpiarId, | ||
}, | ||
{ | ||
id: 'emdb-id-input', | ||
label: `${i18n.emdb}:`, | ||
queryParam: DatasetFilterQueryParams.EmdbId, | ||
}, | ||
] | ||
|
||
const AUTHOR_FILTERS: InputFilterData[] = [ | ||
{ | ||
id: 'author-name-input', | ||
label: `${i18n.authorName}:`, | ||
queryParam: DatasetFilterQueryParams.AuthorName, | ||
}, | ||
{ | ||
id: 'author-orcid-input', | ||
label: `${i18n.authorOrcid}:`, | ||
queryParam: DatasetFilterQueryParams.AuthorOrcid, | ||
}, | ||
] | ||
|
||
export function NameOrIdFilterSection() { | ||
return ( | ||
<FilterSection title={i18n.nameOrId}> | ||
<MultiInputFilter label={i18n.datasetIds} filters={DATASET_ID_FILTERS} /> | ||
<MultiInputFilter label={i18n.author} filters={AUTHOR_FILTERS} /> | ||
</FilterSection> | ||
) | ||
} |
41 changes: 41 additions & 0 deletions
41
...nd/packages/data-portal/app/components/DatasetFilter/SampleAndExperimentFilterSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { useMemo } from 'react' | ||
|
||
import { FilterSection, SelectFilter } from 'app/components/Filters' | ||
import { DatasetFilterQueryParams } from 'app/constants/query' | ||
import { useDatasetFilter } from 'app/hooks/useDatasetFilter' | ||
import { useDatasets } from 'app/hooks/useDatasets' | ||
import { i18n } from 'app/i18n' | ||
import { BaseFilterOption } from 'app/types/filter' | ||
|
||
export function SampleAndExperimentFilterSection() { | ||
const { | ||
updateValue, | ||
sampleAndExperimentConditions: { organismNames }, | ||
} = useDatasetFilter() | ||
const { organismNames: allOrganismNames } = useDatasets() | ||
|
||
const organismNameOptions = useMemo( | ||
() => allOrganismNames.map<BaseFilterOption>((name) => ({ value: name })), | ||
[allOrganismNames], | ||
) | ||
|
||
const organismNameValue = useMemo( | ||
() => organismNames.map<BaseFilterOption>((value) => ({ value })), | ||
[organismNames], | ||
) | ||
|
||
return ( | ||
<FilterSection title={i18n.sampleAndExperimentConditions}> | ||
<SelectFilter | ||
multiple | ||
search | ||
options={organismNameOptions} | ||
value={organismNameValue} | ||
label={i18n.organismName} | ||
onChange={(options) => | ||
updateValue(DatasetFilterQueryParams.Organism, options) | ||
} | ||
/> | ||
</FilterSection> | ||
) | ||
} |
10 changes: 10 additions & 0 deletions
10
...end/packages/data-portal/app/components/DatasetFilter/TiltSeriesMetadataFilterSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { FilterSection, TiltRangeFilter } from 'app/components/Filters' | ||
import { i18n } from 'app/i18n' | ||
|
||
export function TiltSeriesMetadataFilterSection() { | ||
return ( | ||
<FilterSection title={i18n.tiltSeriesMetadata}> | ||
<TiltRangeFilter /> | ||
</FilterSection> | ||
) | ||
} |
Oops, something went wrong.