Skip to content

Commit

Permalink
feat: interpretation panel (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
crfmc authored Jan 2, 2025
1 parent bbea2e8 commit 9008e5e
Show file tree
Hide file tree
Showing 8 changed files with 882 additions and 38 deletions.
58 changes: 46 additions & 12 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { VariantViewModal } from './ui/VariantViewModal';
import { NavigationButtons } from './ui/NavigationButtons';
import { Track, getTrackDocData } from './ui/getTrackDocData.js';
import { NavigationBar } from './ui/NavigationBar';
import { ClinicalPanel } from './ui/ClinicalPanel';

import 'bootstrap/dist/css/bootstrap.min.css';
import './css/App.css';
Expand Down Expand Up @@ -103,6 +104,9 @@ function App(props: RouteComponentProps) {

const currentSpec = useRef<string>();

const [isClinicalPanelOpen, setIsClinicalPanelOpen] = useState(false);
const CLINICAL_PANEL_WIDTH = isMinimalMode || !demo?.clinicalInfo ? 0 : isClinicalPanelOpen ? 250 : 45;

// interactions
const [showSamples, setShowSamples] = useState(urlParams.get('showSamples') !== 'false' && !xDomain);
const [showAbout, setShowAbout] = useState(false);
Expand All @@ -115,7 +119,7 @@ function App(props: RouteComponentProps) {
const [showPutativeDriver, setShowPutativeDriver] = useState(true);
const [interactiveMode, setInteractiveMode] = useState(isMinimalMode ?? false);
const [visPanelWidth, setVisPanelWidth] = useState(
INIT_VIS_PANEL_WIDTH - (isMinimalMode ? 10 : VIS_PADDING.left * 2)
INIT_VIS_PANEL_WIDTH - (isMinimalMode ? 10 : VIS_PADDING.left + VIS_PADDING.right + CLINICAL_PANEL_WIDTH)
);
const [overviewChr, setOverviewChr] = useState('');
const [genomeViewChr, setGenomeViewChr] = useState('');
Expand All @@ -140,6 +144,10 @@ function App(props: RouteComponentProps) {
return (allDrivers as any).filter((d: any) => d.sample_id === demoId && +d.pos);
}

useEffect(() => {
setVisPanelWidth(INIT_VIS_PANEL_WIDTH - (VIS_PADDING.left + VIS_PADDING.right + CLINICAL_PANEL_WIDTH));
}, [isClinicalPanelOpen]);

// update demo
useEffect(() => {
if (typeof demo.drivers === 'string' && demo.drivers.split('.').pop() === 'json') {
Expand Down Expand Up @@ -186,6 +194,9 @@ function App(props: RouteComponentProps) {
setSelectedSvId('');
leftReads.current = [];
rightReads.current = [];

// Update the appearance of the clinical panel
setIsClinicalPanelOpen(!!demo?.clinicalInfo);
}, [demo]);

useEffect(() => {
Expand Down Expand Up @@ -323,13 +334,14 @@ function App(props: RouteComponentProps) {
window.addEventListener(
'resize',
debounce(() => {
setVisPanelWidth(window.innerWidth - (isMinimalMode ? 10 : VIS_PADDING.left * 2));
setVisPanelWidth(window.innerWidth - (isMinimalMode ? 10 : VIS_PADDING.left + VIS_PADDING.right));
}, 500)
);

// Lower opacity of legend image as it leaves viewport
// Lower opacity of legend image as it leaves viewport in minimal mode
if (isMinimalMode) {
const legendElement = document.querySelector<HTMLElement>('.genome-view-legend');

const options = {
root: document.querySelector('.minimal_mode'),
rootMargin: '-250px 0px 0px 0px',
Expand All @@ -342,6 +354,10 @@ function App(props: RouteComponentProps) {
}, options);

observer.observe(legendElement);

return () => {
observer.unobserve(legendElement);
};
}
}, []);

Expand Down Expand Up @@ -740,10 +756,10 @@ function App(props: RouteComponentProps) {
const height = window.innerHeight;
if (!isMinimalMode) {
if (
VIS_PADDING.top < top &&
top < height - VIS_PADDING.top &&
VIS_PADDING.left < left &&
left < width - VIS_PADDING.left
VIS_PADDING.top < top && // past top margin
top < height - VIS_PADDING.top && // before bottom margin
VIS_PADDING.left < left && // past left margin
left < width - (VIS_PADDING.right + CLINICAL_PANEL_WIDTH) // before right margin
) {
setMouseOnVis(true);
} else {
Expand Down Expand Up @@ -939,7 +955,9 @@ function App(props: RouteComponentProps) {
id="gosling-panel"
className="gosling-panel"
style={{
width: `calc(100% - ${VIS_PADDING.left * 2}px)`,
width: isMinimalMode
? `calc(100% - ${VIS_PADDING.left + VIS_PADDING.right}px)`
: `calc(100% - ${VIS_PADDING.left + VIS_PADDING.right + CLINICAL_PANEL_WIDTH}px)`,
height: `calc(100% - ${VIS_PADDING.top * 2}px)`,
padding: `${VIS_PADDING.top}px ${VIS_PADDING.right}px ${VIS_PADDING.bottom}px ${VIS_PADDING.left}px`
}}
Expand All @@ -963,7 +981,7 @@ function App(props: RouteComponentProps) {
{!isMinimalMode && (
<div
style={{
width: '100%',
width: `calc(100% - ${0}px)`,
height: '100%',
boxShadow: `inset 0 0 0 3px ${
interactiveMode && mouseOnVis
Expand Down Expand Up @@ -1061,6 +1079,7 @@ function App(props: RouteComponentProps) {
}}
>
<img
id="genome-view-legend"
className="genome-view-legend"
src={legend}
style={{
Expand All @@ -1072,6 +1091,7 @@ function App(props: RouteComponentProps) {
}}
/>
<div
id="variant-view-controls"
className="variant-view-controls"
style={{ top: `${Math.min(visPanelWidth, isMinimalMode ? 650 : 600)}px` }}
>
Expand Down Expand Up @@ -1280,13 +1300,13 @@ function App(props: RouteComponentProps) {
? 'visible'
: 'collapse',
position: 'absolute',
right: `${VIS_PADDING.right}px`,
right: `${VIS_PADDING.right + CLINICAL_PANEL_WIDTH}px`,
top: '60px',
background: 'lightgray',
color: 'black',
padding: '6px',
pointerEvents: 'none',
zIndex: 9999,
zIndex: 999,
boxShadow: '0 0 20px 2px rgba(0, 0, 0, 0.2)'
}}
>
Expand All @@ -1302,7 +1322,7 @@ function App(props: RouteComponentProps) {
height: '100%',
visibility: 'collapse',
boxShadow: interactiveMode ? 'inset 0 0 4px 2px #2399DB' : 'none',
zIndex: 9999,
zIndex: 999,
background: 'none',
position: 'absolute',
top: 0,
Expand Down Expand Up @@ -1441,6 +1461,9 @@ function App(props: RouteComponentProps) {
className="move-to-top-btn"
tabIndex={showSamples ? -1 : 0}
aria-label="Scroll to top."
style={{
right: isMinimalMode ? '10px' : `${VIS_PADDING.right + CLINICAL_PANEL_WIDTH}px`
}}
onClick={() => {
setTimeout(
() => document.getElementById('gosling-panel')?.scrollTo({ top: 0, behavior: 'smooth' }),
Expand All @@ -1458,6 +1481,17 @@ function App(props: RouteComponentProps) {
<GenomeViewModal />
<VariantViewModal />
</div>
{!isMinimalMode && demo?.clinicalInfo && (
<ClinicalPanel
demo={demo}
gosRef={gosRef}
filteredSamples={filteredSamples}
hasClinicalInfo={!!demo?.clinicalInfo}
isClinicalPanelOpen={isClinicalPanelOpen}
setIsClinicalPanelOpen={setIsClinicalPanelOpen}
setInteractiveMode={setInteractiveMode}
/>
)}
</div>
</ErrorBoundary>
);
Expand Down
Loading

0 comments on commit 9008e5e

Please sign in to comment.