From afe628ea42a6c64118f6fb4d7d96b7a5070ce1c5 Mon Sep 17 00:00:00 2001 From: Theo Sanderson Date: Sat, 26 Oct 2024 15:28:11 +0100 Subject: [PATCH] Move from subdomains for special hosted builds to just URLs (#627) --- taxonium_website/src/App.jsx | 179 ++++++++++++-------------------- taxonium_website/src/trees.json | 36 +++++++ taxonium_website/vercel.json | 16 +++ 3 files changed, 118 insertions(+), 113 deletions(-) create mode 100644 taxonium_website/src/trees.json create mode 100644 taxonium_website/vercel.json diff --git a/taxonium_website/src/App.jsx b/taxonium_website/src/App.jsx index a283b052..bfd15c49 100644 --- a/taxonium_website/src/App.jsx +++ b/taxonium_website/src/App.jsx @@ -1,60 +1,77 @@ import React, { useState, Suspense, useRef, useEffect } from "react"; import AboutOverlay from "./components/AboutOverlay"; import TaxoniumBit from "./components/TaxoniumBit"; - import { CgListTree } from "react-icons/cg"; import { BsInfoSquare } from "react-icons/bs"; import { FaGithub } from "react-icons/fa"; +import { HiOutlineBookOpen } from "react-icons/hi"; import useQueryAsState from "./hooks/useQueryAsState"; import classNames from "classnames"; import { useInputHelper } from "./hooks/useInputHelper"; - import InputSupplier from "./components/InputSupplier"; +import treeConfig from "./trees.json"; -import { HiOutlineBookOpen } from "react-icons/hi"; - -const default_query = {}; +// Hardcoded list of paths to show in the showcase +const SHOWCASE_PATHS = [ + "sars-cov-2/public", + "taxonomy/visual", + "taxonomy/full", + "mpox/public", +]; -default_query.backend = null; -if (window.location.hostname.includes("viridian.taxonium.org")) { - default_query.backend = "https://viridian-api.cov2tree.org"; -} -if (window.location.hostname.includes("cov2tree.org")) { - default_query.backend = "https://api.cov2tree.org"; -} +function checkLegacyHostname() { + const currentHostname = window.location.hostname; -if (window.location.hostname.includes("mpx.taxonium.org")) { - default_query.protoUrl = "https://mpx-tree.vercel.app/mpx.jsonl.gz"; - default_query.configUrl = "https://mpx-tree.vercel.app/config.json"; -} + // Look through all configurations for matching legacy hostnames + for (const [path, config] of Object.entries(treeConfig)) { + if ( + config.legacyHostnames && + config.legacyHostnames.includes(currentHostname) + ) { + // If we find a match, redirect to the new path + // Preserve any query parameters + const newPath = `${window.location.protocol}//${window.location.host}/${path}${window.location.search}`; -if (window.location.hostname.includes("taxonomy.taxonium.org")) { - default_query.treeUrl = - "https://cov2tree.nyc3.digitaloceanspaces.com/ncbi/tree.nwk.gz"; + // Only redirect if we're not already on the correct path + if (!window.location.pathname.startsWith(`/${path}`)) { + window.location.href = newPath; + return true; + } + } + } - default_query.metaUrl = - "https://cov2tree.nyc3.digitaloceanspaces.com/ncbi/metadata.tsv.gz"; + return false; +} - default_query.configUrl = - "https://cov2tree.nyc3.digitaloceanspaces.com/ncbi/config.json"; +function getConfigFromPath() { + // First check for legacy hostname redirects + if (checkLegacyHostname()) { + return null; // Return null as we're about to redirect + } - default_query.ladderizeTree = "true"; -} + // Remove leading slash and get full path + const path = window.location.pathname.substring(1); -if (window.location.hostname.includes("visualtreeoflife.taxonium.org")) { - default_query.protoUrl = - "https://cov2tree.nyc3.digitaloceanspaces.com/wikidata/out.jsonl.gz"; + // Return the configuration for this path, if it exists + return treeConfig[path] || null; } function App() { useEffect(() => { import("taxonium-component"); }, []); - const [uploadedData, setUploadedData] = useState(null); - // check if .epicov.org is in the URL + const pathConfig = getConfigFromPath(); + const default_query = pathConfig || {}; + const [uploadedData, setUploadedData] = useState(null); const [query, updateQuery] = useQueryAsState(default_query); + const [title, setTitle] = useState(null); + const [beingDragged, setBeingDragged] = useState(false); + const [aboutEnabled, setAboutEnabled] = useState(false); + const [overlayContent, setOverlayContent] = useState(null); + + const dragTimeout = useRef(null); const inputHelper = useInputHelper({ setUploadedData, @@ -62,29 +79,20 @@ function App() { query, uploadedData, }); - const [title, setTitle] = useState(null); - const [beingDragged, setBeingDragged] = useState(false); - - const dragTimeout = useRef(null); function onDrop(ev) { console.log("File(s) dropped"); setBeingDragged(false); - - // Prevent default behavior (Prevent file from being opened) ev.preventDefault(); if (ev.dataTransfer.items) { - // Use DataTransferItemList interface to access the file(s) for (var i = 0; i < ev.dataTransfer.items.length; i++) { - // If dropped items aren't files, reject them if (ev.dataTransfer.items[i].kind === "file") { var file = ev.dataTransfer.items[i].getAsFile(); inputHelper.readFile(file); } } } else { - // Use DataTransfer interface to access the file(s) inputHelper.readFile(ev.dataTransfer.files[0]); } } @@ -97,18 +105,14 @@ function App() { ev.preventDefault(); return; } - console.log("File(s) in drop zone"); setBeingDragged(true); if (dragTimeout.current) { clearTimeout(dragTimeout.current); } - - // Prevent default behavior (Prevent file from being opened) ev.preventDefault(); } function onDragLeave(ev) { - //debounce: if (dragTimeout.current) { clearTimeout(dragTimeout.current); } @@ -117,62 +121,19 @@ function App() { }, 500); } - const [aboutEnabled, setAboutEnabled] = useState(false); - - const protoUrl = query.protoUrl; - if (protoUrl && protoUrl.includes(".pb")) { - const url_parts = window.location.href.split("?", 2); - if (url_parts[1]) { - console.log(url_parts, "parts"); - // V1 format - if (!window.redirecting) { - window.alert( - "It looks like you are trying to load a Taxonium V1 proto. We will now redirect you to the V1 site. " - ); - } - window.redirecting = 1; - // split url into before question mark and after - - window.location.href = - "https://cov2tree-git-v1-theosanderson.vercel.app/?" + url_parts[1]; - } else { - if (!window.redirecting) { - window.alert( - "It looks like you are trying to load a Taxonium V1 proto. We will now redirect you to the V1 site. " - ); - } - window.redirecting = 1; - window.location.href = - "https://cov2tree-git-v1-theosanderson.vercel.app/?protoUrl=" + - protoUrl; + // Generate showcase items from hardcoded list + const showCase = SHOWCASE_PATHS.map((path) => { + const config = treeConfig[path]; + if (!config) { + console.warn(`No configuration found for showcase path: ${path}`); + return null; } - } - const [overlayContent, setOverlayContent] = useState(null); - // does the window location contain epicov anywhere - const isGisaid = window.location.toString().includes("epicov.org"); - - const showCase = [ - { - title: "SARS-CoV-2", - url: "/?backend=https://api.cov2tree.org", - desc: "All seven million public sequences of SARS-CoV-2 from the INSDC databases", - }, - { - title: "Wikidata visual tree of life", - url: "/?configUrl=https%3A%2F%2Fcov2tree.nyc3.digitaloceanspaces.com%2Fncbi%2Fconfig_special2.json&protoUrl=https%3A%2F%2Fcov2tree.nyc3.cdn.digitaloceanspaces.com%2Fncbi%2Fspecial_filtered.jsonl.gz&xType=x_dist", - desc: "The tree of life, showing species from Wikidata with images. Links to Wikipedia.", - }, - { - title: "NCBI Taxonomy (full)", - url: "https://taxonomy.taxonium.org", - desc: "Full 2.2M NCBI Taxonomy of species", - }, - { - title: "Mpox", - url: "https://mpx.taxonium.org", - desc: "Mpox sequences from GenBank", - }, - ]; + return { + title: config.title, + url: `/${path}`, + desc: config.description, + }; + }).filter(Boolean); // Remove any null entries from missing configs return ( <> @@ -195,7 +156,7 @@ function App() { className={classNames( "from-gray-500 to-gray-600 bg-gradient-to-bl shadow-md", "flex justify-between items-center px-4 flex-shrink-0", - isGisaid ? "h-11" : "h-16" + "h-16" )} >

@@ -203,12 +164,11 @@ function App() { <> {window.screen.width < 600 && ( <> - {" "} {title} visualised with @@ -225,7 +185,7 @@ function App() { visualised with @@ -236,17 +196,13 @@ function App() { )} ) : ( - + Taxonium )}

-
+
@@ -287,7 +243,6 @@ function App() {

- {/* Horizontal separator and text "or load an existing tree:"*/}
@@ -295,7 +250,6 @@ function App() {
- {/* Showcases */}
{showCase.map((item, i) => (
@@ -311,14 +265,13 @@ function App() { ))}
- {/* documentation link, centered with react-icons*/}
- + Read the Taxonium documentation
diff --git a/taxonium_website/src/trees.json b/taxonium_website/src/trees.json new file mode 100644 index 00000000..431021bd --- /dev/null +++ b/taxonium_website/src/trees.json @@ -0,0 +1,36 @@ +{ + "sars-cov-2/public": { + "backend": "https://api.cov2tree.org", + "title": "SARS-CoV-2", + "description": "All seven million public sequences of SARS-CoV-2 from the INSDC databases", + "legacyHostnames": ["cov2tree.org"] + }, + "sars-cov-2/viridian": { + "backend": "https://viridian-api.cov2tree.org", + "title": "SARS-CoV-2 Viridian", + "description": "SARS-CoV-2 sequences processed through Viridian pipeline", + "legacyHostnames": ["viridian.taxonium.org"] + }, + "mpox/public": { + "protoUrl": "https://mpx-tree.vercel.app/mpx.jsonl.gz", + "configUrl": "https://mpx-tree.vercel.app/config.json", + "title": "Mpox", + "description": "Mpox sequences from GenBank", + "legacyHostnames": ["mpx.taxonium.org"] + }, + "taxonomy/full": { + "treeUrl": "https://cov2tree.nyc3.digitaloceanspaces.com/ncbi/tree.nwk.gz", + "metaUrl": "https://cov2tree.nyc3.digitaloceanspaces.com/ncbi/metadata.tsv.gz", + "configUrl": "https://cov2tree.nyc3.digitaloceanspaces.com/ncbi/config.json", + "ladderizeTree": true, + "title": "NCBI Taxonomy (full)", + "description": "Full 2.2M NCBI Taxonomy of species", + "legacyHostnames": ["taxonomy.taxonium.org"] + }, + "taxonomy/visual": { + "protoUrl": "https://cov2tree.nyc3.digitaloceanspaces.com/wikidata/out.jsonl.gz", + "title": "Wikidata visual tree of life", + "description": "The tree of life, showing species from Wikidata with images. Links to Wikipedia.", + "legacyHostnames": ["visualtreeoflife.taxonium.org"] + } +} diff --git a/taxonium_website/vercel.json b/taxonium_website/vercel.json new file mode 100644 index 00000000..5b1bb42c --- /dev/null +++ b/taxonium_website/vercel.json @@ -0,0 +1,16 @@ +{ + "routes": [ + { + "src": "/assets/(.*)", + "dest": "/assets/$1" + }, + { + "src": "/(.*)", + "dest": "/index.html" + }, + { + "src": "/favicon.ico", + "dest": "/favicon.ico" + } + ] +}