Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
2 changes: 1 addition & 1 deletion bedhost/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.10.3"
__version__ = "0.10.4"
6 changes: 4 additions & 2 deletions bedhost/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
EXAMPLE_BED = "bbad85f21962bb8d972444f7f9a3a932"
EXAMPLE_BEDSET = "gse218680"

# how often to save usage data (in days)
USAGE_SAVE_DAYS = 7
# how often to save usage data (in hours)
USAGE_SAVE_HOURS = 1
# For how many days record usage data (every month this will be reset)
USAGE_RECORD_DAYS = 30
8 changes: 5 additions & 3 deletions bedhost/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from . import _LOGGER
from ._version import __version__ as bedhost_version
from .cli import build_parser
from .const import PKG_NAME, STATIC_PATH, USAGE_SAVE_DAYS
from .const import PKG_NAME, STATIC_PATH, USAGE_SAVE_HOURS, USAGE_RECORD_DAYS
from .helpers import attach_routers, configure, drs_response, init_model_usage
from apscheduler.schedulers.background import BackgroundScheduler

Expand Down Expand Up @@ -173,7 +173,9 @@ def upload_usage():
"""

print("Running uploading of the usage")
usage_data.date_to = datetime.datetime.now()
usage_data.date_to = datetime.datetime.now() + datetime.timedelta(
days=USAGE_RECORD_DAYS
)
bbagent.add_usage(usage_data)

usage_data.bed_meta = {}
Expand All @@ -184,7 +186,7 @@ def upload_usage():
usage_data.date_from = datetime.datetime.now()
usage_data.date_to = None

scheduler.add_job(upload_usage, "interval", days=USAGE_SAVE_DAYS)
scheduler.add_job(upload_usage, "interval", hours=USAGE_SAVE_HOURS)
scheduler.start()

attach_routers(app)
Expand Down
20 changes: 17 additions & 3 deletions bedhost/routers/base_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from platform import python_version

from bbconf import __version__ as bbconf_version
from bbconf.models.base_models import StatsReturn, FileStats
from bbconf.models.base_models import StatsReturn, FileStats, UsageStats
from fastapi import APIRouter, Request
from geniml import __version__ as geniml_version

Expand Down Expand Up @@ -46,11 +46,25 @@ async def get_bedbase_db_stats():
summary="Get detailed statistics for BEDbase platform, including number of files for each genome",
response_model=FileStats,
)
async def get_detailed_stats():
async def get_detailed_stats(
concise: bool = False,
):
"""
Returns detailed statistics
"""
return bbagent.get_detailed_stats()
return bbagent.get_detailed_stats(concise=concise)


@router.get(
"/detailed-usage",
summary="Get detailed usage statistics for BEDbase platform",
response_model=UsageStats,
)
async def get_detailed_usage():
"""
Returns detailed usage statistics
"""
return bbagent.get_detailed_usage()


@router.get(
Expand Down
2 changes: 1 addition & 1 deletion requirements/requirements-all.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# bbconf @ git+https://github.com/databio/bbconf.git@dev#egg=bbconf
bbconf>=0.11.2
bbconf>=0.11.3
fastapi>=0.103.0
logmuse>=0.2.7
markdown
Expand Down
42 changes: 28 additions & 14 deletions ui/bedbase-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ export interface paths {
* Create Bedset
* @description Create a new bedset by providing registry path to the PEPhub project
*/
post: operations["create_bedset_v1_bedset_create__post"];
post: operations["create_bedset_v1_bedset_create_post"];
delete?: never;
options?: never;
head?: never;
Expand Down Expand Up @@ -939,6 +939,11 @@ export interface components {
*/
license_id: string | null;
annotation?: components["schemas"]["StandardMeta"] | null;
/**
* Processed
* @default true
*/
processed: boolean | null;
stats?: components["schemas"]["BedStatsModel"] | null;
plots?: components["schemas"]["BedPlots"] | null;
files?: components["schemas"]["BedFiles"] | null;
Expand Down Expand Up @@ -1000,6 +1005,11 @@ export interface components {
*/
license_id: string | null;
annotation?: components["schemas"]["StandardMeta"] | null;
/**
* Processed
* @default true
*/
processed: boolean | null;
};
/** BedPEPHub */
BedPEPHub: {
Expand Down Expand Up @@ -1034,11 +1044,11 @@ export interface components {
*/
cell_line: string;
/**
* Exp Protocol
* Assay
* @description Experimental protocol (e.g. ChIP-seq)
* @default
*/
exp_protocol: string;
assay: string;
/**
* Library Source
* @description Library source (e.g. genomic, transcriptomic)
Expand Down Expand Up @@ -1129,11 +1139,11 @@ export interface components {
*/
cell_line: string;
/**
* Exp Protocol
* Assay
* @description Experimental protocol (e.g. ChIP-seq)
* @default
*/
exp_protocol: string;
assay: string;
/**
* Library Source
* @description Library source (e.g. genomic, transcriptomic)
Expand Down Expand Up @@ -1392,18 +1402,22 @@ export interface components {
};
/** FileStats */
FileStats: {
/** File Type */
file_type: {
/** Bed Compliance */
bed_compliance: {
[key: string]: number;
};
/** File Format */
file_format: {
/** Data Format */
data_format: {
[key: string]: number;
};
/** File Genome */
file_genome: {
[key: string]: number;
};
/** File Organism */
file_organism: {
[key: string]: number;
};
};
/** HTTPValidationError */
HTTPValidationError: {
Expand Down Expand Up @@ -1537,7 +1551,7 @@ export interface components {
*/
library_source: string;
/**
* Exp Protocol
* Assay
* @description Experimental protocol (e.g. ChIP-seq)
* @default
*/
Expand Down Expand Up @@ -1565,13 +1579,13 @@ export interface components {
* @description Global sample identifier. e.g. GSM000
* @default
*/
global_sample_id: string[];
global_sample_id: string[] | null;
/**
* Global Experiment Id
* @description Global experiment identifier. e.g. GSE000
* @default
*/
global_experiment_id: string[];
global_experiment_id: string[] | null;
/**
* Original File Name
* @description Original file name
Expand Down Expand Up @@ -1850,7 +1864,7 @@ export interface operations {
/** @description filter by genome of the bed file. e.g. 'hg38' */
genome?: string;
/** @description filter by bed type. e.g. 'bed6+4' */
bed_type?: string;
bed_compliance?: string;
};
header?: never;
path?: never;
Expand Down Expand Up @@ -2682,7 +2696,7 @@ export interface operations {
};
};
};
create_bedset_v1_bedset_create__post: {
create_bedset_v1_bedset_create_post: {
parameters: {
query?: never;
header?: never;
Expand Down
63 changes: 50 additions & 13 deletions ui/src/components/bed-splash-components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Fragment, useState } from 'react';
import { components } from '../../../bedbase-types';
import { useCopyToClipboard } from '@uidotdev/usehooks';
import { bytesToSize, formatDateTime } from '../../utils';
import { Dropdown, OverlayTrigger } from 'react-bootstrap';
import { Dropdown, OverlayTrigger, Tooltip } from 'react-bootstrap';
import { RefGenomeModal } from './refgenome-modal';

const API_BASE = import.meta.env.VITE_API_BASE || '';
Expand Down Expand Up @@ -51,14 +51,34 @@ export const BedSplashHeader = (props: Props) => {
</button>
</h4>
</div>
{!metadata?.processed && (
<p
className="text-warning text-nowrap me-1 btn btn-outline btn-sm transparent-btn"
>
<OverlayTrigger
placement="top"
overlay={
<Tooltip id="tooltip-top">
This file has not been processed by the BedBoss pipeline yet.
</Tooltip>
}
>
<span>
<i className="bi bi-exclamation-triangle-fill me-1"></i>
Not Processed
</span>
</OverlayTrigger>
</p>
)}

<div className="d-flex flex-col align-items-center gap-1 flex-shrink-0">
<a href={`${API_BASE}/bed/${record_identifier}/metadata?full=true`}>
<button className="btn btn-outline-primary btn-sm">
<i className="bi bi-info-circle me-1"/>
<i className="bi bi-info-circle me-1" />
API
</button>
</a>
{!addedToCart && cart.includes(record_identifier || '') ? (
{!addedToCart && cart[record_identifier || ''] ? (
<button
className="btn btn-outline-danger btn-sm"
onClick={() => {
Expand All @@ -79,21 +99,34 @@ export const BedSplashHeader = (props: Props) => {
disabled={addedToCart}
className="btn btn-primary btn-sm"
onClick={() => {
if (record_identifier == undefined) {
if (record_identifier == undefined || metadata === undefined) {
toast.error(
'This bed file does not have a record identifier... please contact the administrator to fix this issue.',
);
return;
}
addBedToCart(record_identifier);

// Create the bed item object with all required fields
const bedItem = {
id: record_identifier,
name: metadata.name || 'No name',
genome: metadata.genome_alias || 'N/A',
tissue: metadata.annotation?.tissue || 'N/A',
cell_line: metadata.annotation?.cell_line || 'N/A',
cell_type: metadata.annotation?.cell_type || 'N/A',
description: metadata.description || '',
assay: metadata.annotation?.assay || 'N/A',
};

addBedToCart(bedItem);
setAddedToCart(true);
setTimeout(() => {
setAddedToCart(false);
}, 500);
}}
>
<i className="bi bi-cart-fill me-1" />
{addedToCart ? 'Added to cart!' : 'Add to cart'}
{addedToCart ? 'Adding...' : 'Add to cart'}
</button>
)}
<Dropdown>
Expand All @@ -104,11 +137,11 @@ export const BedSplashHeader = (props: Props) => {
{
// If there are no files to download, disable the dropdown
noFilesToDownload ? (
<Dropdown.Menu className='border border-light-subtle shadow-sm'>
<Dropdown.Menu className="border border-light-subtle shadow-sm">
<Dropdown.Item disabled>There are no files to download</Dropdown.Item>
</Dropdown.Menu>
) : (
<Dropdown.Menu className='border border-light-subtle shadow-sm'>
<Dropdown.Menu className="border border-light-subtle shadow-sm">
{metadata.files?.bed_file && (
<Fragment>
{(metadata.files?.bed_file?.access_methods || []).map((method) => {
Expand Down Expand Up @@ -149,7 +182,8 @@ export const BedSplashHeader = (props: Props) => {
<h5 className="fw-semibold mb-1">{metadata.name}</h5>
<p className="text-body-secondary fst-italic">{metadata?.description || 'No description available'}</p>
</div>
<div className="d-flex flex-column flex-xl-row align-items-start align-items-xl-end justify-content-xl-between mt-2 overflow-x-auto">
<div
className="d-flex flex-column flex-xl-row align-items-start align-items-xl-end justify-content-xl-between mt-2 overflow-x-auto">
<div className="d-md-flex flex-row gap-1 text-lg mb-2 mb-xl-0">
<div className="d-flex flex-row">
<div className="mb-0">
Expand All @@ -164,8 +198,10 @@ export const BedSplashHeader = (props: Props) => {
>
{metadata?.genome_digest ? (
<>
<a href={`http://refgenomes.databio.org/v3/genomes/splash/${metadata.genome_digest}`} target="_blank">
<div className={genomeStats?.compared_genome ? "badge bg-primary rounded-end-0" : "badge bg-primary"}>
<a href={`http://refgenomes.databio.org/v3/genomes/splash/${metadata.genome_digest}`}
target="_blank">
<div
className={genomeStats?.compared_genome ? 'badge bg-primary rounded-end-0' : 'badge bg-primary'}>
<i className="bi bi-database-fill me-2" />
{metadata.genome_alias || 'No assembly available'}
</div>
Expand All @@ -190,7 +226,7 @@ export const BedSplashHeader = (props: Props) => {
</div>
}
>
<div
<div
className="badge bg-primary border-start border-light rounded-start-0"
role="button"
onClick={() => {
Expand Down Expand Up @@ -285,7 +321,8 @@ export const BedSplashHeader = (props: Props) => {
</div>
)}
</div>
<div className="d-flex flex-column flex-md-row justify-content-xl-between align-items-start align-items-xl-end text-sm">
<div
className="d-flex flex-column flex-md-row justify-content-xl-between align-items-start align-items-xl-end text-sm">
<div className="d-flex flex-row text-muted">
<i className="bi bi-calendar4-event me-1" />
<p className="mb-0">
Expand Down
Loading