Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: deposition filter banner #1040

Merged
merged 21 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions frontend/packages/data-portal/app/components/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export function Breadcrumbs({

const { browseDatasetHistory } = useBrowseDatasetFilterHistory()
const { singleDatasetHistory } = useSingleDatasetFilterHistory()
const { previousDepositionId } = useDepositionHistory()
const { previousDepositionId, previousSingleDepositionParams } =
useDepositionHistory()

const browseAllLink = useMemo(() => {
const url =
Expand Down Expand Up @@ -83,8 +84,7 @@ export function Breadcrumbs({
{previousDepositionId != null && variant !== 'deposition' && (
<Link
className="uppercase font-semibold text-sds-caps-xxxs leading-sds-caps-xxxs text-sds-primary-400"
// TODO add filter carry back behavior
to={`/depositions/${previousDepositionId}`}
to={`/depositions/${previousDepositionId}?${previousSingleDepositionParams}`}
>
{t('returnToDeposition')}
</Link>
Expand Down
36 changes: 29 additions & 7 deletions frontend/packages/data-portal/app/components/Dataset/RunsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Skeleton from '@mui/material/Skeleton'
import { useNavigate, useSearchParams } from '@remix-run/react'
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
import { range } from 'lodash-es'
import { useEffect, useMemo, useState } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'

import { GetDatasetByIdQuery } from 'app/__generated__/graphql'
import { AnnotatedObjectsList } from 'app/components/AnnotatedObjectsList'
Expand All @@ -16,6 +16,7 @@ import { TiltSeriesQualityScoreBadge } from 'app/components/TiltSeriesQualitySco
import { ViewTomogramButton } from 'app/components/ViewTomogramButton'
import { RUN_FILTERS } from 'app/constants/filterQueryParams'
import { MAX_PER_PAGE } from 'app/constants/pagination'
import { QueryParams } from 'app/constants/query'
import { RunTableWidths } from 'app/constants/table'
import { TiltSeriesScore } from 'app/constants/tiltSeries'
import { useDatasetById } from 'app/hooks/useDatasetById'
Expand All @@ -27,6 +28,7 @@ import {
} from 'app/state/filterHistory'
import { cnsNoMerge } from 'app/utils/cns'
import { inQualityScoreRange } from 'app/utils/tiltSeries'
import { carryOverFilterParams, createUrl } from 'app/utils/url'

type Run = GetDatasetByIdQuery['datasets'][number]['runs'][number]

Expand All @@ -39,7 +41,7 @@ const LOADING_RUNS = range(0, MAX_PER_PAGE).map<Run>(() => ({

export function RunsTable() {
const { isLoadingDebounced } = useIsLoading()
const { dataset } = useDatasetById()
const { dataset, deposition } = useDatasetById()
const runs = dataset.runs as unknown as Run[]
const { t } = useI18n()
const { setSingleDatasetHistory } = useSingleDatasetFilterHistory()
Expand All @@ -61,6 +63,25 @@ export function RunsTable() {
[searchParams, setSingleDatasetHistory],
)

const getRunUrl = useCallback(
(id: number) => {
const url = createUrl(`/runs/${id}`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - since we're only using the path and the query params, do we need createUrl()? what if carryOverFilterParams() just returned a new URLSearchParams and we did return `/runs/${id}\` + urlSearchParams.toString()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to prefer modifying the URL and URLSearchParams objects directly to avoid direct string concatenation, so createUrl() is helpful here since we're only using the pathname and params


carryOverFilterParams({
filters: RUN_FILTERS,
params: url.searchParams,
prevParams: searchParams,
})

if (deposition && searchParams.has(QueryParams.DepositionId)) {
url.searchParams.set(QueryParams.DepositionId, `${deposition.id}`)
}

return url.pathname + url.search
},
[deposition, searchParams],
)

const columns = useMemo(() => {
const columnHelper = createColumnHelper<Run>()

Expand Down Expand Up @@ -106,7 +127,7 @@ export function RunsTable() {
</CellHeader>
),
cell({ row: { original: run } }) {
const runUrl = `/runs/${run.id}`
const runUrl = getRunUrl(run.id)

return (
<TableCell
Expand Down Expand Up @@ -248,19 +269,20 @@ export function RunsTable() {
),
] as ColumnDef<Run>[]
}, [
dataset.id,
dataset.organism_name,
isLoadingDebounced,
t,
isHoveringOverInteractable,
t,
getRunUrl,
dataset.id,
dataset.organism_name,
])

return (
<PageTable
data={isLoadingDebounced ? LOADING_RUNS : runs}
columns={columns}
onTableRowClick={(row) =>
!isHoveringOverInteractable && navigate(`/runs/${row.original.id}`)
!isHoveringOverInteractable && navigate(getRunUrl(row.original.id))
}
hoverType="group"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import Skeleton from '@mui/material/Skeleton'
import { useSearchParams } from '@remix-run/react'
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
import { range, sum } from 'lodash-es'
import { useMemo } from 'react'
import { useCallback, useMemo } from 'react'

import { AnnotatedObjectsList } from 'app/components/AnnotatedObjectsList'
import { AuthorList } from 'app/components/AuthorList'
import { I18n } from 'app/components/I18n'
import { KeyPhoto } from 'app/components/KeyPhoto'
import { Link } from 'app/components/Link'
import { CellHeader, PageTable, TableCell } from 'app/components/Table'
import { DATASET_FILTERS } from 'app/constants/filterQueryParams'
import { ANNOTATED_OBJECTS_MAX, MAX_PER_PAGE } from 'app/constants/pagination'
import { QueryParams } from 'app/constants/query'
import { DepositionPageDatasetTableWidths } from 'app/constants/table'
import { Dataset, useDepositionById } from 'app/hooks/useDepositionById'
import { useI18n } from 'app/hooks/useI18n'
Expand All @@ -22,6 +24,7 @@ import { LogLevel } from 'app/types/logging'
import { cnsNoMerge } from 'app/utils/cns'
import { sendLogs } from 'app/utils/logging'
import { getErrorMessage } from 'app/utils/string'
import { carryOverFilterParams, createUrl } from 'app/utils/url'

const LOADING_DATASETS = range(0, MAX_PER_PAGE).map(
(value) =>
Expand All @@ -45,6 +48,23 @@ export function DatasetsTable() {

const { isLoadingDebounced } = useIsLoading()

const getDatasetUrl = useCallback(
(id: number) => {
const url = createUrl(`/datasets/${id}`)

carryOverFilterParams({
filters: DATASET_FILTERS,
params: url.searchParams,
prevParams: searchParams,
})

url.searchParams.set(QueryParams.DepositionId, `${id}`)

return url.pathname + url.search
},
[searchParams],
)

const columns = useMemo(() => {
const columnHelper = createColumnHelper<Dataset>()

Expand All @@ -54,7 +74,7 @@ export function DatasetsTable() {
header: () => <p />,

cell({ row: { original: dataset } }) {
const datasetUrl = `/datasets/${dataset.id}`
const datasetUrl = getDatasetUrl(dataset.id)

return (
<TableCell
Expand Down Expand Up @@ -103,7 +123,7 @@ export function DatasetsTable() {
),

cell({ row: { original: dataset } }) {
const datasetUrl = `/datasets/${dataset.id}`
const datasetUrl = getDatasetUrl(dataset.id)

return (
<TableCell
Expand Down Expand Up @@ -295,7 +315,14 @@ export function DatasetsTable() {

throw err
}
}, [datasetSort, isLoadingDebounced, searchParams, setSearchParams, t])
}, [
datasetSort,
getDatasetUrl,
isLoadingDebounced,
searchParams,
setSearchParams,
t,
])

return (
<PageTable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Button, Callout } from '@czi-sds/components'

import { I18n } from 'app/components/I18n'
import { QueryParams } from 'app/constants/query'
import { useQueryParam } from 'app/hooks/useQueryParam'
import {
useDepositionHistory,
useSingleDatasetFilterHistory,
} from 'app/state/filterHistory'
import { I18nKeys } from 'app/types/i18n'

interface Deposition {
id: number
title: string
}

export function DepositionFilterBanner({
deposition,
labelI18n,
}: {
deposition: Deposition
labelI18n: I18nKeys
}) {
const { singleDatasetHistory, setSingleDatasetHistory } =
useSingleDatasetFilterHistory()
const { previousSingleDepositionParams } = useDepositionHistory()
const [, setDepositionId] = useQueryParam<string>(QueryParams.DepositionId)

return (
<Callout
className="!w-full !mx-sds-xl"
classes={{ message: 'w-full' }}
intent="info"
>
<div className="flex w-full items-center justify-between">
<p className="text-sds-body-xs leading-sds-body-xs">
<I18n
i18nKey={labelI18n}
values={{
...deposition,
url: `/depositions/${deposition.id}${previousSingleDepositionParams}`,
}}
tOptions={{ interpolation: { escapeValue: false } }}
/>
</p>

<Button
onClick={() => {
setDepositionId(null)

const nextHistory = new Map(singleDatasetHistory)
nextHistory.delete(QueryParams.DepositionId)
setSingleDatasetHistory(nextHistory)
}}
sdsStyle="minimal"
sdsType="secondary"
>
Remove Filter
</Button>
</div>
</Callout>
)
}
10 changes: 4 additions & 6 deletions frontend/packages/data-portal/app/components/Link/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { Link as RemixLink, LinkProps } from '@remix-run/react'
import { ForwardedRef, forwardRef } from 'react'

import {
DASHED_BORDERED_CLASSES,
DASHED_UNDERLINED_CLASSES,
} from 'app/utils/classNames'
import { cnsNoMerge } from 'app/utils/cns'
import { isExternalUrl } from 'app/utils/url'

export const DASHED_BORDERED_CLASSES =
'border-b border-dashed hover:border-solid border-current'

export const DASHED_UNDERLINED_CLASSES =
'underline underline-offset-[3px] decoration-dashed hover:decoration-solid'

export type VariantLinkProps = LinkProps & {
variant?: 'dashed-bordered' | 'dashed-underlined'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { ComponentProps, ReactNode, useCallback, useMemo } from 'react'

import { AuthorList } from 'app/components/AuthorList'
import { I18n } from 'app/components/I18n'
import { DASHED_BORDERED_CLASSES } from 'app/components/Link'
import { CellHeader, PageTable, TableCell } from 'app/components/Table'
import { Tooltip } from 'app/components/Tooltip'
import {
Expand All @@ -35,6 +34,7 @@ import {
import { useRunById } from 'app/hooks/useRunById'
import { AnnotationRow, useAnnotation } from 'app/state/annotation'
import { I18nKeys } from 'app/types/i18n'
import { DASHED_BORDERED_CLASSES } from 'app/utils/classNames'
import { cns, cnsNoMerge } from 'app/utils/cns'

const LOADING_ANNOTATIONS = range(0, MAX_PER_PAGE).map<AnnotationRow>(() => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { TableCount } from './Table/TableCount'
import { Tabs } from './Tabs'

export interface TablePageLayoutProps {
banner?: ReactNode
header?: ReactNode

tabs: TableLayoutTab[] // If there is only 1 tab, the tab selector will not show.
Expand All @@ -26,6 +27,7 @@ export interface TablePageLayoutProps {
export interface TableLayoutTab {
title: string

banner?: ReactNode
filterPanel?: ReactNode

table: ReactNode
Expand All @@ -44,6 +46,7 @@ export function TablePageLayout({
tabsTitle,
downloadModal,
drawers,
banner,
}: TablePageLayoutProps) {
const [searchParams, setSearchParams] = useSearchParams()

Expand Down Expand Up @@ -87,7 +90,7 @@ export function TablePageLayout({
</div>
)}

<TablePageTabContent {...activeTab} />
<TablePageTabContent banner={banner} {...activeTab} />

{drawers}
</div>
Expand All @@ -105,6 +108,7 @@ function TablePageTabContent({
pageQueryParamKey = QueryParams.Page,
totalCount,
countLabel,
banner,
}: TableLayoutTab) {
const [searchParams, setSearchParams] = useSearchParams()
const pageQueryParamValue = +(searchParams.get(pageQueryParamKey) ?? '1')
Expand Down Expand Up @@ -165,6 +169,8 @@ function TablePageTabContent({
filterPanel && 'screen-2040:translate-x-[-100px] max-w-content',
)}
>
<div className="flex mb-sds-xl">{banner}</div>

<div className="px-sds-xl flex items-center gap-x-sds-xl">
<p className="text-sds-header-l leading-sds-header-l font-semibold">
{title}
Expand Down
17 changes: 14 additions & 3 deletions frontend/packages/data-portal/app/constants/filterQueryParams.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { QueryParams } from './query'

export const DATASET_FILTERS = [
const COMMON_DATASET_FILTERS = [
QueryParams.GroundTruthAnnotation,
QueryParams.AvailableFiles,
QueryParams.NumberOfRuns,
QueryParams.DatasetId,
QueryParams.EmpiarId,
QueryParams.EmdbId,
QueryParams.AuthorName,
QueryParams.AuthorOrcid,
QueryParams.Organism,
Expand All @@ -20,13 +18,21 @@ export const DATASET_FILTERS = [
QueryParams.ObjectShapeType,
] as const

export const DATASET_FILTERS = [
...COMMON_DATASET_FILTERS,
QueryParams.EmpiarId,
QueryParams.EmdbId,
QueryParams.DepositionId,
] as const

export const RUN_FILTERS = [
QueryParams.GroundTruthAnnotation,
QueryParams.QualityScore,
QueryParams.TiltRangeMin,
QueryParams.TiltRangeMax,
QueryParams.ObjectName,
QueryParams.ObjectShapeType,
QueryParams.DepositionId,
] as const

export const ANNOTATION_FILTERS = [
Expand All @@ -38,3 +44,8 @@ export const ANNOTATION_FILTERS = [
QueryParams.MethodType,
QueryParams.AnnotationSoftware,
] as const

export const DEPOSITION_FILTERS = [
...COMMON_DATASET_FILTERS,
QueryParams.ObjectId,
] as const
Loading
Loading