Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3ac8ab0
Migrate frontend package manager from npm to pnpm
inodb Jun 19, 2026
73a3380
Add annotation overlay for the OncoTree
inodb Jun 19, 2026
dfdf643
Pin ts-jest compile target so tests pass under pnpm
inodb Jun 19, 2026
d9e5503
Preserve node OncoTree color in annotation overlay
inodb Jun 19, 2026
8395663
Accept raw JSON in the ?annotations= URL parameter
inodb Jun 19, 2026
b8497e5
Roll up descendant annotations on collapsed nodes
inodb Jun 19, 2026
1381b08
Drop the Σ prefix on aggregated badges
inodb Jun 19, 2026
3fbf5e1
Prefill the annotation editor with URL-loaded annotations
inodb Jun 19, 2026
fa61ed5
Add postMessage embed API for annotations
inodb Jun 19, 2026
4cfca25
Make the frontend deployable as a static demo
inodb Jun 19, 2026
de0cfc1
Add parent-driven search to the embed API
inodb Jun 19, 2026
638022b
Keep build artifacts pristine after deploy build
inodb Jun 19, 2026
1ea7711
Bundle an API snapshot into the static demo
inodb Jun 19, 2026
7c407c1
Add ?embed mode to hide header/footer
inodb Jun 19, 2026
a161e1e
Hide the annotation panel in embed mode
inodb Jun 19, 2026
ac7b33e
Clearer annotation badges and a unified node tooltip
inodb Jun 19, 2026
9f35999
Clarify own value vs subtree total in the tooltip
inodb Jun 19, 2026
705fc7f
Clearer tree toolbar with a full-screen button
inodb Jun 21, 2026
213e6d3
Tree-shaped expand/collapse icons and fix fullscreen background
inodb Jun 21, 2026
e15367a
Handle blocked fullscreen in iframes gracefully
inodb Jun 21, 2026
1f37e3c
Make nodes and badges clearly interactive
inodb Jun 21, 2026
140b91a
Emit oncotree-node-click when a leaf annotation badge is clicked
inodb Jun 22, 2026
c5e0487
Mark host-selected codes with a checkmark on the tree
inodb Jun 22, 2026
8fc1669
Separate select (badge) from expand (name/dot); 3-way badge state
inodb Jun 22, 2026
71adf83
Let a parent badge select/deselect its whole branch when expanded too
inodb Jun 22, 2026
96e8b10
Hide the misaligned tooltip caret
inodb Jun 22, 2026
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: 8 additions & 3 deletions .github/workflows/eslint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v2
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 20.12.2
cache: pnpm
cache-dependency-path: web/src/main/javascript/pnpm-lock.yaml
- name: Install node modules
run: npm install
run: pnpm install --frozen-lockfile
- name: Run ESLint
run: npm run lint
run: pnpm run lint
13 changes: 9 additions & 4 deletions .github/workflows/github-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ jobs:
working-directory: web/src/main/javascript
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v2
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 20.12.2
cache: pnpm
cache-dependency-path: web/src/main/javascript/pnpm-lock.yaml
- name: Install node modules
run: npm install
run: pnpm install --frozen-lockfile
- name: Build frontend
run: npm run build
run: pnpm run build
- name: Run unit tests
run: npm test
run: pnpm test
9 changes: 5 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
FROM node:20.12.2-alpine AS frontend-builder
RUN corepack enable
WORKDIR /app/frontend
COPY web/src/main/javascript/package*.json ./
RUN npm config set fetch-timeout 600000
RUN npm ci
COPY web/src/main/javascript/package.json web/src/main/javascript/pnpm-lock.yaml ./
RUN pnpm config set fetch-timeout 600000
RUN pnpm install --frozen-lockfile
COPY web/src/main/javascript/ ./
RUN npm run build
RUN pnpm run build

FROM golang:1.24.5-alpine AS backend-builder
RUN apk add --no-cache git openssh-client
Expand Down
66 changes: 63 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,78 @@ Read about our latest developments on our [News page](/docs/News.md).

Users may submit their OncoTree related questions to the [OncoTree Users Google Group](https://groups.google.com/forum/#!forum/oncotree-users).

## Annotation overlay

The tree can be overlaid with custom annotations that map OncoTree codes to
values. Each annotation may be a number, a text label, a gene list, or an
object combining them, e.g.:

```json
{
"LUAD": { "label": "1204 samples", "value": 1204 },
"GB": { "genes": ["EGFR", "PTEN", "TP53"] }
}
```

Each annotated node gets a small badge showing its value or gene count;
hovering the node adds the full detail (value, gene list) to the node's
tooltip. Collapsing a node rolls up its hidden descendants — values are summed
and gene lists unioned.

Annotations can be supplied four ways:

1. **Paste or upload** JSON/CSV in the *Annotations* panel.
2. **URL parameter** — `?annotations=<json>` where the value is raw
(URL-encoded) JSON or base64-encoded JSON (the panel's "Copy share link"
button produces the base64 form).
3. **Embed via `postMessage`** — add `?embed` to the URL to hide the site
header and footer (leaving just the tree), then drive it from the host. Add
`allow="fullscreen"` to the `<iframe>` if you want the full-screen button to
work (browsers block fullscreen from an iframe otherwise):

```html
<iframe src="https://…/?embed=1" allow="fullscreen"></iframe>
```

When the app runs in an `<iframe>` it posts `{ type: "oncotree-ready" }` to
its parent; the parent then pushes annotations:

```js
iframe.contentWindow.postMessage(
{ type: "oncotree-annotations", annotations: { LUAD: 1204 } },
"*",
);
```

The `annotations` payload may be an object, a JSON string, or `null` to
clear.

The parent can also drive the search, filtering the tree to the matching
node(s) (by code, name, or annotation content — gene/label/value):

```js
iframe.contentWindow.postMessage(
{ type: "oncotree-search", query: "EGFR" },
"*",
);
```

Send an empty `query` (or `{ clear: true }`) to reset. The app posts back
`{ type: "oncotree-search-result", query, count }` with the number of
matches.

## Frontend Development

All of the frontend code can be found at [/web/src/main/javascript](/web/src/main/javascript). The only configuration needed is to set `ONCOTREE_BASE_URL`
in [constants.ts](/web/src/main/javascript/src/shared/constants.ts). During development, it may be easiest to simply point to the public instance of
[OncoTree](https://oncotree.mskcc.org).

Make sure you are using node version >=20.12.2.
Make sure you are using node version >=20.12.2. The frontend uses [pnpm](https://pnpm.io/) as its package manager (enable it with `corepack enable`).

To begin development run:
```
cd ./web/src/main/javascript
npm install && npm run dev
pnpm install && pnpm run dev
```

## Building the Frontend
Expand All @@ -36,7 +96,7 @@ The frontend must be transpiled to static assets before bundling into a jar. To

```
cd ./web/src/main/javascript
npm install && npm run build
pnpm install && pnpm run build
```
3. The frontend assets are now up to date, and you are ready to bundle the jar.

Expand Down
66 changes: 66 additions & 0 deletions scripts/deploy-gh-pages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env bash
#
# Build the frontend as a static demo and publish it to the gh-pages branch of a
# fork, served at https://<user>.github.io/<repo>/.
#
# The demo is fully self-contained: a snapshot of the OncoTree API is fetched at
# build time and served alongside the app (same origin), so the running page
# never makes a cross-origin request. This avoids CORS / Private Network Access
# blocks when the page is embedded elsewhere. Configure via env vars:
#
# DEPLOY_REMOTE git remote/URL to push to (default: inodb)
# DEPLOY_BASE base path the site is served at (default: /oncotree/)
# ONCOTREE_API OncoTree API to snapshot at build time(default: https://oncotree.mskcc.org)
# TREE_VERSION tree version to snapshot (default: oncotree_latest_stable)
#
# Usage: scripts/deploy-gh-pages.sh
set -euo pipefail

DEPLOY_REMOTE="${DEPLOY_REMOTE:-inodb}"
DEPLOY_BASE="${DEPLOY_BASE:-/oncotree/}"
ONCOTREE_API="${ONCOTREE_API:-https://oncotree.mskcc.org}"
TREE_VERSION="${TREE_VERSION:-oncotree_latest_stable}"

# The app fetches `${API_BASE}/api/...`; point it at the deploy's own subpath so
# requests resolve to the snapshot files staged below (same origin as the app).
API_BASE="${DEPLOY_BASE%/}"

repo_root="$(git rev-parse --show-toplevel)"
js_dir="$repo_root/web/src/main/javascript"
static_dir="$repo_root/web/src/main/resources/static"
stage_dir="$(mktemp -d)"
trap 'rm -rf "$stage_dir"' EXIT

echo "Building static demo (base=$DEPLOY_BASE, apiBase=$API_BASE)..."
cd "$js_dir"
DEPLOY_BASE="$DEPLOY_BASE" VITE_ONCOTREE_BASE_URL="$API_BASE" pnpm run build

echo "Staging build output..."
cp -r "$static_dir/." "$stage_dir/"
cp "$stage_dir/index.html" "$stage_dir/404.html" # SPA fallback for client routing
touch "$stage_dir/.nojekyll"

# The demo build (subpath base) overwrites the repo's committed build artifacts;
# restore them so the working tree stays clean.
git -C "$repo_root" checkout -- \
web/src/main/resources/static web/src/main/javascript/public 2>/dev/null || true

echo "Snapshotting API from $ONCOTREE_API ..."
mkdir -p "$stage_dir/api/tumorTypes"
# GitHub Pages ignores the query string and serves these files for the app's
# `/api/versions` and `/api/tumorTypes/tree?version=...` requests.
curl -fsSL "$ONCOTREE_API/api/versions" -o "$stage_dir/api/versions"
curl -fsSL "$ONCOTREE_API/api/tumorTypes/tree?version=$TREE_VERSION" \
-o "$stage_dir/api/tumorTypes/tree"

remote_url="$(git -C "$repo_root" remote get-url "$DEPLOY_REMOTE")"
echo "Publishing to $remote_url (gh-pages)..."
cd "$stage_dir"
git init -q
git checkout -q -b gh-pages
git add -A
git commit -q -m "Deploy oncotree annotation overlay demo"
git push -f "$remote_url" gh-pages

echo "Done. Enable Pages once with:"
echo " gh api -X POST repos/<owner>/<repo>/pages -f source.branch=gh-pages -f source.path=/"
2 changes: 1 addition & 1 deletion web/src/main/javascript/.husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
npx lint-staged
pnpm exec lint-staged
2 changes: 1 addition & 1 deletion web/src/main/javascript/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Running locally

```bash
npm run dev
pnpm run dev
```

# React + TypeScript + Vite
Expand Down
5 changes: 4 additions & 1 deletion web/src/main/javascript/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
export default {
testEnvironment: "jsdom",
transform: {
"^.+.tsx?$": ["ts-jest", {}],
"^.+.tsx?$": [
"ts-jest",
{ tsconfig: { target: "ES2020", lib: ["ES2020", "DOM"] } },
],
},
};

Loading
Loading