From 86b10b3598741648ecc8d1b9b262a716f978f1f4 Mon Sep 17 00:00:00 2001 From: Vincent Rubinetti Date: Thu, 30 Jul 2026 11:58:05 -0400 Subject: [PATCH 1/8] add more info to cart --- frontend/src/api/api.ts | 8 ++++---- frontend/src/api/types.ts | 2 ++ frontend/src/pages/Cart.tsx | 21 ++++++++++++++------- frontend/src/pages/Studies.tsx | 20 ++++++++++++++------ frontend/src/state/cart.ts | 7 +++++-- 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/frontend/src/api/api.ts b/frontend/src/api/api.ts index 72f070a..508bdd1 100644 --- a/frontend/src/api/api.ts +++ b/frontend/src/api/api.ts @@ -1,5 +1,5 @@ import type { Feedback } from "@/api/types"; -import type { ShareCart } from "@/state/cart"; +import type { LocalCart, ShareCart } from "@/state/cart"; import analytics from "react-ga4"; import z from "zod"; import { api, request } from "@/api"; @@ -122,7 +122,7 @@ export const shareCart = async (shareCart: ShareCart) => { /** download cart data */ export const downloadCart = async ( - ids: string[], + localCart: LocalCart, filename: string, type: string, ) => { @@ -132,10 +132,10 @@ export const downloadCart = async ( const options = { method: "POST", headers: { "Content-Type": "application/json" }, - body: { ids }, + body: { localCart }, parse: "blob", } as const; - analytics.event("download_cart", { ids, filename, type }); + analytics.event("download_cart", { localCart, filename, type }); const data = await request(url, z.instanceof(Blob), options); if (type === "csv") downloadBlob(data, filename, "csv"); if (type === "json") downloadBlob(data, filename, "json"); diff --git a/frontend/src/api/types.ts b/frontend/src/api/types.ts index 7c72d7d..c601926 100644 --- a/frontend/src/api/types.ts +++ b/frontend/src/api/types.ts @@ -101,6 +101,8 @@ export const cart = z.object({ z.object({ id: z.string(), added: z.string(), + search: z.string(), + term: z.string(), }), ), }); diff --git a/frontend/src/pages/Cart.tsx b/frontend/src/pages/Cart.tsx index 503484c..95e298a 100644 --- a/frontend/src/pages/Cart.tsx +++ b/frontend/src/pages/Cart.tsx @@ -264,7 +264,7 @@ export default function Cart() { <> - downloadCart(studyIds, name || "cart", "csv") + downloadCart(localCart, name || "cart", "csv") } > @@ -273,7 +273,7 @@ export default function Cart() { - downloadCart(studyIds, name || "cart", "json") + downloadCart(localCart, name || "cart", "json") } > @@ -409,9 +409,16 @@ export default function Cart() { key: "database", name: "Databases", render: (database) => - Object.keys(database).map((database, index) => ( - - )), + Object.entries(database).map( + ([database, { url, external_id }], index) => ( + + ), + ), }, { key: "added", @@ -487,7 +494,7 @@ export default function Cart() { + + - - downloadCart(localCart, name || "cart", "json") - } - > + } > @@ -436,12 +480,7 @@ export default function Cart() { ), }, ]} - rows={studyDetails.map((study) => ({ - ...study, - added: - localCart?.studies.find((s) => s.id === study.id) - ?.added ?? "2025-01-01T00:00:00.000Z", - }))} + rows={studyDetails} sort={ordering} onSort={setOrdering} page={offset} diff --git a/frontend/src/pages/Studies.tsx b/frontend/src/pages/Studies.tsx index 390aed2..161c955 100644 --- a/frontend/src/pages/Studies.tsx +++ b/frontend/src/pages/Studies.tsx @@ -124,7 +124,6 @@ export default function Studies() { debouncedParams.getAll(key), ]), ); - console.log(facets); /** exclude param keywords */ delete facets.ordering; delete facets.offset; diff --git a/frontend/src/util/download.ts b/frontend/src/util/download.ts index 20d91ee..eac48c8 100755 --- a/frontend/src/util/download.ts +++ b/frontend/src/util/download.ts @@ -41,10 +41,41 @@ const getUrl = ( data instanceof Blob ? data : new Blob([data], { type }), ); -/** download blob as file */ -export const downloadBlob = (data: Blob, filename: string, ext: string) => - download(getUrl(data), filename, ext); +/** download data as json file */ +export const downloadJson = (data: unknown, filename: string) => + download( + getUrl(JSON.stringify(data, null, 2), "application/json;charset=utf-8"), + filename, + "json", + ); -/** download string as text file */ -export const downloadTxt = (data: string, filename: string) => - download(getUrl(data, "text/plain;charset=utf-8"), filename, "txt"); +type Table = (string | number | boolean | null | undefined)[][]; + +/** assemble csv/tsv from arrays */ +const stringifyTable = (table: Table, delimiter = "\t") => + table + .map((row) => + row + .map((col) => (col === null || col === undefined ? "" : String(col))) + .join(delimiter), + ) + .join("\n"); + +/** download data as csv file */ +export const downloadCsv = (data: Table, filename: string) => + download( + getUrl(stringifyTable(data, ","), "text/csv;charset=utf-8"), + filename, + "csv", + ); + +/** download data as tsv file */ +export const downloadTsv = (data: Table, filename: string) => + download( + getUrl( + stringifyTable(data, "\t"), + "text/tab-separated-values;charset=utf-8", + ), + filename, + "tsv", + ); From d5592933b5e9c384560bb8f075dd79342f2b9180 Mon Sep 17 00:00:00 2001 From: Vincent Rubinetti Date: Fri, 7 Aug 2026 14:14:30 -0400 Subject: [PATCH 7/8] add database external ids to cart download --- frontend/src/pages/Cart.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/frontend/src/pages/Cart.tsx b/frontend/src/pages/Cart.tsx index 8626cd7..7c56ce4 100644 --- a/frontend/src/pages/Cart.tsx +++ b/frontend/src/pages/Cart.tsx @@ -7,7 +7,7 @@ import { useParams } from "react-router"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import clsx from "clsx"; import { useAtomValue } from "jotai"; -import { omit, sum } from "lodash"; +import { omit, sum, uniq } from "lodash"; import { ArrowRight, Braces, @@ -178,6 +178,12 @@ export default function Cart() { filename, ); + /** unique list of databases */ + const databases = uniq( + studyDetails.flatMap((study) => Object.keys(study.database)), + ); + + /** format data into table */ const table = [ [ "ID", @@ -187,10 +193,10 @@ export default function Cart() { "Description", "Sample Count", "Confidence", - "Databases", "Platform", "Organisms", "Classification", + ...databases, ], ...studyDetails.map((study) => [ study.id, @@ -200,12 +206,15 @@ export default function Cart() { study.description, study.sample_count, study.confidence.name, - Object.keys(study.database).join(", "), study.platform.join(", "), study.organisms.join(", "), study.classification, + ...databases.map( + (database) => study.database[database]?.external_id || "", + ), ]), ]; + if (type === "csv") downloadCsv(table, filename); if (type === "tsv") downloadTsv(table, filename); }; From 83709f6d0525586d71bb4de6b458d16533e941d3 Mon Sep 17 00:00:00 2001 From: Vincent Rubinetti Date: Fri, 7 Aug 2026 14:19:43 -0400 Subject: [PATCH 8/8] add check marks to dbs in cart download --- frontend/src/pages/Cart.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/Cart.tsx b/frontend/src/pages/Cart.tsx index 7c56ce4..ecb05fd 100644 --- a/frontend/src/pages/Cart.tsx +++ b/frontend/src/pages/Cart.tsx @@ -209,8 +209,13 @@ export default function Cart() { study.platform.join(", "), study.organisms.join(", "), study.classification, - ...databases.map( - (database) => study.database[database]?.external_id || "", + ...databases.map((database) => + [ + study.database[database] ? "✓" : "✗", + study.database[database]?.external_id || "", + ] + .filter(Boolean) + .join(" "), ), ]), ];