From 83374b0227b4e2b006d27f51da9dfe466a270505 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 11 Nov 2024 14:54:22 -0500 Subject: [PATCH 01/51] updated trackhub file for bedset --- bedhost/routers/bedset_api.py | 30 ++++++++++++------------------ requirements/requirements-all.txt | 4 ++-- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/bedhost/routers/bedset_api.py b/bedhost/routers/bedset_api.py index bcf05d3..4c769d2 100644 --- a/bedhost/routers/bedset_api.py +++ b/bedhost/routers/bedset_api.py @@ -160,27 +160,21 @@ async def get_genomes_file_bedset(request: Request, bedset_id: str): @router.head("/{bedset_id}/track_hub_trackDb_file", include_in_schema=False) -@router.get("/{bedset_id}/track_hub_trackDb_file", include_in_schema=False) +@router.get("/{bedset_id}/track_hub_trackDb_file", include_in_schema=True) async def get_trackDb_file_bedset(bedset_id: str): """ Generate trackDb file for the BED set track hub """ - - hit = bbagent.bedset.get_bedset_bedfiles(bedset_id) - - trackDb_txt = "" - for bed in hit.results: - metadata = bbagent.bed.get(bed.id, full=True) - - if metadata.files.bigbed_file: - - trackDb_txt = ( - trackDb_txt + f"track\t {metadata.name}\n" - "type\t bigBed\n" - f"bigDataUrl\t {metadata.files.bigbed_file.access_methods[0].access_url.url} \n" - f"shortLabel\t {metadata.name}\n" - f"longLabel\t {metadata.description}\n" - "visibility\t full\n\n" - ) + # Response should be this type: + # trackDb_txt = ( + # trackDb_txt + f"track\t {metadata.name}\n" + # "type\t bigBed\n" + # f"bigDataUrl\t {metadata.files.bigbed_file.access_methods[0].access_url.url} \n" + # f"shortLabel\t {metadata.name}\n" + # f"longLabel\t {metadata.description}\n" + # "visibility\t full\n\n" + # ) + + trackDb_txt = bbagent.bedset.get_track_hub_file(bedset_id) return Response(trackDb_txt, media_type="text/plain") diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index 46423aa..451418d 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -1,5 +1,5 @@ -# bbconf @ git+https://github.com/databio/bbconf.git@dev#egg=bbconf -bbconf>=0.9.0 +bbconf @ git+https://github.com/databio/bbconf.git@dev#egg=bbconf +# bbconf>=0.9.1 fastapi>=0.103.0 logmuse>=0.2.7 markdown From 1358cb83030f2385b380064856881f71c7beed6d Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 11 Nov 2024 14:56:13 -0500 Subject: [PATCH 02/51] excluded from schema trackhub endpoint --- bedhost/routers/bedset_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bedhost/routers/bedset_api.py b/bedhost/routers/bedset_api.py index 4c769d2..87d3363 100644 --- a/bedhost/routers/bedset_api.py +++ b/bedhost/routers/bedset_api.py @@ -160,7 +160,7 @@ async def get_genomes_file_bedset(request: Request, bedset_id: str): @router.head("/{bedset_id}/track_hub_trackDb_file", include_in_schema=False) -@router.get("/{bedset_id}/track_hub_trackDb_file", include_in_schema=True) +@router.get("/{bedset_id}/track_hub_trackDb_file", include_in_schema=False) async def get_trackDb_file_bedset(bedset_id: str): """ Generate trackDb file for the BED set track hub From 8e15412e2e761f4970fc290fca55ba6ae21a452a Mon Sep 17 00:00:00 2001 From: Sam Park Date: Tue, 12 Nov 2024 15:05:25 -0500 Subject: [PATCH 03/51] fix search table stretched link in safari --- .../components/search/search-bedset-table.tsx | 14 +++- .../text2bed/t2b-search-results-table.tsx | 81 +++++++++---------- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/ui/src/components/search/search-bedset-table.tsx b/ui/src/components/search/search-bedset-table.tsx index 9417728..3e2c9d0 100644 --- a/ui/src/components/search/search-bedset-table.tsx +++ b/ui/src/components/search/search-bedset-table.tsx @@ -9,6 +9,12 @@ type Props = { export const SearchBedSetResultTable = (props: Props) => { const { results } = props; + const handleRowClick = (id?: string) => (e: React.MouseEvent) => { + if (!(e.target as HTMLElement).closest('button')) { + window.location.href = `/bedset/${id}`; + } + }; + return ( @@ -24,13 +30,17 @@ export const SearchBedSetResultTable = (props: Props) => { {results.results?.map((result) => ( - + -

Overview

+

Overview

-
{result?.id || 'Unknown Id'} {result?.name || 'Unknown Name'} {result?.description || 'Unknown Description'} {result?.bed_ids?.length || 0} - + diff --git a/ui/src/components/search/text2bed/t2b-search-results-table.tsx b/ui/src/components/search/text2bed/t2b-search-results-table.tsx index c5f9765..0fe727a 100644 --- a/ui/src/components/search/text2bed/t2b-search-results-table.tsx +++ b/ui/src/components/search/text2bed/t2b-search-results-table.tsx @@ -15,30 +15,38 @@ type Props = { export const Text2BedSearchResultsTable = (props: Props) => { const { results } = props; const { cart, addBedToCart, removeBedFromCart } = useBedCart(); + + const handleRowClick = (id?: string) => (e: React.MouseEvent) => { + if (!(e.target as HTMLElement).closest('button')) { + window.location.href = `/bed/${id}`; + } + }; + return ( - - - - - - - {/**/} - {/**/} - - - - - {/* */} - - + + + + + + + + + + + + - {results.results?.map((result) => ( - + {results.results?.map((result) => ( + - {/**/} - {/**/} - - {/**/} - - {/* */} - {/**/} - - - ); - })} - - ))} + + {metadata.plots && + chunkArray(plotNames, 3).map((chunk, idx) => ( + + {chunk.map((plotName) => { + // this is for type checking + const plotNameKey = plotName as keyof typeof metadata.plots; + const plotExists = metadata.plots && metadata.plots[plotNameKey]; + // @ts-expect-error: type checking here is just too much + const title = plotExists ? metadata.plots[plotNameKey]?.title : plotName; + const alt = plotExists + ? // @ts-expect-error: type checking here is just too much + metadata.plots[plotNameKey]?.description || metadata.plots[plotNameKey].title + : plotName; + return ( + + + + ); + })} + + ))} + ); diff --git a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx index 844a427..b30f9c8 100644 --- a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx +++ b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx @@ -183,17 +183,23 @@ export const Bed2BedSearchResultsTable = (props: Props) => { getFilteredRowModel: getFilteredRowModel(), }); + const handleRowClick = (id?: string) => (e: React.MouseEvent) => { + if (!(e.target as HTMLElement).closest('button')) { + window.location.href = `/bed/${id}`; + } + }; + return (
setGlobalFilter(e.target.value)} />
-
NameGenomeTissueCell LineCell TypeTarget AntibodyDescriptionAssayInfoScoreBEDbase ID - Actions -
NameGenomeTissueCell LineCell TypeDescriptionAssayInfoScore + Actions +
{result?.metadata?.name || 'No name'} {result?.metadata?.genome_alias || 'N/A'} @@ -46,12 +54,8 @@ export const Text2BedSearchResultsTable = (props: Props) => { {result?.metadata?.annotation?.tissue || 'N/A'} {result?.metadata?.annotation?.cell_line || 'N/A'} {result?.metadata?.annotation?.cell_type || 'N/A'}{result?.metadata?.annotation?.target || 'N/A'}{result?.metadata?.annotation?.antibody || 'N/A'}{result?.metadata?.description || ''} {result?.metadata?.annotation?.assay || 'N/A'} { } > - + @@ -77,30 +81,17 @@ export const Text2BedSearchResultsTable = (props: Props) => { variant="primary" /> {result?.metadata?.id || 'No id'}*/} - {/* /!*{result?.metadata?.submission_date === undefined*!/*/} - {/* /!* ? 'No date'*!/*/} - {/* /!* : new Date(result.metadata?.submission_date).toLocaleDateString()}*!/\*/} - {/* */} - {/* - - {/**/} - {cart.includes(result?.metadata?.id || '') ? ( ) : ( -

{metadata.name}

+
+ {metadata.name} +
+ {metadata.description} +
+
+ +
+

@@ -243,17 +251,17 @@ export const BedSplashHeader = (props: Props) => {

)}
-
-
- +
+
+

Created:{' '} {metadata?.submission_date ? formatDateTime(metadata?.submission_date) : 'No date available'}

-
- +
+

Last update:{' '} {metadata?.last_update_date ? formatDateTime(metadata?.last_update_date) : 'No date available'} From 891e877ada53a29c6391e40488c525569796bfd8 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 13 Nov 2024 16:16:25 -0500 Subject: [PATCH 06/51] ui - disabled link if genome digest is not provided --- ui/src/components/bed-splash-components/header.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index a3078ed..1887704 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -162,12 +162,19 @@ export const BedSplashHeader = (props: Props) => {

} > -
+ {metadata?.genome_digest ? ( + +
+ + {metadata.genome_alias || 'No assembly available'} +
+
+ ) : (
- {metadata?.genome_alias || 'No assembly available'} + {metadata.genome_alias || 'No assembly available'}
- + )}

From b43828a325603332978d1500321618aabf482c9d Mon Sep 17 00:00:00 2001 From: Sam Park Date: Thu, 14 Nov 2024 12:38:28 -0500 Subject: [PATCH 07/51] bootstrap detail cleanup --- .../bed-splash-components/plots.tsx | 60 ++++++++++--------- .../bed2bed/b2b-search-results-table.tsx | 24 +++++--- ui/src/pages/bed-splash.tsx | 44 ++++++++++---- 3 files changed, 80 insertions(+), 48 deletions(-) diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index a773d49..1a3f0b3 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -31,13 +31,13 @@ const Plot = (props: PlotProps) => { }} className="h-100 border rounded p-1 shadow-sm hover-border-primary transition-all" > -
- {title} +
+ {title} {/* */}
-
+
{alt}
{ return (
- {metadata.plots && - chunkArray(plotNames, 3).map((chunk, idx) => ( - - {chunk.map((plotName) => { - // this is for type checking - const plotNameKey = plotName as keyof typeof metadata.plots; - const plotExists = metadata.plots && metadata.plots[plotNameKey]; - // @ts-expect-error: type checking here is just too much - const title = plotExists ? metadata.plots[plotNameKey]?.title : plotName; - const alt = plotExists - ? // @ts-expect-error: type checking here is just too much - metadata.plots[plotNameKey]?.description || metadata.plots[plotNameKey].title - : plotName; - return ( -
+
{table.getHeaderGroups().map((headerGroup) => ( @@ -215,8 +221,8 @@ export const Bed2BedSearchResultsTable = (props: Props) => { > {flexRender(header.column.columnDef.header, header.getContext())} {{ - asc: ' 🔼', - desc: ' 🔽', + asc: , + desc: , }[header.column.getIsSorted() as string] ?? null} )} @@ -227,7 +233,11 @@ export const Bed2BedSearchResultsTable = (props: Props) => { {table.getRowModel().rows.map((row) => ( - + {row.getVisibleCells().map((cell) => ( ))} @@ -236,8 +246,8 @@ export const Bed2BedSearchResultsTable = (props: Props) => {
{flexRender(cell.column.columnDef.cell, cell.getContext())}
-
-
+
+
Showing {table.getState().pagination.pageSize * table.getState().pagination.pageIndex + 1} to{' '} diff --git a/ui/src/pages/bed-splash.tsx b/ui/src/pages/bed-splash.tsx index cd5fb4c..47f0563 100644 --- a/ui/src/pages/bed-splash.tsx +++ b/ui/src/pages/bed-splash.tsx @@ -68,10 +68,10 @@ export const BedSplash = () => { >

Oh no!

-

+

We could not find BED with record identifier:
{bedId} -

+

@@ -108,11 +108,11 @@ export const BedSplash = () => { {metadata !== undefined ? : null} - +

+
@@ -146,7 +146,7 @@ export const BedSplash = () => { -

BED Sets

+

BED Sets

Key
@@ -179,25 +179,45 @@ export const BedSplash = () => { -

Statistics

- + + +

Statistics

{metadata && ( -
+ )} - + {/* */} -

Plots

- +
+

Plots

+ + + + + +

Similar BED Files

+ {metadata && ( +
+ + + + + + )} + + + {/* */} + + ); From 86e9e3770b3eed5b3819d4b495c18b0a98a78b5a Mon Sep 17 00:00:00 2001 From: Sam Park Date: Thu, 14 Nov 2024 18:19:22 -0500 Subject: [PATCH 08/51] address #153 and #154, and clean up more ui related details --- ui/bedbase-types.d.ts | 11 ++ .../bed-splash-components/plots.tsx | 67 +++++------ .../bedset-splash-components/beds-table.tsx | 104 +++++++++--------- .../bedset-splash-components/plots.tsx | 8 +- ui/src/components/modals/figure-modal.tsx | 20 +++- .../bed2bed/b2b-search-results-table.tsx | 6 +- .../text2bed/t2b-search-results-table.tsx | 5 +- .../components/search/text2bed/text2bed.tsx | 2 +- ui/src/components/search/text2bedset.tsx | 6 +- ui/src/custom.scss | 5 + ui/src/pages/bed-splash.tsx | 40 ++++--- ui/src/pages/bedset-splash.tsx | 58 +++++----- ui/src/queries/useBedNeighbours.ts | 24 ++++ ui/src/queries/useBedSetBedfiles.ts | 17 ++- ui/src/queries/useBedsetMetadata.ts | 17 ++- ui/src/utils.ts | 5 + 16 files changed, 237 insertions(+), 158 deletions(-) create mode 100644 ui/src/queries/useBedNeighbours.ts diff --git a/ui/bedbase-types.d.ts b/ui/bedbase-types.d.ts index 410d2cb..ded3271 100644 --- a/ui/bedbase-types.d.ts +++ b/ui/bedbase-types.d.ts @@ -678,6 +678,17 @@ export interface components { /** Results */ results?: components["schemas"]["QdrantSearchResult"][]; }; + /** BedNeighborsResult */ + BedNeighboursResult: { + /** Count */ + count: number; + /** Limit */ + limit: number; + /** Offset */ + offset: number; + /** Results */ + results?: components["schemas"]["QdrantSearchResult"][]; + }; /** BedMetadataAll */ BedMetadataAll: { /** diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index 1a3f0b3..201410e 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { Col, Image, Row } from 'react-bootstrap'; import { components } from '../../../bedbase-types'; -import { chunkArray, makeThumbnailImageLink } from '../../utils'; +import { chunkArray, makeThumbnailImageLink , makePDFImageLink } from '../../utils'; import { Fragment } from 'react'; import { FigureModal } from '../modals/figure-modal'; @@ -13,12 +13,13 @@ type PlotsProps = { type PlotProps = { src: string; + pdf: string; alt: string; title: string; }; const Plot = (props: PlotProps) => { - const { src, alt, title } = props; + const { src, pdf, alt, title } = props; const [show, setShow] = useState(false); return ( @@ -47,6 +48,7 @@ const Plot = (props: PlotProps) => { }} title={title} src={src} + pdf={pdf} alt={alt} /> @@ -55,39 +57,40 @@ const Plot = (props: PlotProps) => { export const Plots = (props: PlotsProps) => { const { metadata } = props; + console.log(props) + const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( -
- - {metadata.plots && - chunkArray(plotNames, 3).map((chunk, idx) => ( - - {chunk.map((plotName) => { - // this is for type checking - const plotNameKey = plotName as keyof typeof metadata.plots; - const plotExists = metadata.plots && metadata.plots[plotNameKey]; - // @ts-expect-error: type checking here is just too much - const title = plotExists ? metadata.plots[plotNameKey]?.title : plotName; - const alt = plotExists - ? // @ts-expect-error: type checking here is just too much - metadata.plots[plotNameKey]?.description || metadata.plots[plotNameKey].title - : plotName; - return ( -
- - - ); - })} - - ))} - - + + {metadata.plots && + chunkArray(plotNames, 3).map((chunk, idx) => ( + + {chunk.map((plotName) => { + // this is for type checking + const plotNameKey = plotName as keyof typeof metadata.plots; + const plotExists = metadata.plots && metadata.plots[plotNameKey]; + // @ts-expect-error: type checking here is just too much + const title = plotExists ? metadata.plots[plotNameKey]?.title : plotName; + const alt = plotExists + ? // @ts-expect-error: type checking here is just too much + metadata.plots[plotNameKey]?.description || metadata.plots[plotNameKey].title + : plotName; + return ( + + + + ); + })} + + ))} + ); }; diff --git a/ui/src/components/bedset-splash-components/beds-table.tsx b/ui/src/components/bedset-splash-components/beds-table.tsx index 69e2e00..fb554ac 100644 --- a/ui/src/components/bedset-splash-components/beds-table.tsx +++ b/ui/src/components/bedset-splash-components/beds-table.tsx @@ -139,65 +139,67 @@ export const BedsTable = (props: Props) => { }); return ( -
+
setGlobalFilter(e.target.value)} />
-
- - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => ( - - ))} - - ))} - - - {table.getRowModel().rows.map((row) => ( - (window.location.href = `/bed/${row.original.id}`)} - > - {row.getVisibleCells().map((cell) => ( - - ))} - - ))} - -
- {header.isPlaceholder ? null : ( -
- {flexRender(header.column.columnDef.header, header.getContext())} - {{ - asc: ' 🔼', - desc: ' 🔽', - }[header.column.getIsSorted() as string] ?? null} -
- )} -
- {flexRender(cell.column.columnDef.cell, cell.getContext())} -
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + ))} + + ))} + + + {table.getRowModel().rows.map((row) => ( + (window.location.href = `/bed/${row.original.id}`)} + > + {row.getVisibleCells().map((cell) => ( + + ))} + + ))} + +
+ {header.isPlaceholder ? null : ( +
+ {flexRender(header.column.columnDef.header, header.getContext())} + {{ + asc: , + desc: , + }[header.column.getIsSorted() as string] ?? null} +
+ )} +
+ {flexRender(cell.column.columnDef.cell, cell.getContext())} +
+
-
+
Showing diff --git a/ui/src/components/bedset-splash-components/plots.tsx b/ui/src/components/bedset-splash-components/plots.tsx index d2575cc..e9b84d1 100644 --- a/ui/src/components/bedset-splash-components/plots.tsx +++ b/ui/src/components/bedset-splash-components/plots.tsx @@ -58,10 +58,10 @@ export const Plots = (props: PlotsProps) => { const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( -
+ {metadata.plots && chunkArray(plotNames, 3).map((chunk, idx) => ( - + {chunk.map((plotName) => { // this is for type checking const plotNameKey = plotName as keyof typeof metadata.plots; @@ -83,9 +83,9 @@ export const Plots = (props: PlotsProps) => { ); })} - + ))} -
+
); }; diff --git a/ui/src/components/modals/figure-modal.tsx b/ui/src/components/modals/figure-modal.tsx index a60a700..f010c15 100644 --- a/ui/src/components/modals/figure-modal.tsx +++ b/ui/src/components/modals/figure-modal.tsx @@ -3,13 +3,15 @@ import { Modal } from 'react-bootstrap'; type Props = { title: string; src: string; + pdf?: string; alt: string; show: boolean; onHide: () => void; }; export const FigureModal = (props: Props) => { - const { title, src, alt, show, onHide } = props; + const { title, src, pdf, alt, show, onHide } = props; + return ( { link.click(); }} > - Download + Download PNG + + {pdf && + + } + diff --git a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx index b30f9c8..47b42d5 100644 --- a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx +++ b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx @@ -190,10 +190,10 @@ export const Bed2BedSearchResultsTable = (props: Props) => { }; return ( -
+
setGlobalFilter(e.target.value)} @@ -246,7 +246,7 @@ export const Bed2BedSearchResultsTable = (props: Props) => {
-
+
Showing diff --git a/ui/src/components/search/text2bed/t2b-search-results-table.tsx b/ui/src/components/search/text2bed/t2b-search-results-table.tsx index 0fe727a..971ee3b 100644 --- a/ui/src/components/search/text2bed/t2b-search-results-table.tsx +++ b/ui/src/components/search/text2bed/t2b-search-results-table.tsx @@ -7,15 +7,16 @@ import toast from 'react-hot-toast'; import YAML from 'js-yaml'; type SearchResponse = components['schemas']['BedListSearchResult']; +type BedNeighboursResponse = components['schemas']['BedNeighboursResult']; type Props = { - results: SearchResponse; + results: SearchResponse | BedNeighboursResponse; }; export const Text2BedSearchResultsTable = (props: Props) => { const { results } = props; const { cart, addBedToCart, removeBedFromCart } = useBedCart(); - + const handleRowClick = (id?: string) => (e: React.MouseEvent) => { if (!(e.target as HTMLElement).closest('button')) { window.location.href = `/bed/${id}`; diff --git a/ui/src/components/search/text2bed/text2bed.tsx b/ui/src/components/search/text2bed/text2bed.tsx index 1c27b70..bb001ca 100644 --- a/ui/src/components/search/text2bed/text2bed.tsx +++ b/ui/src/components/search/text2bed/text2bed.tsx @@ -65,7 +65,7 @@ export const Text2Bed = () => { ) : (
{results ? ( -
+
{' '} diff --git a/ui/src/components/search/text2bedset.tsx b/ui/src/components/search/text2bedset.tsx index b24a9fb..a119108 100644 --- a/ui/src/components/search/text2bedset.tsx +++ b/ui/src/components/search/text2bedset.tsx @@ -60,8 +60,10 @@ export const Text2BedSet = () => { ) : (
{results ? ( -
- +
+
+ +
{' '}
diff --git a/ui/src/custom.scss b/ui/src/custom.scss index 4bb6466..9213e47 100644 --- a/ui/src/custom.scss +++ b/ui/src/custom.scss @@ -298,4 +298,9 @@ a { .small-font { font-size: 0.9rem; /* Adjust the value as needed */ +} + +th, td { + padding-left: 1rem !important; + padding-right: 1rem !important; } \ No newline at end of file diff --git a/ui/src/pages/bed-splash.tsx b/ui/src/pages/bed-splash.tsx index 47f0563..8615886 100644 --- a/ui/src/pages/bed-splash.tsx +++ b/ui/src/pages/bed-splash.tsx @@ -13,6 +13,9 @@ import { Plots } from '../components/bed-splash-components/plots'; import { AxiosError } from 'axios'; import { GCContentCard } from '../components/bed-splash-components/cards/gc-content-card'; import { snakeToTitleCase } from '../utils'; +import { Text2BedSearchResultsTable } from '../components/search/text2bed/t2b-search-results-table.tsx'; +import { useBedNeighbours } from '../queries/useBedNeighbours'; + export const BedSplash = () => { const params = useParams(); @@ -28,6 +31,14 @@ export const BedSplash = () => { full: true, }); + const { + data: neighbours, + } = useBedNeighbours({ + md5: bedId, + limit: 10, + offset: 0, + }); + if (isLoading) { return ( @@ -111,8 +122,8 @@ export const BedSplash = () => {

Overview

-
- +
+
@@ -147,8 +158,8 @@ export const BedSplash = () => {

BED Sets

-
-
Key
+
+
@@ -202,21 +213,14 @@ export const BedSplash = () => { - -

Similar BED Files

- {metadata && ( -
- - - - + { neighbours && + +

Similar BED Files

+
+ - )} - - - {/* */} - - + + } diff --git a/ui/src/pages/bedset-splash.tsx b/ui/src/pages/bedset-splash.tsx index d31ccf6..c281b1f 100644 --- a/ui/src/pages/bedset-splash.tsx +++ b/ui/src/pages/bedset-splash.tsx @@ -64,17 +64,17 @@ export const BedsetSplash = () => { } else if (error) { if ((error as AxiosError)?.response?.status === 404) { return ( - +

Oh no!

-

+

We could not find BEDset with record identifier:
{bedsetId} -

+

@@ -102,18 +102,19 @@ export const BedsetSplash = () => { } } else { return ( - +

-
+ {metadata !== undefined ? : null} -

Statistics

- + + +

Statistics

{metadata && ( - -
+ <> + @@ -121,28 +122,35 @@ export const BedsetSplash = () => { - + )} -

Plots

+ - +
+

Plots

+ + -

BED files in this BED set

+ - {isLoadingBedfiles ? ( -
- - {Array.from({ length: 10 }).map((_, index) => ( -
- -
- ))} -
- ) : ( - bedfiles && - )} +

BED files in this BED set

+
+ {isLoadingBedfiles ? ( +
+ + {Array.from({ length: 10 }).map((_, index) => ( +
+ +
+ ))} +
+ ) : ( + bedfiles && + )} + + ); diff --git a/ui/src/queries/useBedNeighbours.ts b/ui/src/queries/useBedNeighbours.ts new file mode 100644 index 0000000..885ec32 --- /dev/null +++ b/ui/src/queries/useBedNeighbours.ts @@ -0,0 +1,24 @@ +import { useQuery } from '@tanstack/react-query'; +import { useBedbaseApi } from '../contexts/api-context'; +import { components } from '../../bedbase-types'; + +type BedNeighboursResponse = components['schemas']['BedNeighboursResult']; +type BedNeighboursQuery = { + md5?: string; + limit?: number; + offset?: number; +}; + +export const useBedNeighbours = (query: BedNeighboursQuery) => { + const { api } = useBedbaseApi(); + + const { md5, limit } = query; + + return useQuery({ + queryKey: ['neighbours', md5], + queryFn: async () => { + const { data } = await api.get(`/bed/${md5}/neighbours?limit=${limit}`); + return data; + } + }); +}; diff --git a/ui/src/queries/useBedSetBedfiles.ts b/ui/src/queries/useBedSetBedfiles.ts index ffa5edc..b700377 100644 --- a/ui/src/queries/useBedSetBedfiles.ts +++ b/ui/src/queries/useBedSetBedfiles.ts @@ -1,6 +1,6 @@ import type { components } from '../../bedbase-types'; import { useQuery } from '@tanstack/react-query'; -import { useBedbaseApi } from '../contexts/api-context.tsx'; +import { useBedbaseApi } from '../contexts/api-context'; type BedSetBedfilesResponse = components['schemas']['BedSetBedFiles']; @@ -11,11 +11,7 @@ type BedSetBedfilesQuery = { export const useBedsetBedfiles = (query: BedSetBedfilesQuery) => { const { api } = useBedbaseApi(); - const { id, autoRun } = query; - let enabled = false; - if (autoRun !== undefined && autoRun && id) { - enabled = true; - } + const { id } = query; return useQuery({ queryKey: ['bedset-bedfiles', id], @@ -23,7 +19,10 @@ export const useBedsetBedfiles = (query: BedSetBedfilesQuery) => { const { data } = await api.get(`/bedset/${id}/bedfiles`); return data; }, - enabled: enabled, - staleTime: 0, + enabled: Boolean(id), + staleTime: 5 * 60 * 1000, // Consider data fresh for 5 minutes + gcTime: 30 * 60 * 1000, // This replaces cacheTime in newer versions + refetchOnWindowFocus: false, + refetchOnMount: false, }); -}; +}; \ No newline at end of file diff --git a/ui/src/queries/useBedsetMetadata.ts b/ui/src/queries/useBedsetMetadata.ts index e847bf9..303448c 100644 --- a/ui/src/queries/useBedsetMetadata.ts +++ b/ui/src/queries/useBedsetMetadata.ts @@ -1,6 +1,6 @@ import type { components } from '../../bedbase-types'; import { useQuery } from '@tanstack/react-query'; -import { useBedbaseApi } from '../contexts/api-context.tsx'; +import { useBedbaseApi } from '../contexts/api-context'; type BedSetMetadataResponse = components['schemas']['BedSetMetadata']; @@ -11,11 +11,7 @@ type BedSetMetadataQuery = { export const useBedsetMetadata = (query: BedSetMetadataQuery) => { const { api } = useBedbaseApi(); - const { md5, autoRun } = query; - let enabled = false; - if (autoRun !== undefined && autoRun && md5) { - enabled = true; - } + const { md5 } = query; return useQuery({ queryKey: ['bedset-metadata', md5], @@ -23,7 +19,10 @@ export const useBedsetMetadata = (query: BedSetMetadataQuery) => { const { data } = await api.get(`/bedset/${md5}/metadata`); return data; }, - enabled: enabled, - staleTime: 0, + enabled: Boolean(md5), + staleTime: 5 * 60 * 1000, + gcTime: 30 * 60 * 1000, // This replaces cacheTime in newer versions + refetchOnWindowFocus: false, + refetchOnMount: false, }); -}; +}; \ No newline at end of file diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 1af3a65..ce365ad 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -23,6 +23,11 @@ export const makeThumbnailImageLink = (md5: string, plotName: string, type: Obje return `${API_BASE}/objects/${type}.${md5}.${plotName}/access/http/thumbnail`; }; +export const makePDFImageLink = (md5: string, plotName: string, type: ObjectType) => { + const API_BASE = import.meta.env.VITE_API_BASE || ''; + return `${API_BASE}/objects/${type}.${md5}.${plotName}/access/http/bytes`; +}; + export const formatDateTime = (date: string) => { return new Date(date).toLocaleString(); }; From 52543cd8658b7f58154d21fb29d47324fffd9552 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Fri, 15 Nov 2024 00:39:05 -0500 Subject: [PATCH 09/51] ui detail cleanup --- .../bed-splash-components/header.tsx | 11 +++----- .../bed-splash-components/plots.tsx | 2 +- .../bedset-splash-components/beds-table.tsx | 6 ++-- .../bedset-splash-components/header.tsx | 28 +++++++++++-------- .../bedset-splash-components/plots.tsx | 2 +- ui/src/components/modals/figure-modal.tsx | 2 +- .../bed2bed/b2b-search-results-table.tsx | 2 +- ui/src/pages/bed-cart.tsx | 2 +- ui/src/pages/bed-splash.tsx | 15 +++++----- ui/src/pages/bedset-splash.tsx | 28 +++++++++---------- 10 files changed, 50 insertions(+), 48 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index 1887704..2b67ee8 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -141,15 +141,12 @@ export const BedSplashHeader = (props: Props) => { -
- {metadata.name} -
- {metadata.description} -
+
+
{metadata.name}
+

{metadata.description}

-

@@ -270,7 +267,7 @@ export const BedSplashHeader = (props: Props) => {

- Last update:{' '} + Updated:{' '} {metadata?.last_update_date ? formatDateTime(metadata?.last_update_date) : 'No date available'}

diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index 201410e..770b1cb 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -62,7 +62,7 @@ export const Plots = (props: PlotsProps) => { const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( - + {metadata.plots && chunkArray(plotNames, 3).map((chunk, idx) => ( diff --git a/ui/src/components/bedset-splash-components/beds-table.tsx b/ui/src/components/bedset-splash-components/beds-table.tsx index fb554ac..7fe74dc 100644 --- a/ui/src/components/bedset-splash-components/beds-table.tsx +++ b/ui/src/components/bedset-splash-components/beds-table.tsx @@ -139,17 +139,17 @@ export const BedsTable = (props: Props) => { }); return ( -
+
setGlobalFilter(e.target.value)} />
-
BED set ID
+
{table.getHeaderGroups().map((headerGroup) => ( diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index 1e7a347..55bb83c 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -22,10 +22,10 @@ export const BedsetSplashHeader = (props: Props) => { return (
-
+

- + {metadata?.id || 'No name available'}

-

{metadata?.description || 'No description available'}

+

{metadata?.description || 'No description available'}

-
-
- - {metadata.md5sum} -
-
- - {metadata.bed_ids?.length} BED files +
+
+

+

+ + {metadata.md5sum} +
+

+

+

+ + {metadata.bed_ids?.length} BED files +
+

diff --git a/ui/src/components/bedset-splash-components/plots.tsx b/ui/src/components/bedset-splash-components/plots.tsx index e9b84d1..7ed822a 100644 --- a/ui/src/components/bedset-splash-components/plots.tsx +++ b/ui/src/components/bedset-splash-components/plots.tsx @@ -58,7 +58,7 @@ export const Plots = (props: PlotsProps) => { const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( - + {metadata.plots && chunkArray(plotNames, 3).map((chunk, idx) => ( diff --git a/ui/src/components/modals/figure-modal.tsx b/ui/src/components/modals/figure-modal.tsx index f010c15..c142113 100644 --- a/ui/src/components/modals/figure-modal.tsx +++ b/ui/src/components/modals/figure-modal.tsx @@ -49,7 +49,7 @@ export const FigureModal = (props: Props) => { link.click(); }} > - Download PDF + Download PDF } diff --git a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx index 47b42d5..40793cc 100644 --- a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx +++ b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx @@ -193,7 +193,7 @@ export const Bed2BedSearchResultsTable = (props: Props) => {
setGlobalFilter(e.target.value)} diff --git a/ui/src/pages/bed-cart.tsx b/ui/src/pages/bed-cart.tsx index 9880eb4..c4387dd 100644 --- a/ui/src/pages/bed-cart.tsx +++ b/ui/src/pages/bed-cart.tsx @@ -14,7 +14,7 @@ export const BedCart = () => {

Your cart is empty

Try searching for some bedfiles!

-

Overview

+

Overview

@@ -157,7 +157,7 @@ export const BedSplash = () => { -

BED Sets

+

BED Sets

@@ -192,7 +192,7 @@ export const BedSplash = () => { -

Statistics

+

Statistics

{metadata && (
@@ -206,16 +206,17 @@ export const BedSplash = () => { {/* */} + -

Plots

+

Plots

{ neighbours && -

Similar BED Files

+

Similar BED Files

diff --git a/ui/src/pages/bedset-splash.tsx b/ui/src/pages/bedset-splash.tsx index c281b1f..f40ef6a 100644 --- a/ui/src/pages/bedset-splash.tsx +++ b/ui/src/pages/bedset-splash.tsx @@ -71,10 +71,10 @@ export const BedsetSplash = () => { >

Oh no!

-

+

We could not find BEDset with record identifier:
{bedsetId} -

+

@@ -111,30 +111,28 @@ export const BedsetSplash = () => { -

Statistics

+

Statistics

{metadata && ( - <> -
- - - - - - - - + + + + + )} + + + -

Plots

+

Plots

-

BED files in this BED set

+

Constituent BED Files

{isLoadingBedfiles ? (
From 1f9eb9d9a7319b96422fe546974eba09f8c495e9 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Fri, 15 Nov 2024 00:43:07 -0500 Subject: [PATCH 10/51] description placeholder text for bed splash --- ui/src/components/bed-splash-components/header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index 2b67ee8..245befe 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -143,7 +143,7 @@ export const BedSplashHeader = (props: Props) => {
{metadata.name}
-

{metadata.description}

+

{metadata?.description || 'No description available'}

From 9e999c879d6a43899ccd9fc9084a263a95a4e937 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Fri, 15 Nov 2024 01:21:45 -0500 Subject: [PATCH 11/51] bed sets table height consistency --- .../bed-splash-components/plots.tsx | 1 - ui/src/pages/bed-splash.tsx | 109 ++++++++++++------ ui/src/pages/bedset-splash.tsx | 5 + 3 files changed, 76 insertions(+), 39 deletions(-) diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index 770b1cb..c19747f 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -57,7 +57,6 @@ const Plot = (props: PlotProps) => { export const Plots = (props: PlotsProps) => { const { metadata } = props; - console.log(props) const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( diff --git a/ui/src/pages/bed-splash.tsx b/ui/src/pages/bed-splash.tsx index ea5a8ff..3e61b51 100644 --- a/ui/src/pages/bed-splash.tsx +++ b/ui/src/pages/bed-splash.tsx @@ -13,9 +13,12 @@ import { Plots } from '../components/bed-splash-components/plots'; import { AxiosError } from 'axios'; import { GCContentCard } from '../components/bed-splash-components/cards/gc-content-card'; import { snakeToTitleCase } from '../utils'; -import { Text2BedSearchResultsTable } from '../components/search/text2bed/t2b-search-results-table.tsx'; +import { Text2BedSearchResultsTable } from '../components/search/text2bed/t2b-search-results-table'; import { useBedNeighbours } from '../queries/useBedNeighbours'; +import type { components } from '../../bedbase-types.d.ts'; +// Use the response type to properly type the metadata +type BedMetadata = components['schemas']['BedMetadataAll']; export const BedSplash = () => { const params = useParams(); @@ -39,6 +42,23 @@ export const BedSplash = () => { offset: 0, }); + // Helper function to safely type the annotation keys + const getAnnotationValue = (data: BedMetadata | undefined, key: string) => { + if (!data?.annotation) return null; + return (data.annotation as Record)[key]; + }; + + // Helper function to get filtered keys + const getFilteredKeys = (data: BedMetadata | undefined) => { + if (!data?.annotation) return []; + return Object.keys(data.annotation).filter(k => + k !== 'input_file' && + k !== 'file_name' && + k !== 'sample_name' && + getAnnotationValue(data, k) + ); + }; + if (isLoading) { return ( @@ -134,31 +154,31 @@ export const BedSplash = () => { {Object.keys(metadata?.annotation || {}).map((k) => { if (k === 'input_file' || k === 'file_name' || k === 'sample_name') { return null; - // @ts-expect-error wants to get mad because it could be an object and React cant render that (it wont be) - } else if (!metadata?.annotation[k]) { + } + + const value = getAnnotationValue(metadata, k); + if (!value) { return null; - } else { - return ( -
- - - - - ); } + + return ( + + + + + ); })}
- {snakeToTitleCase(k)} - - {/* @ts-expect-error wants to get mad because it could be an object and React cant render that (it wont be) */} - {metadata?.annotation[k] || 'N/A'} -
+ {snakeToTitleCase(k)} + + {value ?? 'N/A'} +
- +

BED Sets

-
+
@@ -169,22 +189,37 @@ export const BedSplash = () => { - {metadata?.bedsets?.map((bedset) => ( - - - - - - - )) || 'N/A'} + {[ + ...(metadata?.bedsets || []).map((bedset) => ( + + + + + + + )), + ...Array( + Math.max( + 0, + getFilteredKeys(metadata).length - (metadata?.bedsets?.length || 0) + ) + ).fill(null).map((_, index) => ( + + + + + + + )) + ]}
- {bedset.id} - - {bedset.name || 'No name'} - - {bedset.description || 'No description'} - - View -
+ {bedset.id} + + {bedset.name || 'No name'} + + {bedset.description || 'No description'} + + View +
    
@@ -203,10 +238,9 @@ export const BedSplash = () => { )} - {/* */} - +

Plots

@@ -222,9 +256,8 @@ export const BedSplash = () => {
} -
); } -}; +}; \ No newline at end of file diff --git a/ui/src/pages/bedset-splash.tsx b/ui/src/pages/bedset-splash.tsx index f40ef6a..53cd7e8 100644 --- a/ui/src/pages/bedset-splash.tsx +++ b/ui/src/pages/bedset-splash.tsx @@ -26,6 +26,11 @@ export const BedsetSplash = () => { autoRun: true, }); + console.log(useBedsetMetadata({ + md5: bedsetId, + autoRun: true, + })); + const { isFetching: isLoadingBedfiles, data: bedfiles } = useBedsetBedfiles({ id: bedsetId, autoRun: true, From 44f1592ab1b76c81e4adfde432f46c321d40cee2 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Fri, 15 Nov 2024 01:29:28 -0500 Subject: [PATCH 12/51] bedsets typo --- ui/src/pages/bed-splash.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/pages/bed-splash.tsx b/ui/src/pages/bed-splash.tsx index 3e61b51..6d99ee0 100644 --- a/ui/src/pages/bed-splash.tsx +++ b/ui/src/pages/bed-splash.tsx @@ -177,12 +177,12 @@ export const BedSplash = () => {
-

BED Sets

+

BEDsets

- + From 0fc1b37a298d3f11e2217fbe34012d84a3f8df31 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Fri, 15 Nov 2024 10:26:30 -0500 Subject: [PATCH 13/51] address comments --- .../cards/mean-region-width-card.tsx | 2 +- .../cards/no-regions-card.tsx | 2 +- .../cards/median-region-width.tsx | 2 +- .../components/bedset-splash-components/header.tsx | 14 ++++++++------ ui/src/pages/bedset-splash.tsx | 5 ----- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/ui/src/components/bed-splash-components/cards/mean-region-width-card.tsx b/ui/src/components/bed-splash-components/cards/mean-region-width-card.tsx index 3a4f2b3..f094631 100644 --- a/ui/src/components/bed-splash-components/cards/mean-region-width-card.tsx +++ b/ui/src/components/bed-splash-components/cards/mean-region-width-card.tsx @@ -12,7 +12,7 @@ export const MeanRegionWidthCard = (props: Props) => { return ( diff --git a/ui/src/components/bed-splash-components/cards/no-regions-card.tsx b/ui/src/components/bed-splash-components/cards/no-regions-card.tsx index 998e130..b38836c 100644 --- a/ui/src/components/bed-splash-components/cards/no-regions-card.tsx +++ b/ui/src/components/bed-splash-components/cards/no-regions-card.tsx @@ -11,7 +11,7 @@ export const NoRegionsCard = (props: Props) => { const { metadata } = props; return ( diff --git a/ui/src/components/bedset-splash-components/cards/median-region-width.tsx b/ui/src/components/bedset-splash-components/cards/median-region-width.tsx index ca2a9ea..b198fec 100644 --- a/ui/src/components/bedset-splash-components/cards/median-region-width.tsx +++ b/ui/src/components/bedset-splash-components/cards/median-region-width.tsx @@ -11,7 +11,7 @@ export const MeanRegionWidthCard = (props: Props) => { const { metadata } = props; return ( - +

{formatNumberWithCommas(Math.round(metadata.statistics?.mean?.mean_region_width || 0))} bp diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index 55bb83c..6ef7e53 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -114,12 +114,14 @@ export const BedsetSplashHeader = (props: Props) => { {metadata.md5sum}

-

-

- - {metadata.bed_ids?.length} BED files -
-

+ { metadata.bed_ids && +

+

+ + {metadata.bed_ids?.length} BED files +
+

+ } diff --git a/ui/src/pages/bedset-splash.tsx b/ui/src/pages/bedset-splash.tsx index 53cd7e8..f40ef6a 100644 --- a/ui/src/pages/bedset-splash.tsx +++ b/ui/src/pages/bedset-splash.tsx @@ -26,11 +26,6 @@ export const BedsetSplash = () => { autoRun: true, }); - console.log(useBedsetMetadata({ - md5: bedsetId, - autoRun: true, - })); - const { isFetching: isLoadingBedfiles, data: bedfiles } = useBedsetBedfiles({ id: bedsetId, autoRun: true, From 7b8c0d175abba4306e84e12caf49982ac5018a1d Mon Sep 17 00:00:00 2001 From: Nathan LeRoy Date: Fri, 15 Nov 2024 10:33:25 -0500 Subject: [PATCH 14/51] prettier --- .../bed-splash-components/header.tsx | 5 +- .../bed-splash-components/plots.tsx | 2 +- .../bedset-splash-components/beds-table.tsx | 14 ++++-- .../bedset-splash-components/header.tsx | 29 +++++------ ui/src/components/modals/figure-modal.tsx | 26 +++++----- .../bed2bed/b2b-search-results-table.tsx | 10 ++-- .../components/search/search-bedset-table.tsx | 8 +-- .../text2bed/t2b-search-results-table.tsx | 6 +-- ui/src/components/search/text2bedset.tsx | 2 +- ui/src/custom.scss | 5 +- ui/src/pages/bed-splash.tsx | 50 ++++++++----------- ui/src/pages/bedset-splash.tsx | 13 ++--- ui/src/queries/useBedNeighbours.ts | 2 +- ui/src/queries/useBedSetBedfiles.ts | 2 +- ui/src/queries/useBedsetMetadata.ts | 2 +- 15 files changed, 82 insertions(+), 94 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index 245befe..d621e6b 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -45,7 +45,6 @@ export const BedSplashHeader = (props: Props) => { {copiedId ? : } -
-
{metadata.name}
-

{metadata?.description || 'No description available'}

+
{metadata.name}
+

{metadata?.description || 'No description available'}

diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index c19747f..b84e6c7 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { Col, Image, Row } from 'react-bootstrap'; import { components } from '../../../bedbase-types'; -import { chunkArray, makeThumbnailImageLink , makePDFImageLink } from '../../utils'; +import { chunkArray, makeThumbnailImageLink, makePDFImageLink } from '../../utils'; import { Fragment } from 'react'; import { FigureModal } from '../modals/figure-modal'; diff --git a/ui/src/components/bedset-splash-components/beds-table.tsx b/ui/src/components/bedset-splash-components/beds-table.tsx index 7fe74dc..0163d32 100644 --- a/ui/src/components/bedset-splash-components/beds-table.tsx +++ b/ui/src/components/bedset-splash-components/beds-table.tsx @@ -148,13 +148,19 @@ export const BedsTable = (props: Props) => { onChange={(e) => setGlobalFilter(e.target.value)} />
-
+
BED set IDBEDset ID Name Description View
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( - {table.getRowModel().rows.map((row) => ( - + {row.getVisibleCells().map((cell) => ( ))} diff --git a/ui/src/components/search/search-bedset-table.tsx b/ui/src/components/search/search-bedset-table.tsx index 3e2c9d0..01f68eb 100644 --- a/ui/src/components/search/search-bedset-table.tsx +++ b/ui/src/components/search/search-bedset-table.tsx @@ -30,18 +30,14 @@ export const SearchBedSetResultTable = (props: Props) => { {results.results?.map((result) => ( - + {results.results?.map((result) => ( - diff --git a/ui/src/components/search/text2bedset.tsx b/ui/src/components/search/text2bedset.tsx index a119108..f71607d 100644 --- a/ui/src/components/search/text2bedset.tsx +++ b/ui/src/components/search/text2bedset.tsx @@ -61,7 +61,7 @@ export const Text2BedSet = () => {
{results ? (
-
+
{' '} diff --git a/ui/src/custom.scss b/ui/src/custom.scss index 9213e47..a2ca052 100644 --- a/ui/src/custom.scss +++ b/ui/src/custom.scss @@ -300,7 +300,8 @@ a { font-size: 0.9rem; /* Adjust the value as needed */ } -th, td { +th, +td { padding-left: 1rem !important; padding-right: 1rem !important; -} \ No newline at end of file +} diff --git a/ui/src/pages/bed-splash.tsx b/ui/src/pages/bed-splash.tsx index 6d99ee0..228e8e1 100644 --- a/ui/src/pages/bed-splash.tsx +++ b/ui/src/pages/bed-splash.tsx @@ -34,9 +34,7 @@ export const BedSplash = () => { full: true, }); - const { - data: neighbours, - } = useBedNeighbours({ + const { data: neighbours } = useBedNeighbours({ md5: bedId, limit: 10, offset: 0, @@ -51,11 +49,8 @@ export const BedSplash = () => { // Helper function to get filtered keys const getFilteredKeys = (data: BedMetadata | undefined) => { if (!data?.annotation) return []; - return Object.keys(data.annotation).filter(k => - k !== 'input_file' && - k !== 'file_name' && - k !== 'sample_name' && - getAnnotationValue(data, k) + return Object.keys(data.annotation).filter( + (k) => k !== 'input_file' && k !== 'file_name' && k !== 'sample_name' && getAnnotationValue(data, k), ); }; @@ -154,8 +149,8 @@ export const BedSplash = () => { {Object.keys(metadata?.annotation || {}).map((k) => { if (k === 'input_file' || k === 'file_name' || k === 'sample_name') { return null; - } - + } + const value = getAnnotationValue(metadata, k); if (!value) { return null; @@ -176,7 +171,7 @@ export const BedSplash = () => {
+ {header.isPlaceholder ? null : (
{ > {flexRender(header.column.columnDef.header, header.getContext())} {{ - asc: , - desc: , + asc: , + desc: , }[header.column.getIsSorted() as string] ?? null}
)} diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index 6ef7e53..14b43ff 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import { components } from '../../../bedbase-types'; import { useBedCart } from '../../contexts/bedcart-context'; import { DownloadBedSetModal } from '../modals/download-bedset-modal'; -import {useCopyToClipboard} from "@uidotdev/usehooks"; +import { useCopyToClipboard } from '@uidotdev/usehooks'; type BedSetMetadata = components['schemas']['BedSetMetadata']; type Props = { @@ -42,11 +42,12 @@ export const BedsetSplashHeader = (props: Props) => {
-

{metadata?.description || 'No description available'}

+

{metadata?.description || 'No description available'}

-

+

{metadata.md5sum}

- { metadata.bed_ids && -

+ {metadata.bed_ids && ( +

{metadata.bed_ids?.length} BED files

- } + )}
diff --git a/ui/src/components/modals/figure-modal.tsx b/ui/src/components/modals/figure-modal.tsx index c142113..05d6a6f 100644 --- a/ui/src/components/modals/figure-modal.tsx +++ b/ui/src/components/modals/figure-modal.tsx @@ -39,20 +39,20 @@ export const FigureModal = (props: Props) => { > Download PNG - {pdf && + {pdf && ( - } - + className="btn btn-outline-primary" + onClick={() => { + const link = document.createElement('a'); + link.href = pdf; + link.download = alt; + link.click(); + }} + > + Download PDF + + )} + diff --git a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx index 40793cc..30dd595 100644 --- a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx +++ b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx @@ -221,8 +221,8 @@ export const Bed2BedSearchResultsTable = (props: Props) => { > {flexRender(header.column.columnDef.header, header.getContext())} {{ - asc: , - desc: , + asc: , + desc: , }[header.column.getIsSorted() as string] ?? null} )} @@ -233,11 +233,7 @@ export const Bed2BedSearchResultsTable = (props: Props) => {
{flexRender(cell.column.columnDef.cell, cell.getContext())}
{result?.id || 'Unknown Id'} {result?.name || 'Unknown Name'} {result?.description || 'Unknown Description'} {result?.bed_ids?.length || 0} - diff --git a/ui/src/components/search/text2bed/t2b-search-results-table.tsx b/ui/src/components/search/text2bed/t2b-search-results-table.tsx index 971ee3b..b25cad7 100644 --- a/ui/src/components/search/text2bed/t2b-search-results-table.tsx +++ b/ui/src/components/search/text2bed/t2b-search-results-table.tsx @@ -16,7 +16,7 @@ type Props = { export const Text2BedSearchResultsTable = (props: Props) => { const { results } = props; const { cart, addBedToCart, removeBedFromCart } = useBedCart(); - + const handleRowClick = (id?: string) => (e: React.MouseEvent) => { if (!(e.target as HTMLElement).closest('button')) { window.location.href = `/bed/${id}`; @@ -43,8 +43,8 @@ export const Text2BedSearchResultsTable = (props: Props) => {
- +

BEDsets

@@ -206,26 +201,23 @@ export const BedSplash = () => { )), - ...Array( - Math.max( - 0, - getFilteredKeys(metadata).length - (metadata?.bedsets?.length || 0) - ) - ).fill(null).map((_, index) => ( - - - - - - - )) + ...Array(Math.max(0, getFilteredKeys(metadata).length - (metadata?.bedsets?.length || 0))) + .fill(null) + .map((_, index) => ( + + + + + + + )), ]}
    
    
- +

Statistics

{metadata && ( @@ -248,16 +240,16 @@ export const BedSplash = () => {
- { neighbours && + {neighbours && (

Similar BED Files

- +
- } + )}
); } -}; \ No newline at end of file +}; diff --git a/ui/src/pages/bedset-splash.tsx b/ui/src/pages/bedset-splash.tsx index f40ef6a..dbdc3ff 100644 --- a/ui/src/pages/bedset-splash.tsx +++ b/ui/src/pages/bedset-splash.tsx @@ -105,11 +105,9 @@ export const BedsetSplash = () => {
- - {metadata !== undefined ? : null} - + {metadata !== undefined ? : null} - +

Statistics

{metadata && ( @@ -123,17 +121,17 @@ export const BedsetSplash = () => {
- +

Plots

- +

Constituent BED Files

- + {isLoadingBedfiles ? (
@@ -148,7 +146,6 @@ export const BedsetSplash = () => { )} -
); diff --git a/ui/src/queries/useBedNeighbours.ts b/ui/src/queries/useBedNeighbours.ts index 885ec32..8d44922 100644 --- a/ui/src/queries/useBedNeighbours.ts +++ b/ui/src/queries/useBedNeighbours.ts @@ -19,6 +19,6 @@ export const useBedNeighbours = (query: BedNeighboursQuery) => { queryFn: async () => { const { data } = await api.get(`/bed/${md5}/neighbours?limit=${limit}`); return data; - } + }, }); }; diff --git a/ui/src/queries/useBedSetBedfiles.ts b/ui/src/queries/useBedSetBedfiles.ts index b700377..220edbd 100644 --- a/ui/src/queries/useBedSetBedfiles.ts +++ b/ui/src/queries/useBedSetBedfiles.ts @@ -25,4 +25,4 @@ export const useBedsetBedfiles = (query: BedSetBedfilesQuery) => { refetchOnWindowFocus: false, refetchOnMount: false, }); -}; \ No newline at end of file +}; diff --git a/ui/src/queries/useBedsetMetadata.ts b/ui/src/queries/useBedsetMetadata.ts index 303448c..f866de3 100644 --- a/ui/src/queries/useBedsetMetadata.ts +++ b/ui/src/queries/useBedsetMetadata.ts @@ -25,4 +25,4 @@ export const useBedsetMetadata = (query: BedSetMetadataQuery) => { refetchOnWindowFocus: false, refetchOnMount: false, }); -}; \ No newline at end of file +}; From 1c3c39518ffd9f877c990eb31c2a8b25bcaaad4f Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Sat, 16 Nov 2024 21:44:50 -0500 Subject: [PATCH 15/51] ui - work on mobile version --- .../bed-splash-components/header.tsx | 10 +++++----- .../components/bed-splash-components/plots.tsx | 2 +- .../text2bed/t2b-search-results-table.tsx | 18 ++++++++++-------- ui/src/pages/bed-splash.tsx | 14 ++++++++------ 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index d621e6b..8ca1fe8 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -144,10 +144,9 @@ export const BedSplashHeader = (props: Props) => {
{metadata.name}

{metadata?.description || 'No description available'}

- -
-
-
+
+
+

{

- +

Updated:{' '} {metadata?.last_update_date ? formatDateTime(metadata?.last_update_date) : 'No date available'} @@ -272,6 +271,7 @@ export const BedSplashHeader = (props: Props) => {

+
); }; diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index b84e6c7..daf462c 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -61,7 +61,7 @@ export const Plots = (props: PlotsProps) => { const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( - + {metadata.plots && chunkArray(plotNames, 3).map((chunk, idx) => ( diff --git a/ui/src/components/search/text2bed/t2b-search-results-table.tsx b/ui/src/components/search/text2bed/t2b-search-results-table.tsx index b25cad7..c1eb9e0 100644 --- a/ui/src/components/search/text2bed/t2b-search-results-table.tsx +++ b/ui/src/components/search/text2bed/t2b-search-results-table.tsx @@ -24,8 +24,9 @@ export const Text2BedSearchResultsTable = (props: Props) => { }; return ( - - +
+
+ @@ -40,8 +41,8 @@ export const Text2BedSearchResultsTable = (props: Props) => { Actions - - + + {results.results?.map((result) => ( { ))} - -
Name Genome
- ); -}; + + +
+ ); + }; diff --git a/ui/src/pages/bed-splash.tsx b/ui/src/pages/bed-splash.tsx index 228e8e1..e20ebb1 100644 --- a/ui/src/pages/bed-splash.tsx +++ b/ui/src/pages/bed-splash.tsx @@ -174,16 +174,17 @@ export const BedSplash = () => {

BEDsets

- - +
+
+ - - + + {[ ...(metadata?.bedsets || []).map((bedset) => ( @@ -212,8 +213,9 @@ export const BedSplash = () => { )), ]} - -
BEDset ID Name Description View
+ + +
From 07f7f1942ef88a4aab84b72c0b0d42e8302ccc91 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Sat, 16 Nov 2024 21:53:30 -0500 Subject: [PATCH 16/51] ui - work on mobile version 2 --- ui/src/components/bed-splash-components/plots.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index daf462c..fbeb0ff 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -61,10 +61,10 @@ export const Plots = (props: PlotsProps) => { const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( - +
{metadata.plots && chunkArray(plotNames, 3).map((chunk, idx) => ( - + {chunk.map((plotName) => { // this is for type checking const plotNameKey = plotName as keyof typeof metadata.plots; @@ -73,10 +73,10 @@ export const Plots = (props: PlotsProps) => { const title = plotExists ? metadata.plots[plotNameKey]?.title : plotName; const alt = plotExists ? // @ts-expect-error: type checking here is just too much - metadata.plots[plotNameKey]?.description || metadata.plots[plotNameKey].title + metadata.plots[plotNameKey]?.description || metadata.plots[plotNameKey].title : plotName; return ( - + { ); })} - + ))} - +
); }; From fafaf569b40a040e5185a4f934a9168a87e1e135 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 18 Nov 2024 01:46:16 -0500 Subject: [PATCH 17/51] mobile improvement --- .../bed-splash-components/header.tsx | 23 +++--- .../bed-splash-components/plots.tsx | 8 +-- .../bedset-splash-components/header.tsx | 12 ++-- .../bedset-splash-components/plots.tsx | 2 +- ui/src/components/nav/nav-mobile.tsx | 2 +- ui/src/pages/bed-splash.tsx | 72 ++++++++++--------- ui/src/pages/bedset-splash.tsx | 4 +- 7 files changed, 62 insertions(+), 61 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index 8ca1fe8..6906fbc 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -27,13 +27,13 @@ export const BedSplashHeader = (props: Props) => { return (
-
-
-

- - {metadata?.id || 'No id available'} +
+
+

+ + {metadata?.id || 'No ID available'}

-
+ -
-
-
+
+
+

{

)}
-
+

@@ -271,7 +271,6 @@ export const BedSplashHeader = (props: Props) => {

-
); }; diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index fbeb0ff..6b2c720 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -61,10 +61,10 @@ export const Plots = (props: PlotsProps) => { const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( -
+ {metadata.plots && chunkArray(plotNames, 3).map((chunk, idx) => ( - + {chunk.map((plotName) => { // this is for type checking const plotNameKey = plotName as keyof typeof metadata.plots; @@ -87,9 +87,9 @@ export const Plots = (props: PlotsProps) => { ); })} - + ))} -
+
); }; diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index 14b43ff..ed8d15d 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -22,9 +22,9 @@ export const BedsetSplashHeader = (props: Props) => { return (
-
-
-

+
+
+

{metadata?.id || 'No name available'}

-
+
{/* TODO: change hg38 on correct genome */} {/**/} {

{metadata?.description || 'No description available'}

-
-
+
+

diff --git a/ui/src/components/bedset-splash-components/plots.tsx b/ui/src/components/bedset-splash-components/plots.tsx index 7ed822a..4e2cdce 100644 --- a/ui/src/components/bedset-splash-components/plots.tsx +++ b/ui/src/components/bedset-splash-components/plots.tsx @@ -58,7 +58,7 @@ export const Plots = (props: PlotsProps) => { const plotNames = metadata.plots ? Object.keys(metadata.plots) : []; return ( - + {metadata.plots && chunkArray(plotNames, 3).map((chunk, idx) => ( diff --git a/ui/src/components/nav/nav-mobile.tsx b/ui/src/components/nav/nav-mobile.tsx index bc1fa4d..0969cb7 100644 --- a/ui/src/components/nav/nav-mobile.tsx +++ b/ui/src/components/nav/nav-mobile.tsx @@ -6,7 +6,7 @@ export const MobileNav = () => { - + GitHub diff --git a/ui/src/pages/bed-splash.tsx b/ui/src/pages/bed-splash.tsx index e20ebb1..db18767 100644 --- a/ui/src/pages/bed-splash.tsx +++ b/ui/src/pages/bed-splash.tsx @@ -138,40 +138,42 @@ export const BedSplash = () => {

Overview

- - - - - - - - - {Object.keys(metadata?.annotation || {}).map((k) => { - if (k === 'input_file' || k === 'file_name' || k === 'sample_name') { - return null; - } +
+
KeyValue
+ + + + + + + + {Object.keys(metadata?.annotation || {}).map((k) => { + if (k === 'input_file' || k === 'file_name' || k === 'sample_name') { + return null; + } - const value = getAnnotationValue(metadata, k); - if (!value) { - return null; - } + const value = getAnnotationValue(metadata, k); + if (!value) { + return null; + } - return ( - - - - - ); - })} - -
KeyValue
- {snakeToTitleCase(k)} - - {value ?? 'N/A'} -
+ return ( + + + {snakeToTitleCase(k)} + + + {value ?? 'N/A'} + + + ); + })} + + +
- +

BEDsets

@@ -223,28 +225,28 @@ export const BedSplash = () => {

Statistics

{metadata && ( - + )} - +
+

Plots

-

Plots

{neighbours && ( - -

Similar BED Files

+ +

Similar BED Files

diff --git a/ui/src/pages/bedset-splash.tsx b/ui/src/pages/bedset-splash.tsx index dbdc3ff..8cdf0fc 100644 --- a/ui/src/pages/bedset-splash.tsx +++ b/ui/src/pages/bedset-splash.tsx @@ -111,13 +111,13 @@ export const BedsetSplash = () => {

Statistics

{metadata && ( - + )} - +
From d6a1f1881f5e991ec28e4d7685d69ff47e140a51 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 18 Nov 2024 01:58:11 -0500 Subject: [PATCH 18/51] type error --- ui/src/components/bed-splash-components/plots.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/bed-splash-components/plots.tsx b/ui/src/components/bed-splash-components/plots.tsx index 6b2c720..d04546e 100644 --- a/ui/src/components/bed-splash-components/plots.tsx +++ b/ui/src/components/bed-splash-components/plots.tsx @@ -64,7 +64,7 @@ export const Plots = (props: PlotsProps) => { {metadata.plots && chunkArray(plotNames, 3).map((chunk, idx) => ( - + {chunk.map((plotName) => { // this is for type checking const plotNameKey = plotName as keyof typeof metadata.plots; From ce3f370a081f7c23d63e2aba54eb6276aeee1869 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 18 Nov 2024 02:21:30 -0500 Subject: [PATCH 19/51] header details --- ui/src/components/bed-splash-components/header.tsx | 6 +++--- ui/src/components/bedset-splash-components/header.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index 6906fbc..d550cc3 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -33,7 +33,7 @@ export const BedSplashHeader = (props: Props) => { {metadata?.id || 'No ID available'}
)}
-
+

@@ -263,7 +263,7 @@ export const BedSplashHeader = (props: Props) => {

- +

Updated:{' '} {metadata?.last_update_date ? formatDateTime(metadata?.last_update_date) : 'No date available'} diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index ed8d15d..00be13b 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -28,7 +28,7 @@ export const BedsetSplashHeader = (props: Props) => { {metadata?.id || 'No name available'}

-

-
+
{/* TODO: change hg38 on correct genome */} {/**/} Date: Mon, 18 Nov 2024 15:15:17 -0500 Subject: [PATCH 21/51] fixed scroll bar --- ui/src/components/bed-splash-components/header.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index a1e6aa8..9ffa742 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -27,8 +27,8 @@ export const BedSplashHeader = (props: Props) => { return (
-
-
+
+

{metadata?.id || 'No ID available'} @@ -144,7 +144,8 @@ export const BedSplashHeader = (props: Props) => {
{metadata.name}

{metadata?.description || 'No description available'}

-
+

From 8267496d6c6934133fa0198cb8d2e734a75a7ae4 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 18 Nov 2024 15:32:47 -0500 Subject: [PATCH 22/51] rolled back combined text search --- bedhost/routers/bed_api.py | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/bedhost/routers/bed_api.py b/bedhost/routers/bed_api.py index 3a7bc1d..9292554 100644 --- a/bedhost/routers/bed_api.py +++ b/bedhost/routers/bed_api.py @@ -357,24 +357,30 @@ async def text_to_bed_search(query, limit: int = 10, offset: int = 0): """ _LOGGER.info(f"Searching for: {query}") - results_sql = bbagent.bed.sql_search( - query, limit=round(limit / 2, 0), offset=round(offset / 2, 0) - ) - - if results_sql.count > results_sql.offset: - qdrant_offset = offset - results_sql.offset - else: - qdrant_offset = offset - results_sql.count - - results_qdr = bbagent.bed.text_to_bed_search( - query, limit=limit, offset=qdrant_offset - 1 if qdrant_offset > 0 else 0 - ) - - results = BedListSearchResult( - count=results_qdr.count, + # results_sql = bbagent.bed.sql_search( + # query, limit=round(limit / 2, 0), offset=round(offset / 2, 0) + # ) + # + # if results_sql.count > results_sql.offset: + # qdrant_offset = offset - results_sql.offset + # else: + # qdrant_offset = offset - results_sql.count + # + # results_qdr = bbagent.bed.text_to_bed_search( + # query, limit=limit, offset=qdrant_offset - 1 if qdrant_offset > 0 else 0 + # ) + # + # results = BedListSearchResult( + # count=results_qdr.count, + # limit=limit, + # offset=offset, + # results=(results_sql.results + results_qdr.results)[0:limit], + # ) + + results = bbagent.bed.text_to_bed_search( + query, limit=limit, offset=offset, - results=(results_sql.results + results_qdr.results)[0:limit], ) if results: From 94ff8dae7b0b925b1b5ed67297ee44b018da6557 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 18 Nov 2024 15:42:43 -0500 Subject: [PATCH 23/51] mobile and safari ui improvements --- .../bed-splash-components/header.tsx | 8 ++--- .../bedset-splash-components/header.tsx | 33 +++++++++++-------- ui/src/components/nav/nav-mobile.tsx | 2 +- ui/src/motions/landing-animations.tsx | 8 +++-- ui/src/pages/home.tsx | 16 ++++----- 5 files changed, 39 insertions(+), 28 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index a1e6aa8..b974414 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -28,7 +28,7 @@ export const BedSplashHeader = (props: Props) => { return (

-
+

{metadata?.id || 'No ID available'} @@ -99,11 +99,11 @@ export const BedSplashHeader = (props: Props) => { { // If there are no files to download, disable the dropdown noFilesToDownload ? ( - + There are no files to download ) : ( - + {metadata.files?.bed_file && ( {(metadata.files?.bed_file?.access_methods || []).map((method) => { @@ -144,7 +144,7 @@ export const BedSplashHeader = (props: Props) => {
{metadata.name}

{metadata?.description || 'No description available'}

-
+

diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index aec2286..42782c3 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -1,9 +1,11 @@ import { useState } from 'react'; +import { Dropdown } from 'react-bootstrap'; import { components } from '../../../bedbase-types'; import { useBedCart } from '../../contexts/bedcart-context'; import { DownloadBedSetModal } from '../modals/download-bedset-modal'; import { useCopyToClipboard } from '@uidotdev/usehooks'; + type BedSetMetadata = components['schemas']['BedSetMetadata']; type Props = { metadata: BedSetMetadata; @@ -22,7 +24,7 @@ export const BedsetSplashHeader = (props: Props) => { return (

-
+

@@ -41,7 +43,7 @@ export const BedsetSplashHeader = (props: Props) => {

-
diff --git a/ui/src/components/nav/nav-mobile.tsx b/ui/src/components/nav/nav-mobile.tsx index 0969cb7..4248f17 100644 --- a/ui/src/components/nav/nav-mobile.tsx +++ b/ui/src/components/nav/nav-mobile.tsx @@ -6,7 +6,7 @@ export const MobileNav = () => { - + GitHub diff --git a/ui/src/motions/landing-animations.tsx b/ui/src/motions/landing-animations.tsx index e172871..b714e2f 100644 --- a/ui/src/motions/landing-animations.tsx +++ b/ui/src/motions/landing-animations.tsx @@ -7,7 +7,9 @@ const STROKE_SPEAD = 0; export const InPaths = () => { return ( { export const OutPaths = () => { return ( { {/*
*/}

Welcome to BEDbase

-
-

+

+

BEDbase is a unified platform for aggregating, analyzing, and serving genomic region data. BEDbase redefines the way to manage genomic region data and allows users to search for BED files of interest and create collections tailored to research needs. BEDbase is composed of a web server and an API. Users can explore @@ -60,7 +60,7 @@ export const Home = () => { interact with the data via an OpenAPI-compatible API.

-
+
{
-
- Or, explore an example BED file or a{' '} - example BED set +
@@ -269,7 +269,7 @@ export const Home = () => { {/*
*/} - +

BEDbase client

@@ -338,7 +338,7 @@ export const Home = () => {

Data Availability Summary

-
+
  • Number of bed files available: From 9bfee65b072570126c3c6a4f19b8ca3cd598a972 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 18 Nov 2024 15:51:20 -0500 Subject: [PATCH 24/51] home page detail --- ui/src/motions/landing-animations.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/motions/landing-animations.tsx b/ui/src/motions/landing-animations.tsx index b714e2f..763977a 100644 --- a/ui/src/motions/landing-animations.tsx +++ b/ui/src/motions/landing-animations.tsx @@ -8,7 +8,7 @@ export const InPaths = () => { return ( { return ( Date: Mon, 18 Nov 2024 15:52:10 -0500 Subject: [PATCH 25/51] home page typo --- ui/src/pages/home.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/pages/home.tsx b/ui/src/pages/home.tsx index 323af42..e3bb332 100644 --- a/ui/src/pages/home.tsx +++ b/ui/src/pages/home.tsx @@ -93,7 +93,7 @@ export const Home = () => {
From ea595409519c1f24a6f611bf4068f238440c4c81 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 18 Nov 2024 15:57:00 -0500 Subject: [PATCH 26/51] fix safari homepage again --- ui/src/motions/landing-animations.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/motions/landing-animations.tsx b/ui/src/motions/landing-animations.tsx index 763977a..b714e2f 100644 --- a/ui/src/motions/landing-animations.tsx +++ b/ui/src/motions/landing-animations.tsx @@ -8,7 +8,7 @@ export const InPaths = () => { return ( { return ( Date: Thu, 21 Nov 2024 18:03:42 -0500 Subject: [PATCH 27/51] Added endpoint and ui modal that creates bedsets --- bedhost/data_models.py | 4 + bedhost/routers/bedset_api.py | 53 +++++++++++ .../components/modals/create-bedset-modal.tsx | 90 +++++++++++++++++++ ui/src/pages/bed-cart.tsx | 15 +++- ui/src/utils.ts | 15 ++++ 5 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 ui/src/components/modals/create-bedset-modal.tsx diff --git a/bedhost/data_models.py b/bedhost/data_models.py index cb524eb..b81ed2b 100644 --- a/bedhost/data_models.py +++ b/bedhost/data_models.py @@ -77,3 +77,7 @@ class BaseListResponse(BaseModel): limit: int offset: int results: list + + +class CreateBEDsetRequest(BaseModel): + registry_path: str diff --git a/bedhost/routers/bedset_api.py b/bedhost/routers/bedset_api.py index d33566c..ef6ccfa 100644 --- a/bedhost/routers/bedset_api.py +++ b/bedhost/routers/bedset_api.py @@ -8,10 +8,12 @@ BedSetPlots, BedSetStats, ) +from pephubclient.helpers import is_registry_path, unwrap_registry_path from fastapi import APIRouter, HTTPException, Request, Response from ..const import EXAMPLE_BEDSET, PKG_NAME from ..main import bbagent +from ..data_models import CreateBEDsetRequest from ..utils import zip_pep router = APIRouter(prefix="/v1/bedset", tags=["bedset"]) @@ -183,3 +185,54 @@ async def get_trackDb_file_bedset(bedset_id: str): ) return Response(trackDb_txt, media_type="text/plain") + + +@router.post( + "/create/", + description="Create a new bedset by providing registry path to the PEPhub project", +) +async def create_bedset(bedset: CreateBEDsetRequest): + """ + Create a new bedset + """ + # Validate the PEPhub project string + if not is_registry_path(bedset.registry_path): + raise HTTPException(status_code=406, detail="Invalid registry path") + + project_reg_path = unwrap_registry_path(bedset.registry_path) + + if project_reg_path.namespace not in ["databio", "bedbase", "pepkit"]: + raise HTTPException(status_code=403, detail="User is not in admin list") + + try: + project = bbagent.config.phc.load_project(bedset.registry_path) + except Exception as err: + raise HTTPException( + status_code=406, detail=f"Unable to retrieve project: {err}" + ) + + bedfiles_list = [ + bedfile_id.get("record_identifier") or bedfile_id.sample_name + for bedfile_id in project.samples + ] + + try: + bbagent.bedset.create( + identifier=project.name, + name=project.name, + bedid_list=bedfiles_list, + statistics=True, + description=project.description, + annotation={ + "source": project.config.get("source", ""), + "author": project.config.get("author", project_reg_path.namespace), + }, + no_fail=False, + overwrite=False, + ) + except Exception as err: + raise HTTPException( + status_code=406, detail=f"Unable to create bedset. Error: {err}" + ) + + return {"status": "success"} diff --git a/ui/src/components/modals/create-bedset-modal.tsx b/ui/src/components/modals/create-bedset-modal.tsx new file mode 100644 index 0000000..2568858 --- /dev/null +++ b/ui/src/components/modals/create-bedset-modal.tsx @@ -0,0 +1,90 @@ +import { useCopyToClipboard } from '@uidotdev/usehooks'; +import { useState } from 'react'; +import { Modal } from 'react-bootstrap'; +import Markdown from 'react-markdown'; +import { generateBEDsetPEPMd, generateBEDsetPEPDownloadRaw } from '../../utils'; +import { useBedCart } from '../../contexts/bedcart-context'; +import rehypeHighlight from 'rehype-highlight'; + +type Props = { + show: boolean; + setShow: (show: boolean) => void; +}; + +const API_BASE = import.meta.env.VITE_API_BASE || ''; + +export const generateBEDsetCreationDescription = () => { + const text = ` + To create new BEDset follow these steps: + + 1. Create PEP in [PEPhub](https://pephub.databio.org/), by copying the text below, and pasting it into the sample table. + The name of the PEP project will be used as the name and identifier for the BEDset. + 2. Add source, author, and other metadata to config file. e.g. + \`\`\`json + 'author': "BEDbase team", + 'source': "BEDbase", + \`\`\` + 3. Go to the BEDbase API ([${API_BASE}](${API_BASE}/docs#/bedset/create_bedset_v1_bedset_create__post)) and + create a new BEDset by providing the registry path in the Body of the request. (Registry path can be copied from the PEPhub): + \`\`\`json + { + "registry_path": "namespace/name:tag" + } + \`\`\` + + + + \** At this point we support only PEPs from bedbase organization. + `; + return text; +}; + +export const CreateBedSetModal = (props: Props) => { + const { show, setShow } = props; + const { cart } = useBedCart(); + const [, copyToClipboard] = useCopyToClipboard(); + const [copied, setCopied] = useState(false); + return ( + setShow(false)} + size="xl" + aria-labelledby="contained-modal-title-vcenter" + centered + > + + +
+ Create BEDset + + {generateBEDsetCreationDescription()} + +
+
+ +
+ {generateBEDsetPEPMd(cart)} +
+
+ +
+
+
+ ); +}; diff --git a/ui/src/pages/bed-cart.tsx b/ui/src/pages/bed-cart.tsx index c4387dd..9230f8e 100644 --- a/ui/src/pages/bed-cart.tsx +++ b/ui/src/pages/bed-cart.tsx @@ -1,10 +1,12 @@ import { useBedCart } from '../contexts/bedcart-context'; import { Layout } from '../components/layout'; import { DownloadCartModal } from '../components/modals/download-cart-modal'; +import { CreateBedSetModal } from '../components/modals/create-bedset-modal'; import { useState } from 'react'; export const BedCart = () => { const [showDownloadModal, setShowDownloadModal] = useState(false); + const [showCreateBedsetModal, setCreateBedSetModal] = useState(false); const { cart, removeBedFromCart } = useBedCart(); if (cart.length === 0) { @@ -45,10 +47,14 @@ export const BedCart = () => { )}
- +
-
- +
+
@@ -71,17 +77,15 @@ export const BedCart = () => { {cart.map((item) => ( - + ))} From fe964e6cc57a81ec87e4a6296a8e623f5dbe629d Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 25 Nov 2024 15:40:57 -0500 Subject: [PATCH 32/51] bedset modal detail fix --- ui/src/components/modals/create-bedset-modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/modals/create-bedset-modal.tsx b/ui/src/components/modals/create-bedset-modal.tsx index 9f66267..77324b7 100644 --- a/ui/src/components/modals/create-bedset-modal.tsx +++ b/ui/src/components/modals/create-bedset-modal.tsx @@ -60,7 +60,7 @@ export const CreateBedSetModal = (props: Props) => {

Create BEDset

-
+
{generateBEDsetCreationDescription()} From 3b75f43683e49ac5b72adc0700e081e1e23c1d88 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 25 Nov 2024 15:49:53 -0500 Subject: [PATCH 33/51] bed splash header detail --- ui/src/components/bed-splash-components/header.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/components/bed-splash-components/header.tsx b/ui/src/components/bed-splash-components/header.tsx index 9ffa742..0f26964 100644 --- a/ui/src/components/bed-splash-components/header.tsx +++ b/ui/src/components/bed-splash-components/header.tsx @@ -254,7 +254,7 @@ export const BedSplashHeader = (props: Props) => {
)} -
+

@@ -263,7 +263,7 @@ export const BedSplashHeader = (props: Props) => {

-
+

Updated:{' '} From d0f5a7153cdfeb18dcfc833a0a9474d0fdfaff6b Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 25 Nov 2024 15:54:51 -0500 Subject: [PATCH 34/51] bed cart detail --- ui/src/pages/bed-cart.tsx | 46 ++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/ui/src/pages/bed-cart.tsx b/ui/src/pages/bed-cart.tsx index e8ea7ca..81592f3 100644 --- a/ui/src/pages/bed-cart.tsx +++ b/ui/src/pages/bed-cart.tsx @@ -68,29 +68,31 @@ export const BedCart = () => {

-
Item
{item} - - -
- - - - - - - - {cart.map((item) => ( - - - +
+
ItemAction
{item} - -
+ + + + - ))} - -
ItemAction
+ + + {cart.map((item) => ( + + {item} + + + + + ))} + + +
From 9c9a3572420b2ea2b38578e33df56bace196ec73 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 25 Nov 2024 17:05:51 -0500 Subject: [PATCH 35/51] work on adding ui for creating bedsets --- .../components/modals/create-bedset-modal.tsx | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/ui/src/components/modals/create-bedset-modal.tsx b/ui/src/components/modals/create-bedset-modal.tsx index 9f66267..7549666 100644 --- a/ui/src/components/modals/create-bedset-modal.tsx +++ b/ui/src/components/modals/create-bedset-modal.tsx @@ -5,6 +5,7 @@ import Markdown from 'react-markdown'; import { generateBEDsetPEPMd, generateBEDsetPEPDownloadRaw } from '../../utils'; import { useBedCart } from '../../contexts/bedcart-context'; import rehypeHighlight from 'rehype-highlight'; +import axios from 'axios'; type Props = { show: boolean; @@ -12,6 +13,7 @@ type Props = { }; const API_BASE = import.meta.env.VITE_API_BASE || ''; +const API_ENDPOINT = `${API_BASE}/bedset/create/`; export const generateBEDsetCreationDescription = () => { const text = ` @@ -31,7 +33,8 @@ export const generateBEDsetCreationDescription = () => { "registry_path": "namespace/name:tag" } \`\`\` - + **Note**: We currently only support PEPs from the bedbase team. If you want to create new bedset, please create an issue: [https://github.com/databio/bedbase](https://github.com/databio/bedbase/issues) + `; return text; }; @@ -41,6 +44,24 @@ export const CreateBedSetModal = (props: Props) => { const { cart } = useBedCart(); const [, copyToClipboard] = useCopyToClipboard(); const [copied, setCopied] = useState(false); + + const [inputValue, setInputValue] = useState(''); + const [message, setMessage] = useState(''); + + const handleInputRegistryPathChange = (e: React.ChangeEvent) => { + setInputValue(e.target.value); + }; + + const handleSubmit = async () => { + try { + await axios.post(API_ENDPOINT, { registry_path: inputValue }); + setMessage('Successfully created BEDset!'); + } catch (error) { + setMessage(`Unable to create BEDset. Error: ${error.message};`); + } + }; + + return ( { {generateBEDsetCreationDescription()} - Note: We currently only support PEPs from the bedbase organization.
-
+
{generateBEDsetPEPMd(cart)}
@@ -85,7 +105,25 @@ export const CreateBedSetModal = (props: Props) => { {copied ? 'Copied!' : 'Copy'} + +
+
+
+ Create a BEDset +
+
+ + +
+ {message &&
{message}
} +
+ + + + ); From d338779e3d298d8773feeb278a7a8a793587c0fd Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 25 Nov 2024 17:33:34 -0500 Subject: [PATCH 36/51] Fixed error type --- ui/src/components/modals/create-bedset-modal.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/src/components/modals/create-bedset-modal.tsx b/ui/src/components/modals/create-bedset-modal.tsx index 113f7b3..81b20ff 100644 --- a/ui/src/components/modals/create-bedset-modal.tsx +++ b/ui/src/components/modals/create-bedset-modal.tsx @@ -57,7 +57,8 @@ export const CreateBedSetModal = (props: Props) => { await axios.post(API_ENDPOINT, { registry_path: inputValue }); setMessage('Successfully created BEDset!'); } catch (error) { - setMessage(`Unable to create BEDset. Error: ${error.message};`); + const err = error as Error; + setMessage(`Unable to create BEDset. Error: ${err.message};`); } }; From b71762b2283942cdd08040846d95df3898810de1 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 25 Nov 2024 21:17:33 -0500 Subject: [PATCH 37/51] Work on bedset erroring --- bedhost/routers/bedset_api.py | 15 ++++++++++++--- ui/src/components/modals/create-bedset-modal.tsx | 9 +++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/bedhost/routers/bedset_api.py b/bedhost/routers/bedset_api.py index ef6ccfa..f344ca7 100644 --- a/bedhost/routers/bedset_api.py +++ b/bedhost/routers/bedset_api.py @@ -206,9 +206,9 @@ async def create_bedset(bedset: CreateBEDsetRequest): try: project = bbagent.config.phc.load_project(bedset.registry_path) - except Exception as err: + except Exception as _: raise HTTPException( - status_code=406, detail=f"Unable to retrieve project: {err}" + status_code=404, detail=f"Project: '{bedset.registry_path}' not found" ) bedfiles_list = [ @@ -216,6 +216,15 @@ async def create_bedset(bedset: CreateBEDsetRequest): for bedfile_id in project.samples ] + try: + bbagent.bedset.get(identifier=project.name) + raise HTTPException( + status_code=409, + detail=f"BEDset with identifier {project.name} already exists", + ) + except BedSetNotFoundError as _: + pass + try: bbagent.bedset.create( identifier=project.name, @@ -232,7 +241,7 @@ async def create_bedset(bedset: CreateBEDsetRequest): ) except Exception as err: raise HTTPException( - status_code=406, detail=f"Unable to create bedset. Error: {err}" + status_code=400, detail=f"Unable to create bedset. Error: {err}" ) return {"status": "success"} diff --git a/ui/src/components/modals/create-bedset-modal.tsx b/ui/src/components/modals/create-bedset-modal.tsx index 81b20ff..0c26a14 100644 --- a/ui/src/components/modals/create-bedset-modal.tsx +++ b/ui/src/components/modals/create-bedset-modal.tsx @@ -26,7 +26,7 @@ export const generateBEDsetCreationDescription = () => { 'author': "BEDbase team", 'source': "BEDbase", \`\`\` - 3. Go to the BEDbase API ([${API_BASE}](${API_BASE}/docs#/bedset/create_bedset_v1_bedset_create__post)) and + 3. Use 'Submit PEP' form below or BEDbase API ([${API_BASE}](${API_BASE}/docs#/bedset/create_bedset_v1_bedset_create__post)) and create a new BEDset by providing the registry path in the Body of the request. (Registry path can be copied from the PEPhub): \`\`\`json { @@ -57,8 +57,9 @@ export const CreateBedSetModal = (props: Props) => { await axios.post(API_ENDPOINT, { registry_path: inputValue }); setMessage('Successfully created BEDset!'); } catch (error) { - const err = error as Error; - setMessage(`Unable to create BEDset. Error: ${err.message};`); + const err = error as Error & { response?: { data?: { detail?: string } } }; + const errorMessage = err.response?.data?.detail || err.message; + setMessage(`! Unable to create BEDset. ${errorMessage}`); } }; @@ -110,7 +111,7 @@ export const CreateBedSetModal = (props: Props) => {
- Create a BEDset + Submit PEP
Date: Mon, 25 Nov 2024 21:52:28 -0500 Subject: [PATCH 38/51] Added bedset metadata --- ui/bedbase-types.d.ts | 386 +++++++++++++++++- .../bedset-splash-components/header.tsx | 39 +- .../text2bed/t2b-search-results-table.tsx | 4 +- ui/src/queries/useBedNeighbours.ts | 2 +- 4 files changed, 406 insertions(+), 25 deletions(-) diff --git a/ui/bedbase-types.d.ts b/ui/bedbase-types.d.ts index ded3271..fbf47a7 100644 --- a/ui/bedbase-types.d.ts +++ b/ui/bedbase-types.d.ts @@ -78,6 +78,26 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/genomes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get available genomes + * @description Returns statistics + */ + get: operations["get_bedbase_db_stats_v1_genomes_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/service-info": { parameters: { query?: never; @@ -264,6 +284,27 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/bed/{bed_id}/neighbours": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get nearest neighbours for a single BED record + * @description Returns most similar BED files in the database. Example + * bed_id: bbad85f21962bb8d972444f7f9a3a932 + */ + get: operations["get_bed_neighbours_v1_bed__bed_id__neighbours_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/bed/{bed_id}/embedding": { parameters: { query?: never; @@ -304,6 +345,28 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/bed/missing_plots": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get missing plots for a bed file. + * @description Get missing plots for a bed file + * + * example -> plot_id: gccontent + */ + get: operations["missing_plots_v1_bed_missing_plots_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/bed/{bed_id}/regions/{chr_num}": { parameters: { query?: never; @@ -462,6 +525,27 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/bedset/{bedset_id}/pep": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Download PEP project for a single BEDset record + * @description Example + * bed_id: gse218680 + */ + get: operations["get_bedset_pep_v1_bedset__bedset_id__pep_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/bedset/{bedset_id}/metadata/plots": { parameters: { query?: never; @@ -525,6 +609,50 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/bedset/{bedset_id}/track_hub": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Track Hub Bedset + * @description Generate track hub files for the BED set + */ + get: operations["get_track_hub_bedset_v1_bedset__bedset_id__track_hub_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + /** + * Get Track Hub Bedset + * @description Generate track hub files for the BED set + */ + head: operations["get_track_hub_bedset_v1_bedset__bedset_id__track_hub_head"]; + patch?: never; + trace?: never; + }; + "/v1/bedset/create/": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Create Bedset + * @description Create a new bedset by providing registry path to the PEPhub project + */ + post: operations["create_bedset_v1_bedset_create__post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/objects/{object_id}": { parameters: { query?: never; @@ -626,6 +754,17 @@ export interface components { /** Headers */ headers?: Record | null; }; + /** BaseListResponse */ + BaseListResponse: { + /** Count */ + count: number; + /** Limit */ + limit: number; + /** Offset */ + offset: number; + /** Results */ + results: unknown[]; + }; /** BedClassification */ BedClassification: { /** Name */ @@ -678,17 +817,6 @@ export interface components { /** Results */ results?: components["schemas"]["QdrantSearchResult"][]; }; - /** BedNeighborsResult */ - BedNeighboursResult: { - /** Count */ - count: number; - /** Limit */ - limit: number; - /** Offset */ - offset: number; - /** Results */ - results?: components["schemas"]["QdrantSearchResult"][]; - }; /** BedMetadataAll */ BedMetadataAll: { /** @@ -971,6 +1099,7 @@ export interface components { widths_histogram?: components["schemas"]["FileModel"]; neighbor_distances?: components["schemas"]["FileModel"]; open_chromatin?: components["schemas"]["FileModel"]; + tss_distance?: components["schemas"]["FileModel"]; }; /** BedSetBedFiles */ BedSetBedFiles: { @@ -998,12 +1127,26 @@ export interface components { name: string; /** Md5Sum */ md5sum: string; + /** + * Submission Date + * Format: date-time + */ + submission_date?: string; + /** + * Last Update Date + * Format: date-time + */ + last_update_date?: string; statistics?: components["schemas"]["BedSetStats"] | null; plots?: components["schemas"]["BedSetPlots"] | null; /** Description */ description?: string; /** Bed Ids */ bed_ids?: string[]; + /** Author */ + author?: string | null; + /** Source */ + source?: string | null; }; /** BedSetMinimal */ BedSetMinimal: { @@ -1025,7 +1168,7 @@ export interface components { }; /** BedStatsModel */ BedStatsModel: { - /** Regions No */ + /** Number Of Regions */ number_of_regions?: number | null; /** Gc Content */ gc_content?: number | null; @@ -1091,6 +1234,11 @@ export interface components { /** Openapi Version */ openapi_version: string; }; + /** CreateBEDsetRequest */ + CreateBEDsetRequest: { + /** Registry Path */ + registry_path: string; + }; /** DRSModel */ DRSModel: { /** Id */ @@ -1155,7 +1303,7 @@ export interface components { /** Id */ id: string; /** Payload */ - payload: Record; + payload?: Record; /** Score */ score: number; metadata?: components["schemas"]["BedMetadataBasic"] | null; @@ -1429,6 +1577,26 @@ export interface operations { }; }; }; + get_bedbase_db_stats_v1_genomes_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BaseListResponse"]; + }; + }; + }; + }; service_info_v1_service_info_get: { parameters: { query?: never; @@ -1700,6 +1868,41 @@ export interface operations { }; }; }; + get_bed_neighbours_v1_bed__bed_id__neighbours_get: { + parameters: { + query?: { + limit?: number; + offset?: number; + }; + header?: never; + path: { + /** @description BED digest */ + bed_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BedListSearchResult"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; get_bed_embedding_v1_bed__bed_id__embedding_get: { parameters: { query?: never; @@ -1765,6 +1968,37 @@ export interface operations { }; }; }; + missing_plots_v1_bed_missing_plots_get: { + parameters: { + query: { + plot_id: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BaseListResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; get_regions_for_bedfile_v1_bed__bed_id__regions__chr_num__get: { parameters: { query?: { @@ -2026,6 +2260,37 @@ export interface operations { }; }; }; + get_bedset_pep_v1_bedset__bedset_id__pep_get: { + parameters: { + query?: never; + header?: never; + path: { + bedset_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; get_bedset_metadata_v1_bedset__bedset_id__metadata_plots_get: { parameters: { query?: never; @@ -2119,6 +2384,101 @@ export interface operations { }; }; }; + get_track_hub_bedset_v1_bedset__bedset_id__track_hub_get: { + parameters: { + query?: never; + header?: never; + path: { + bedset_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_track_hub_bedset_v1_bedset__bedset_id__track_hub_head: { + parameters: { + query?: never; + header?: never; + path: { + bedset_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + create_bedset_v1_bedset_create__post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateBEDsetRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; get_drs_object_metadata_v1_objects__object_id__get: { parameters: { query?: never; diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index aec2286..c806d7a 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -3,6 +3,7 @@ import { components } from '../../../bedbase-types'; import { useBedCart } from '../../contexts/bedcart-context'; import { DownloadBedSetModal } from '../modals/download-bedset-modal'; import { useCopyToClipboard } from '@uidotdev/usehooks'; +import { formatDateTime } from '../../utils.ts'; type BedSetMetadata = components['schemas']['BedSetMetadata']; type Props = { @@ -83,12 +84,12 @@ export const BedsetSplashHeader = (props: Props) => { metadata.bed_ids?.length === 0 ? undefined : () => { - addMultipleBedsToCart(metadata.bed_ids || []); - setAddedToCart(true); - setTimeout(() => { - setAddedToCart(false); - }, 500); - } + addMultipleBedsToCart(metadata.bed_ids || []); + setAddedToCart(true); + setTimeout(() => { + setAddedToCart(false); + }, 500); + } } disabled={metadata.bed_ids?.length === 0 || addedToCart} className="btn btn-primary btn-sm" @@ -104,10 +105,12 @@ export const BedsetSplashHeader = (props: Props) => {
-
-

{metadata?.description || 'No description available'}

+
+

{metadata?.description || 'No description available'}

+
Author: {metadata?.author || 'N/A'}
+
Source: {metadata?.source || 'N/A'}
-
+

@@ -124,6 +127,24 @@ export const BedsetSplashHeader = (props: Props) => {

)}
+ +
+
+ +

+ Created:{' '} + {metadata?.submission_date ? formatDateTime(metadata?.submission_date) : 'No date available'} +

+
+ +
+ +

+ Updated:{' '} + {metadata?.last_update_date ? formatDateTime(metadata?.last_update_date) : 'No date available'} +

+
+
diff --git a/ui/src/components/search/text2bed/t2b-search-results-table.tsx b/ui/src/components/search/text2bed/t2b-search-results-table.tsx index dd4561d..ce5842f 100644 --- a/ui/src/components/search/text2bed/t2b-search-results-table.tsx +++ b/ui/src/components/search/text2bed/t2b-search-results-table.tsx @@ -7,10 +7,10 @@ import toast from 'react-hot-toast'; import YAML from 'js-yaml'; type SearchResponse = components['schemas']['BedListSearchResult']; -type BedNeighboursResponse = components['schemas']['BedNeighboursResult']; +// type BedNeighboursResponse = components['schemas']['BedNeighboursResult']; type Props = { - results: SearchResponse | BedNeighboursResponse; + results: SearchResponse; search_query?: string | undefined; }; diff --git a/ui/src/queries/useBedNeighbours.ts b/ui/src/queries/useBedNeighbours.ts index 8d44922..82ca34a 100644 --- a/ui/src/queries/useBedNeighbours.ts +++ b/ui/src/queries/useBedNeighbours.ts @@ -2,7 +2,7 @@ import { useQuery } from '@tanstack/react-query'; import { useBedbaseApi } from '../contexts/api-context'; import { components } from '../../bedbase-types'; -type BedNeighboursResponse = components['schemas']['BedNeighboursResult']; +type BedNeighboursResponse = components['schemas']['BedListSearchResult']; type BedNeighboursQuery = { md5?: string; limit?: number; From babb5e123a8cfb4bfac56e918c06ffbecb5d85a7 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Tue, 26 Nov 2024 21:14:42 -0500 Subject: [PATCH 39/51] bedset creation modal details --- .../components/modals/create-bedset-modal.tsx | 50 ++++++++++--------- ui/src/custom.scss | 6 +++ ui/src/pages/bed-cart.tsx | 2 +- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/ui/src/components/modals/create-bedset-modal.tsx b/ui/src/components/modals/create-bedset-modal.tsx index 0c26a14..60d715d 100644 --- a/ui/src/components/modals/create-bedset-modal.tsx +++ b/ui/src/components/modals/create-bedset-modal.tsx @@ -82,38 +82,40 @@ export const CreateBedSetModal = (props: Props) => { >

Create BEDset

- -
- - - {generateBEDsetCreationDescription()} -
-
- {generateBEDsetPEPMd(cart)} +
+ + {generateBEDsetCreationDescription()} +
-
- +
+ {generateBEDsetPEPMd(cart)} +
+ +
-
-
+ +
+ +
+ Submit PEP -
-
+ +
diff --git a/ui/src/custom.scss b/ui/src/custom.scss index a2ca052..7be2237 100644 --- a/ui/src/custom.scss +++ b/ui/src/custom.scss @@ -305,3 +305,9 @@ td { padding-left: 1rem !important; padding-right: 1rem !important; } + +.markdown-bg code { + border-radius: 1rem !important; + color: #212529; + background: #e9ecef; +} diff --git a/ui/src/pages/bed-cart.tsx b/ui/src/pages/bed-cart.tsx index 81592f3..e436f0e 100644 --- a/ui/src/pages/bed-cart.tsx +++ b/ui/src/pages/bed-cart.tsx @@ -41,7 +41,7 @@ export const BedCart = () => { } return ( - +
From f80e2a8b1a5cced44b1f3f02d0c41239b96dcdf0 Mon Sep 17 00:00:00 2001 From: nsheff Date: Tue, 26 Nov 2024 21:16:10 -0500 Subject: [PATCH 40/51] some tests --- interactive.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 interactive.py diff --git a/interactive.py b/interactive.py new file mode 100644 index 0000000..113490b --- /dev/null +++ b/interactive.py @@ -0,0 +1,52 @@ +import bbconf +bba = bbconf.BedBaseAgent("deployment/config/api-dev.bedbase.org.yaml") + +bba.config._b2bsi=bba.config._init_b2bsi_object() +bba.config._r2v = bba.config._init_r2v_object() +bba.config._bivec = bba.config._init_bivec_object() + + +# Here's some code to test the BiVectorSearchInterface + +from geniml.search.interfaces import BiVectorSearchInterface +from geniml.search.backends import BiVectorBackend + +from geniml.search.query2vec import Text2Vec + +search_backend = BiVectorBackend( + metadata_backend=self._qdrant_text_engine, bed_backend=self._qdrant_engine +) + +t2v = Text2Vec('sentence-transformers/all-MiniLM-L6-v2', v2v=None) + +bvsi = BiVectorSearchInterface() + +from langchain_huggingface.embeddings import HuggingFaceEmbeddings +import logging +from typing import Union + +import numpy as np +from langchain_huggingface.embeddings import HuggingFaceEmbeddings + +from geniml.text2bednn import Vec2VecFNN +from geniml.search.query2vec.abstract import Query2Vec + +# culprit: +te = HuggingFaceEmbeddings(model_name='sentence-transformers/all-MiniLM-L6-v2') + +# Testing the sentence transformers: + + +from sentence_transformers import SentenceTransformer +sentences = ["This is an example sentence", "Each sentence is converted"] + +model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') +embeddings = model.encode(sentences) +print(embeddings) + + +from fastembed import TextEmbedding +model = TextEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2", max_length=512) +sentences = ["This is an example sentence", "Each sentence is converted"] +embeddings = list(model.embed(sentences)) + From f7b36759e82d5ac08f6bb4027107fa3478223644 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 2 Dec 2024 12:33:38 -0500 Subject: [PATCH 41/51] Fixed #103 --- .../bed2bed/b2b-search-results-table.tsx | 21 ++++++++++++++++++- .../text2bed/t2b-search-results-table.tsx | 20 +++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx index 30dd595..66bb393 100644 --- a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx +++ b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx @@ -28,6 +28,25 @@ type Props = { const columnHelper = createColumnHelper(); +const scoreTooltip = ( + +
+            Cosine similarity between files.
+            Score is between 0 an 100, where 100 is a perfect match.
+          
+ + } + > + + Score* + + +
+) + export const Bed2BedSearchResultsTable = (props: Props) => { const { beds } = props; const { cart, addBedToCart, removeBedFromCart } = useBedCart(); @@ -118,7 +137,7 @@ export const Bed2BedSearchResultsTable = (props: Props) => { ), footer: (info) => info.column.id, - header: 'Score', + header: scoreTooltip, id: 'score', }), columnHelper.accessor('metadata.id', { diff --git a/ui/src/components/search/text2bed/t2b-search-results-table.tsx b/ui/src/components/search/text2bed/t2b-search-results-table.tsx index ce5842f..8f9e182 100644 --- a/ui/src/components/search/text2bed/t2b-search-results-table.tsx +++ b/ui/src/components/search/text2bed/t2b-search-results-table.tsx @@ -62,7 +62,25 @@ export const Text2BedSearchResultsTable = (props: Props) => { Description Assay Info - Score + + +
+                      Cosine similarity between search term and bedfile
+                      Score is between 0 an 100, where 100 is a perfect match.
+                    
+ + } + > + + Score* + + +
+ + Actions From ea3c1951d4ca6c2c5ebf7b77f59d41673c70ab5f Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 2 Dec 2024 13:00:29 -0500 Subject: [PATCH 42/51] bedset header ui details --- ui/src/components/bedset-splash-components/header.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index 07ce1d0..c8df7cd 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -114,8 +114,8 @@ export const BedsetSplashHeader = (props: Props) => {

{metadata?.description || 'No description available'}

-
Author: {metadata?.author || 'N/A'}
-
Source: {metadata?.source || 'N/A'}
+

Author: {metadata?.author || 'None'}

+

Source: {metadata?.source || 'None'}

@@ -135,7 +135,7 @@ export const BedsetSplashHeader = (props: Props) => { )}
-
+

From a676ad2112d81065d14c5fa9ee1514e14dbabb3f Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 2 Dec 2024 14:13:26 -0500 Subject: [PATCH 43/51] type error --- ui/src/components/search/bed2bed/b2b-search-results-table.tsx | 2 +- ui/src/components/search/text2bed/t2b-search-results-table.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx index 66bb393..a869c60 100644 --- a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx +++ b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx @@ -137,7 +137,7 @@ export const Bed2BedSearchResultsTable = (props: Props) => { ), footer: (info) => info.column.id, - header: scoreTooltip, + header: () => scoreTooltip, id: 'score', }), columnHelper.accessor('metadata.id', { diff --git a/ui/src/components/search/text2bed/t2b-search-results-table.tsx b/ui/src/components/search/text2bed/t2b-search-results-table.tsx index 8f9e182..a19a5f4 100644 --- a/ui/src/components/search/text2bed/t2b-search-results-table.tsx +++ b/ui/src/components/search/text2bed/t2b-search-results-table.tsx @@ -68,7 +68,7 @@ export const Text2BedSearchResultsTable = (props: Props) => { overlay={

-                      Cosine similarity between search term and bedfile
+                      Cosine similarity between search term and bedfile.
                       Score is between 0 an 100, where 100 is a perfect match.
                     
From 2e3251fa757455672d82cf97d0a0383c89c424cd Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 2 Dec 2024 14:14:04 -0500 Subject: [PATCH 44/51] fixed tooltip and lint --- interactive.py | 16 ++- .../bed2bed/b2b-search-results-table.tsx | 106 +++++++++--------- 2 files changed, 64 insertions(+), 58 deletions(-) diff --git a/interactive.py b/interactive.py index 113490b..88c6ed7 100644 --- a/interactive.py +++ b/interactive.py @@ -1,7 +1,8 @@ import bbconf + bba = bbconf.BedBaseAgent("deployment/config/api-dev.bedbase.org.yaml") -bba.config._b2bsi=bba.config._init_b2bsi_object() +bba.config._b2bsi = bba.config._init_b2bsi_object() bba.config._r2v = bba.config._init_r2v_object() bba.config._bivec = bba.config._init_bivec_object() @@ -17,7 +18,7 @@ metadata_backend=self._qdrant_text_engine, bed_backend=self._qdrant_engine ) -t2v = Text2Vec('sentence-transformers/all-MiniLM-L6-v2', v2v=None) +t2v = Text2Vec("sentence-transformers/all-MiniLM-L6-v2", v2v=None) bvsi = BiVectorSearchInterface() @@ -32,21 +33,24 @@ from geniml.search.query2vec.abstract import Query2Vec # culprit: -te = HuggingFaceEmbeddings(model_name='sentence-transformers/all-MiniLM-L6-v2') +te = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") # Testing the sentence transformers: from sentence_transformers import SentenceTransformer + sentences = ["This is an example sentence", "Each sentence is converted"] -model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') +model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2") embeddings = model.encode(sentences) print(embeddings) from fastembed import TextEmbedding -model = TextEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2", max_length=512) + +model = TextEmbedding( + model_name="sentence-transformers/all-MiniLM-L6-v2", max_length=512 +) sentences = ["This is an example sentence", "Each sentence is converted"] embeddings = list(model.embed(sentences)) - diff --git a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx index 66bb393..e786c9b 100644 --- a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx +++ b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx @@ -28,24 +28,26 @@ type Props = { const columnHelper = createColumnHelper(); -const scoreTooltip = ( - -
-            Cosine similarity between files.
-            Score is between 0 an 100, where 100 is a perfect match.
-          
- - } - > - - Score* - - -
-) +// TODO: Add tooltip for score. Element is not excepted by the table +// const scoreTooltip = ( +// +//
+//             Cosine similarity between files.
+//             Score is between 0 an 100, where 100 is a perfect match.
+//           
+// +// } +// > +// +// Score* +// +// +//
+// ) +const scoreTooltip: string = 'Score'; export const Bed2BedSearchResultsTable = (props: Props) => { const { beds } = props; @@ -220,44 +222,44 @@ export const Bed2BedSearchResultsTable = (props: Props) => {
- {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => ( - + {headerGroup.headers.map((header) => ( + - ))} - - ))} + : undefined + } + > + {flexRender(header.column.columnDef.header, header.getContext())} + {{ + asc: , + desc: , + }[header.column.getIsSorted() as string] ?? null} + + )} + + ))} + + ))} - {table.getRowModel().rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - ))} - - ))} + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + ))} + + ))}
- {header.isPlaceholder ? null : ( -
( +
+ {header.isPlaceholder ? null : ( +
- {flexRender(header.column.columnDef.header, header.getContext())} - {{ - asc: , - desc: , - }[header.column.getIsSorted() as string] ?? null} -
- )} -
{flexRender(cell.column.columnDef.cell, cell.getContext())}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
From 08f2743d54a7d3ccdd1bb136c3677b7f58c6d835 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 2 Dec 2024 14:21:00 -0500 Subject: [PATCH 45/51] fixed tooltip --- .../bed2bed/b2b-search-results-table.tsx | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx index 8194188..e5802e5 100644 --- a/ui/src/components/search/bed2bed/b2b-search-results-table.tsx +++ b/ui/src/components/search/bed2bed/b2b-search-results-table.tsx @@ -28,26 +28,24 @@ type Props = { const columnHelper = createColumnHelper(); -// TODO: Add tooltip for score. Element is not excepted by the table -// const scoreTooltip = ( -// -//
-//             Cosine similarity between files.
-//             Score is between 0 an 100, where 100 is a perfect match.
-//           
-// -// } -// > -// -// Score* -// -// -//
-// ) -const scoreTooltip: string = 'Score'; +const scoreTooltip = ( + +
+            Cosine similarity between files.
+            Score is between 0 an 100, where 100 is a perfect match.
+          
+ + } + > + + Score* + + +
+) export const Bed2BedSearchResultsTable = (props: Props) => { const { beds } = props; From f772a81a3a7062c5ecc414c1f95395d67d1b3695 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 3 Dec 2024 14:51:52 -0500 Subject: [PATCH 46/51] added geniml version --- ui/src/components/layout.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/src/components/layout.tsx b/ui/src/components/layout.tsx index 6d8ee6a..f006bce 100644 --- a/ui/src/components/layout.tsx +++ b/ui/src/components/layout.tsx @@ -27,6 +27,9 @@ const Footer = () => { bbconf {data?.component_versions?.bbconf_version || ''} + + geniml {data?.component_versions?.geniml_version || ''} + Python {data?.component_versions?.python_version || ''} From ac59324df5cc83e2131e0ac9de192c0b9c5b6f35 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Wed, 11 Dec 2024 14:52:56 -0500 Subject: [PATCH 47/51] remove footer again from nonempty cart page --- ui/src/pages/bed-cart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/pages/bed-cart.tsx b/ui/src/pages/bed-cart.tsx index e436f0e..81592f3 100644 --- a/ui/src/pages/bed-cart.tsx +++ b/ui/src/pages/bed-cart.tsx @@ -41,7 +41,7 @@ export const BedCart = () => { } return ( - +
From a41e47d9d7cca8062ea3ec819138c478561f8279 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 19 Dec 2024 13:14:54 -0500 Subject: [PATCH 48/51] Added reference validation endpoint --- bedhost/routers/bed_api.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/bedhost/routers/bed_api.py b/bedhost/routers/bed_api.py index c1b3998..6b98792 100644 --- a/bedhost/routers/bed_api.py +++ b/bedhost/routers/bed_api.py @@ -28,6 +28,7 @@ TokenizedBedResponse, TokenizedPathResponse, QdrantSearchResult, + RefGenValidReturnModel, ) from fastapi import APIRouter, File, HTTPException, Query, UploadFile from fastapi.responses import PlainTextResponse @@ -481,3 +482,24 @@ async def get_tokens( status_code=404, detail="Tokenized file not found", ) + + +@router.get( + "/{bed_id}/reference_validations", + summary="Get reference genome validation results", + response_model=RefGenValidReturnModel, +) +async def get_ref_gen_results( + bed_id: str, +): + """ + Return reference genome validation results for a bed file + Example: bed: 0dcdf8986a72a3d85805bbc9493a1302 + """ + try: + return bbagent.bed.get_reference_validation(bed_id) + except BEDFileNotFoundError as _: + raise HTTPException( + status_code=404, + detail=f"Bed file {bed_id} not found", + ) From dd09342468a39847d478888481f0a15045bbfcf8 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 19 Dec 2024 13:51:55 -0500 Subject: [PATCH 49/51] Fixed #156 --- .../bedset-splash-components/header.tsx | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index c8df7cd..1a6b3cc 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -47,15 +47,17 @@ export const BedsetSplashHeader = (props: Props) => { -
+

From 0c31b814241105a68a399fe7789e6f9f6e72f453 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 19 Dec 2024 13:54:10 -0500 Subject: [PATCH 50/51] FIxed previous commit --- ui/src/components/bedset-splash-components/header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/bedset-splash-components/header.tsx b/ui/src/components/bedset-splash-components/header.tsx index 1a6b3cc..00ed080 100644 --- a/ui/src/components/bedset-splash-components/header.tsx +++ b/ui/src/components/bedset-splash-components/header.tsx @@ -47,7 +47,7 @@ export const BedsetSplashHeader = (props: Props) => {

{/* TODO: change hg38 on correct genome */} {/**/} - {metadata.bed_ids?.length <= 20 && ( + {(metadata.bed_ids?.length || 0) <= 20 && ( Date: Fri, 3 Jan 2025 12:21:42 -0500 Subject: [PATCH 51/51] Fixed comments --- bedhost/_version.py | 2 +- bedhost/routers/bed_api.py | 2 +- bedhost/routers/bedset_api.py | 5 +---- requirements/requirements-all.txt | 6 +++--- ui/src/components/modals/create-bedset-modal.tsx | 5 +---- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/bedhost/_version.py b/bedhost/_version.py index 777f190..3e2f46a 100644 --- a/bedhost/_version.py +++ b/bedhost/_version.py @@ -1 +1 @@ -__version__ = "0.8.0" +__version__ = "0.9.0" diff --git a/bedhost/routers/bed_api.py b/bedhost/routers/bed_api.py index 6b98792..72b79e1 100644 --- a/bedhost/routers/bed_api.py +++ b/bedhost/routers/bed_api.py @@ -485,7 +485,7 @@ async def get_tokens( @router.get( - "/{bed_id}/reference_validations", + "/{bed_id}/genome-stats", summary="Get reference genome validation results", response_model=RefGenValidReturnModel, ) diff --git a/bedhost/routers/bedset_api.py b/bedhost/routers/bedset_api.py index f344ca7..33650f8 100644 --- a/bedhost/routers/bedset_api.py +++ b/bedhost/routers/bedset_api.py @@ -216,14 +216,11 @@ async def create_bedset(bedset: CreateBEDsetRequest): for bedfile_id in project.samples ] - try: - bbagent.bedset.get(identifier=project.name) + if bbagent.bedset.exists(identifier=project.name): raise HTTPException( status_code=409, detail=f"BEDset with identifier {project.name} already exists", ) - except BedSetNotFoundError as _: - pass try: bbagent.bedset.create( diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index 451418d..323d72b 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -1,5 +1,5 @@ -bbconf @ git+https://github.com/databio/bbconf.git@dev#egg=bbconf -# bbconf>=0.9.1 +# bbconf @ git+https://github.com/databio/bbconf.git@dev#egg=bbconf +bbconf>=0.10.0 fastapi>=0.103.0 logmuse>=0.2.7 markdown @@ -9,4 +9,4 @@ uvicorn yacman>=0.9.2 pephubclient>=0.4.1 psycopg[binary,pool] -python-multipart>=0.0.9 \ No newline at end of file +python-multipart>=0.0.9 diff --git a/ui/src/components/modals/create-bedset-modal.tsx b/ui/src/components/modals/create-bedset-modal.tsx index 60d715d..30d0c96 100644 --- a/ui/src/components/modals/create-bedset-modal.tsx +++ b/ui/src/components/modals/create-bedset-modal.tsx @@ -13,7 +13,7 @@ type Props = { }; const API_BASE = import.meta.env.VITE_API_BASE || ''; -const API_ENDPOINT = `${API_BASE}/bedset/create/`; +const API_ENDPOINT = `${API_BASE}/bedset/create`; export const generateBEDsetCreationDescription = () => { const text = ` @@ -125,9 +125,6 @@ export const CreateBedSetModal = (props: Props) => {
- - - );