Files
dv3d/dicom-viewer/public/embedded-viewer-test.html
T

130 lines
5.6 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Embedded Viewer — Test Page</title>
<style>
html,body{height:100%;margin:0;font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial}
header{background:#111;color:#fff;padding:12px 20px}
header h1{margin:0;font-size:18px}
.page{display:flex;gap:20px;padding:20px}
.main{flex:1}
.sidebar{width:260px;background:#f6f6f6;padding:12px;border-radius:6px}
.dicom-viewer-root{width:100%;height:72vh;background:#222;color:#fff;border-radius:6px;overflow:hidden}
.controls{margin:12px 0}
.note{background:#eef;padding:10px;border-radius:4px}
</style>
</head>
<body>
<header>
<h1>Embedded Viewer Test</h1>
</header>
<div class="page">
<main class="main">
<p class="note">This page demonstrates the DICOM viewer embedded alongside other content.</p>
<div class="controls">
<button onclick="document.getElementById('main_viewer').scrollIntoView({behavior:'smooth'})">Scroll to viewer</button>
<button onclick="console.log('Example action')">Example action</button>
</div>
<div id="main_viewer" class="dicom-viewer-root" data-auto-cache-stack="false"></div>
<section style="margin-top:16px">
<h2>Related information</h2>
<p>Here you can place text, controls, or other UI components while the viewer stays mounted within the page layout.</p>
</section>
</main>
<aside class="sidebar">
<h3>Sidebar</h3>
<p>Extra controls, metadata, or notes can live here.</p>
<ul>
<li>Patient: Anonymous</li>
<li>Study: Demo stack</li>
<li>Notes: Test page</li>
</ul>
</aside>
</div>
<!-- Provide noop React Refresh preamble to avoid plugin-react runtime errors -->
<script>
window.$RefreshReg$ = window.$RefreshReg$ || function() {};
window.$RefreshSig$ = window.$RefreshSig$ || function() { return function(type) { return type; }; };
</script>
<script type="module" src="/src/main.tsx"></script>
<script>
// Reuse the same viewer state as the penra test for convenience
const state = {"grid":{"rows":1,"cols":3},"modes":["stack","stack","stack"],"stacks":[{"i":["wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_573_PN7j4gd.dcm","wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_580_kBgyDxS.dcm","wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_572_DYQisSg.dcm"]},{"i":["wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_588_tGfMjqb.dcm","wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_592_Js4efiI.dcm","wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_584_U8WCsNY.dcm"]},{"i":["wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_631_NxRBhMn.dcm","wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_619_2cVhUyC.dcm","wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_607_VvL52Af.dcm"]}],"stackIdx":[0,2,1],"stackPos":[0,0,2],"props":[{"voiRange":{"lower":39.15,"upper":559.17},"invert":false,"interpolationType":1,"VOILUTFunction":"LINEAR","colormap":{"name":"Grayscale","opacity":[]}}],"cam":[null,null,null],"orientations":[null,null,null],"volumeSliceIndices":[null,null,null]};
function callWhenReady(fnName, payload) {
const maxWait = 5000;
const start = Date.now();
(function check() {
if (window[fnName] && typeof window[fnName] === 'function') {
try {
window[fnName](payload);
console.log('imported viewer state via', fnName);
} catch (e) {
console.error('importViewerState call failed', e);
}
return;
}
if (Date.now() - start > maxWait) {
console.warn('Timed out waiting for', fnName);
return;
}
setTimeout(check, 2000);
})();
}
document.addEventListener('DOMContentLoaded', () => {
(function loadStacksThenImport() {
if (!state.stacks || !Array.isArray(state.stacks)) {
callWhenReady('importViewerState_main_viewer', state);
return;
}
function pushStacks() {
const fnName = 'loadAdditionalStack_main_viewer';
if (window[fnName] && typeof window[fnName] === 'function') {
try {
state.stacks.forEach(s => {
if (s && Array.isArray(s.i) && s.i.length) {
window[fnName](s.i);
}
});
console.log('Requested viewer to load', state.stacks.length, 'stacks');
} catch (e) {
console.warn('loadAdditionalStack call failed', e);
}
setTimeout(() => { callWhenReady('importViewerState_main_viewer', state); }, 2000);
return true;
}
return false;
}
const started = pushStacks();
if (!started) {
const maxWait = 5000;
const start = Date.now();
(function waitForApi() {
if (pushStacks()) return;
if (Date.now() - start > maxWait) {
console.warn('Timed out waiting for loadAdditionalStack API; importing state directly');
callWhenReady('importViewerState_main_viewer', state);
return;
}
setTimeout(waitForApi, 2000);
})();
}
})();
});
</script>
</body>
</html>