Skip to content

Commit

Permalink
refactor: separate app and gui
Browse files Browse the repository at this point in the history
the gui will allow embedding
  • Loading branch information
tuner committed Oct 2, 2024
1 parent 8faa427 commit 098fc26
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 46 deletions.
22 changes: 2 additions & 20 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,8 @@

<body>
<h1 id="title">Jellyfish Plotter</h1>
<div class="jellyfish-gui">
<div class="jellyfish-plot-container">
<div class="jellyfish-plot"></div>
</div>
<div class="jellyfish-patient-nav" style="display: none">
<button class="jellyfish-prev-patient">
<svg viewBox="0 0 8 16" fill="currentColor">
<polygon points="8,0 0,8 8,16" />
</svg>
<span>Previous</span>
</button>
<button class="jellyfish-next-patient">
<span>Next</span>
<svg viewBox="0 0 8 16" fill="currentColor">
<polygon points="0,0 8,8 0,16" />
</svg>
</button>
</div>
</div>
<script type="module" src="/src/gui/index.ts"></script>
<div id="app"></div>
<script type="module" src="/src/gui/app.ts"></script>
</body>

</html>
25 changes: 25 additions & 0 deletions src/gui/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { DataTables, loadDataTables } from "../data.js";
import { escapeHtml } from "../utils.js";
import { setupGui } from "./gui.js";

export default async function main() {
const appElement = document.getElementById("app");

let tables: DataTables;
try {
tables = await loadDataTables();
} catch (e) {
showError(appElement, (e as Error).message);
throw e;
}

setupGui(appElement, tables);
}

function showError(container: HTMLElement, message: string) {
container.innerHTML = `<div class="jellyfish-error-message">${escapeHtml(
message
)}</div>`;
}

main();
69 changes: 43 additions & 26 deletions src/gui/index.ts → src/gui/gui.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import GUI, { Controller } from "lil-gui";
import {
DataTables,
filterDataTablesByPatient,
loadDataTables,
} from "../data.js";
import { DataTables, filterDataTablesByPatient } from "../data.js";
import { tablesToJellyfish } from "../jellyfish.js";
import {
CostWeights,
Expand All @@ -13,6 +9,7 @@ import {
import { addInteractions } from "../interactions.js";
import { downloadSvg, downloadPng } from "./download.js";
import { DEFAULT_BELL_PLOT_PROPERTIES } from "../bellplot.js";
import { escapeHtml } from "../utils.js";

interface GeneralProperties {
patient: string | null;
Expand Down Expand Up @@ -41,22 +38,15 @@ const DEFAULT_LAYOUT_PROPERTIES = {
...DEFAULT_BELL_PLOT_PROPERTIES,
} as LayoutProperties;

export default async function main() {
const jellyfishGui = document.querySelector(".jellyfish-gui") as HTMLElement;
export function setupGui(container: HTMLElement, tables: DataTables) {
container.innerHTML = HTML_TEMPLATE;
const jellyfishGui = container.querySelector(".jellyfish-gui") as HTMLElement;

const { generalProps, layoutProps, costWeights } =
getSavedOrDefaultSettings();
const saveSettings = () =>
saveSettingsToSessionStorage(generalProps, layoutProps, costWeights);

let tables: DataTables;
try {
tables = await loadDataTables();
} catch (e) {
showError(jellyfishGui, (e as Error).message);
throw e;
}

const patients = Array.from(new Set(tables.samples.map((d) => d.patient)));
generalProps.patient ??= patients[0];

Expand Down Expand Up @@ -163,10 +153,12 @@ function updatePlot(
}
}

function showError(jellyfishGui: HTMLElement, message: string) {
jellyfishGui.querySelector(
function showError(container: HTMLElement, message: string) {
container.querySelector(
".jellyfish-plot"
).innerHTML = `<div class="jellyfish-error-message">${message}</div>`;
).innerHTML = `<div class="jellyfish-error-message">${escapeHtml(
message
)}</div>`;
}

const STORAGE_KEY = "jellyfish-plotter-settings";
Expand Down Expand Up @@ -224,13 +216,18 @@ function setupPatientNavigation(
.querySelector(".jellyfish-next-patient")
.addEventListener("click", () => navigate(1));

document.addEventListener("keydown", (event) => {
if (event.key === "ArrowLeft") {
navigate(-1);
} else if (event.key === "ArrowRight") {
navigate(1);
}
});
// If used in the standalone mode, enable keyboard navigation.
// Otherwise, like when multiple instances are embedded in a page,
// we don't want to interfere with the page's keyboard navigation.
if (jellyfishGui?.parentElement.id === "app") {
document.addEventListener("keydown", (event) => {
if (event.key === "ArrowLeft") {
navigate(-1);
} else if (event.key === "ArrowRight") {
navigate(1);
}
});
}
}

function makePatientNavigator(
Expand All @@ -255,4 +252,24 @@ function makePatientNavigator(
};
}

main();
const HTML_TEMPLATE = `
<div class="jellyfish-gui">
<div class="jellyfish-plot-container">
<div class="jellyfish-plot"></div>
</div>
<div class="jellyfish-patient-nav" style="display: none">
<button class="jellyfish-prev-patient">
<svg viewBox="0 0 8 16" fill="currentColor">
<polygon points="8,0 0,8 8,16" />
</svg>
<span>Previous</span>
</button>
<button class="jellyfish-next-patient">
<span>Next</span>
<svg viewBox="0 0 8 16" fill="currentColor">
<polygon points="0,0 8,8 0,16" />
</svg>
</button>
</div>
</div>
`;
4 changes: 4 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ export function mapUnion<K, V>(...maps: Array<Map<K, V>>): Map<K, V> {
}
return union;
}

export function escapeHtml(unsafe: string) {
return unsafe.replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

0 comments on commit 098fc26

Please sign in to comment.