Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add basic table for similar bed files and pdf download button for plots #155

Merged
merged 9 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions ui/bedbase-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
/**
Expand Down
25 changes: 15 additions & 10 deletions ui/src/components/bed-splash-components/plots.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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 (
Expand All @@ -31,13 +32,13 @@ const Plot = (props: PlotProps) => {
}}
className="h-100 border rounded p-1 shadow-sm hover-border-primary transition-all"
>
<div className="px-1 d-flex flex-row justify-content-between w-100 mb-1">
<span className="fw-bold text-sm text-center w-100 mb-1">{title}</span>
<div className="px-1 text-center">
<span className="fw-bold text-sm mb-1">{title}</span>
{/* <button onClick={() => setShow(true)} className="btn btn-sm btn-outline-primary text-xs">
<i className="bi bi-eye" />
</button> */}
</div>
<div className="d-flex flex-row align-items-center w-100 justify-content-center">
<div className="text-center">
<Image height="300px" src={src} alt={alt} />
</div>
<FigureModal
Expand All @@ -47,6 +48,7 @@ const Plot = (props: PlotProps) => {
}}
title={title}
src={src}
pdf={pdf}
alt={alt}
/>
</div>
Expand All @@ -55,13 +57,15 @@ const Plot = (props: PlotProps) => {

export const Plots = (props: PlotsProps) => {
const { metadata } = props;
console.log(props)
Copy link
Member

Choose a reason for hiding this comment

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

Remove console.log?


const plotNames = metadata.plots ? Object.keys(metadata.plots) : [];
return (
<Fragment>
<div className="my-2">
<Row className="my-2 row-cols-3 g-2">
{metadata.plots &&
chunkArray(plotNames, 3).map((chunk, idx) => (
<Row key={idx} className="mb-2">
<Fragment key={idx}>
{chunk.map((plotName) => {
// this is for type checking
const plotNameKey = plotName as keyof typeof metadata.plots;
Expand All @@ -73,19 +77,20 @@ export const Plots = (props: PlotsProps) => {
metadata.plots[plotNameKey]?.description || metadata.plots[plotNameKey].title
: plotName;
return (
<Col key={plotName} sm={12} md={4} className="px-1">
<Col key={plotName}>
<Plot
key={plotName}
src={plotExists ? makeThumbnailImageLink(metadata.id, plotName, 'bed') : '/fignotavl_png.svg'}
pdf={plotExists ? makePDFImageLink(metadata.id, plotName, 'bed') : '/fignotavl_png.svg'}
alt={alt || 'No description available'}
title={title || 'No title available'}
/>
</Col>
);
})}
</Row>
</Fragment>
))}
</div>
</Row>
</Fragment>
);
};
104 changes: 53 additions & 51 deletions ui/src/components/bedset-splash-components/beds-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,65 +139,67 @@ export const BedsTable = (props: Props) => {
});

return (
<div className="rounded border shadow-sm my-2">
<div className="rounded border shadow-sm my-2 p-0">
<div className="d-flex flex-row mt-2">
<input
className="form-control"
className="form-control mx-3 mt-1 mb-2"
placeholder="Search files"
value={globalFilter}
onChange={(e) => setGlobalFilter(e.target.value)}
/>
</div>
<table className="table mb-2 table-hover">
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id} colSpan={header.colSpan} scope="col" className="text-right align-middle" style={{ minWidth: '110px' }}>
{header.isPlaceholder ? null : (
<div
className={header.column.getCanSort() ? 'cursor-pointer' : ''}
onClick={header.column.getToggleSortingHandler()}
title={
header.column.getCanSort()
? header.column.getNextSortingOrder() === 'asc'
? 'Sort ascending'
: header.column.getNextSortingOrder() === 'desc'
? 'Sort descending'
: 'Clear sort'
: undefined
}
>
{flexRender(header.column.columnDef.header, header.getContext())}
{{
asc: ' 🔼',
desc: ' 🔽',
}[header.column.getIsSorted() as string] ?? null}
</div>
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr
key={row.id}
className="cursor-pointer"
onClick={() => (window.location.href = `/bed/${row.original.id}`)}
>
{row.getVisibleCells().map((cell) => (
<td key={cell.id} className="text-right align-middle small-font">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
<div className='table-responsive'>
<table className="table mb-2 table-hover">
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id} colSpan={header.colSpan} scope="col" className="text-right align-middle" style={{ minWidth: '110px' }}>
{header.isPlaceholder ? null : (
<div
className={header.column.getCanSort() ? 'cursor-pointer' : ''}
onClick={header.column.getToggleSortingHandler()}
title={
header.column.getCanSort()
? header.column.getNextSortingOrder() === 'asc'
? 'Sort ascending'
: header.column.getNextSortingOrder() === 'desc'
? 'Sort descending'
: 'Clear sort'
: undefined
}
>
{flexRender(header.column.columnDef.header, header.getContext())}
{{
asc: <i className='bi bi-caret-up-fill ms-1' />,
desc: <i className='bi bi-caret-down-fill ms-1' />,
}[header.column.getIsSorted() as string] ?? null}
</div>
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr
key={row.id}
className="cursor-pointer"
onClick={() => (window.location.href = `/bed/${row.original.id}`)}
>
{row.getVisibleCells().map((cell) => (
<td key={cell.id} className="text-right align-middle small-font">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
<div className="h-4" />
<div className="d-flex justify-content-between align-items-center gap-2 mb-2">
<div className="d-flex justify-content-between align-items-center gap-2 m-3">
<div className="d-flex flex-row align-items-center ">
Showing
<span className="fw-bold mx-1">
Expand Down
8 changes: 4 additions & 4 deletions ui/src/components/bedset-splash-components/plots.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ export const Plots = (props: PlotsProps) => {
const plotNames = metadata.plots ? Object.keys(metadata.plots) : [];
return (
<Fragment>
<div className="my-2">
<Row className="my-2 row-cols-3 g-2">
{metadata.plots &&
chunkArray(plotNames, 3).map((chunk, idx) => (
<Row key={idx} className="mb-2">
<Fragment key={idx}>
{chunk.map((plotName) => {
// this is for type checking
const plotNameKey = plotName as keyof typeof metadata.plots;
Expand All @@ -83,9 +83,9 @@ export const Plots = (props: PlotsProps) => {
</Col>
);
})}
</Row>
</Fragment>
))}
</div>
</Row>
</Fragment>
);
};
20 changes: 18 additions & 2 deletions ui/src/components/modals/figure-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<Modal
animation={false}
Expand All @@ -35,8 +37,22 @@ export const FigureModal = (props: Props) => {
link.click();
}}
>
<i className="bi bi-download me2"></i> Download
<i className="bi bi-download me-1"></i> Download PNG
</button>
{pdf &&
<button
className="btn btn-outline-primary"
onClick={() => {
const link = document.createElement('a');
link.href = pdf;
link.download = alt;
link.click();
}}
>
<i className="bi bi-download me-1"></i> Download PDF
</button>
}

<button onClick={() => onHide()} className="btn btn-primary">
Close
</button>
Expand Down
26 changes: 18 additions & 8 deletions ui/src/components/search/bed2bed/b2b-search-results-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
}
};
Comment on lines +187 to +190
Copy link
Member

Choose a reason for hiding this comment

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

Curious what this is doing? Are we able to somehow make it an href or anchor tag (<a />)?

Copy link
Member

Choose a reason for hiding this comment

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

I think I get it. I was looking at it seems that there's not really a nice "right" way to make a row a link: https://stackoverflow.com/questions/17147821/how-to-make-a-whole-row-in-a-table-clickable-as-a-link

I'm confused why its not just window.location.href = /bed/idand whatclosest` is doing? Im sure I am missing something.


return (
<div className="rounded border shadow-sm p-1">
<div className="rounded border shadow-sm px-0 py-1">
<div className="d-flex flex-row mt-2">
<input
className="form-control"
className="form-control mx-3 mt-1 mb-2"
placeholder="Search files"
value={globalFilter}
onChange={(e) => setGlobalFilter(e.target.value)}
/>
</div>
<table className="table mb-2 text-sm">
<table className="table mb-2 text-sm table-hover">
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
Expand All @@ -215,8 +221,8 @@ export const Bed2BedSearchResultsTable = (props: Props) => {
>
{flexRender(header.column.columnDef.header, header.getContext())}
{{
asc: ' 🔼',
desc: ' 🔽',
asc: <i className='bi bi-caret-up-fill ms-1' />,
desc: <i className='bi bi-caret-down-fill ms-1' />,
}[header.column.getIsSorted() as string] ?? null}
</div>
)}
Expand All @@ -227,7 +233,11 @@ export const Bed2BedSearchResultsTable = (props: Props) => {
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id}>
<tr
key={row.id}
onClick={handleRowClick(row.original.metadata?.id)}
className="cursor-pointer"
>
{row.getVisibleCells().map((cell) => (
<td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
))}
Expand All @@ -236,8 +246,8 @@ export const Bed2BedSearchResultsTable = (props: Props) => {
</tbody>
</table>
<div className="h-4" />
<div className="d-flex justify-content-between align-items-center gap-2 mb-2">
<div className="d-flex flex-row align-items-center ">
<div className="d-flex justify-content-between align-items-center gap-2 m-3">
<div className="d-flex flex-row align-items-center">
Showing
<span className="fw-bold mx-1">
{table.getState().pagination.pageSize * table.getState().pagination.pageIndex + 1} to{' '}
Expand Down
14 changes: 12 additions & 2 deletions ui/src/components/search/search-bedset-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<table className="table table-hover">
<thead>
Expand All @@ -24,13 +30,17 @@ export const SearchBedSetResultTable = (props: Props) => {
</thead>
<tbody>
{results.results?.map((result) => (
<tr key={result.id} className='position-relative'>
<tr
key={result.id}
onClick={handleRowClick(result?.id)}
className='cursor-pointer position-relative'
>
<td>{result?.id || 'Unknown Id'}</td>
<td>{result?.name || 'Unknown Name'}</td>
<td>{result?.description || 'Unknown Description'}</td>
<td>{result?.bed_ids?.length || 0}</td>
<td>
<a className="me-1 align-content-center stretched-link" href={`/bedset/${result?.id}`}>
<a className="me-1 align-content-center" href={`/bedset/${result?.id}`}>
<button className="btn btn-sm btn-outline-primary position-relative" style={{zIndex: 999}}>
<i className="bi bi-eye"></i>
</button>
Expand Down
Loading
Loading