Browse Source

Issue #837: refactored 1D component: fixed frozen axis bug; #864: dataload indicator added

cycle20 1 year ago
parent
commit
4259b760f8

+ 1 - 2
src/TmFv3DApp/index.tsx

@@ -10,8 +10,7 @@ import { BlockSelectorManager, FeatureBlockInterface } from "../RcsbFvSequence/S
 import * as React from "react";
 import { LoadMolstarInterface, LoadMolstarReturnType } from "../RcsbFvStructure/StructureViewers/MolstarViewer/MolstarActionManager";
 
-customElements.define("tm-saguaro-1d", TmFv1DElement);
-
+customElements.define(TmFv1DElement.TagName, TmFv1DElement);
 
 function createRcsb3DViewer(configParams: any) {
     document.addEventListener("DOMContentLoaded", (event) => {

+ 0 - 2
src/TmFv3DApp/tmdet-extension/tmdet-color-theme.ts

@@ -213,8 +213,6 @@ function loadRegionColorsFromStyleSheets(prefix: string = 'ult_'): void {
 
 export function updateSiteColors(side1: "Inside"|"Outside"|"Unknown"|null): void {
 
-    console.log(`updateSiteColors: side1: ${side1}`);
-
     if (!side1) {
         console.error('updateSiteColors: side1 is undefined or null');
         return;

+ 73 - 13
src/TmFv3DApp/tmdet-viewer/TmFv1DComponent.tsx

@@ -15,7 +15,8 @@ type TmFv1DParams = {
     side1: string,
     trackWidth?: number,
     rowTitleWidth?: number,
-    autoResize?: boolean
+    autoResize?: boolean,
+    parent?: TmFv1DElement
 };
 
 type TmFv1DState = {
@@ -24,7 +25,7 @@ type TmFv1DState = {
 };
 
 
-export class TmFv1D extends React.Component<TmFv1DParams, TmFv1DState> {
+export class TmFv1DComponent extends React.Component<TmFv1DParams, TmFv1DState> {
 
     protected containerRef = React.createRef<HTMLDivElement>();
 
@@ -38,7 +39,8 @@ export class TmFv1D extends React.Component<TmFv1DParams, TmFv1DState> {
             url: this.props.url,
             side1: this.props.side1,
             rowTitleWidth: this.props.rowTitleWidth,
-            trackWidth: this.props.trackWidth
+            trackWidth: this.props.trackWidth,
+            parent: this.props.parent
         });
 
         if (this.props.autoResize) {
@@ -71,9 +73,24 @@ export class TmFv1D extends React.Component<TmFv1DParams, TmFv1DState> {
 
 export class TmFv1DElement extends HTMLElement {
 
+    public static readonly TagName: string = "tm-saguaro-1d";
+
+    public interSections: number = 0;
+    public static interVal: number = 500;
+    public static isMassResizeScheduled: boolean = false;
+    public static isMassResizeTriggered: boolean = false;
+    public isDataReceived: boolean = false;
+
     connectedCallback() {
         const root = createRoot(this);
-        setTimeout(() => this.render(root), 1000);
+        this.render(root);
+
+        const intersectionOptions = {
+            root: null,
+            rootMargin: "0px",
+            threshold: 0.01
+        };
+        new IntersectionObserver(this.intersection, intersectionOptions).observe(this);
     }
 
     render(root: Root) {
@@ -94,26 +111,40 @@ export class TmFv1DElement extends HTMLElement {
             ? parseInt(this.getAttribute("trackWidth")!) || (defaultViewerWidth - ULTIMATE_GAP_CONSTANT)
             : calculatedWidth;
         trackWidth -= rowTitleWidth;
-        console.log(`${elementId} Widths:`, [ rowTitleWidth, trackWidth ]);
 
-        root.render(
-            <TmFv1D
+        root.render(<>
+            <div className="loader">Loading...</div>
+            <TmFv1DComponent
                 elementId={ elementId }
                 url={ url }
                 side1={ side1 }
                 trackWidth={ trackWidth }
                 rowTitleWidth={ rowTitleWidth }
                 autoResize={ autoResize }
+                parent={ this }
             />
-        );
+        </>);
+
+        setTimeout(() => this.triggerResize(elementId), TmFv1DElement.interVal);
+        TmFv1DElement.interVal += 250;
+    }
 
-        setTimeout(() => this.triggerResize(elementId), 250);
+    public dataReceivedCallback() {
+        this.isDataReceived = true;
+        this.firstChild?.remove();
+        const elements: Element[] = Array.from(document.getElementsByTagName(TmFv1DElement.TagName));
+        const isAllReceived = elements.every(element => (element as TmFv1DElement).isDataReceived);
+        if (isAllReceived && !TmFv1DElement.isMassResizeScheduled) {
+            TmFv1DElement.isMassResizeScheduled = true;
+            TmFv1DElement.massResize();
+        }
     }
 
-    public triggerResize(id: string): void {
-        const element = document.getElementById(id);
+    public triggerResize(id?: string|null): void {
+        const element = id ? document.getElementById(id)
+            : document.getElementById((this.firstChild! as HTMLElement).id);
         if (!element) {
-            console.warn(`'${id}' element not found`);
+            console.warn(`triggerResize: counter: ${this.interSections} '${id}' element not found`);
             return;
         }
         const paddingRight = element.style.paddingRight;
@@ -121,6 +152,31 @@ export class TmFv1DElement extends HTMLElement {
         setTimeout(() => element.style.setProperty('padding-right', paddingRight), 250);
     }
 
+    public intersection(entries: IntersectionObserverEntry[], observer: IntersectionObserver) {
+        const target = entries[0].target as TmFv1DElement;
+        target.interSections++;
+
+        if (target.interSections < 4) {
+            target.triggerResize(target.getAttribute("elementId"));
+        } else {
+            observer.unobserve(target);
+        }
+    }
+
+    public static massResize() {
+        const element = document.getElementsByTagName('body')[0];
+        if (!element) {
+            console.error(`body element not found`);
+            return;
+        }
+
+        TmFv1DElement.isMassResizeTriggered = true;
+
+        const paddingRight = element.style.paddingRight;
+        element.style.setProperty('padding-right', '1px');
+        setTimeout(() => element.style.setProperty('padding-right', paddingRight), 500);
+        console.log(`Mass resize of ${TmFv1DElement.TagName} elements has been scheduled`);
+    }
 }
 
 function calculateViewerWidth(parent: HTMLElement|null) {
@@ -147,11 +203,15 @@ const featureViewerRegistry = new Map();
  * @param side1 side1 paramter to update site colors, if it is needed
  */
 export async function createRcsbFeatureViewer(params: {
-    elementId: string, url: string, side1: string, trackWidth?: number, rowTitleWidth?: number }): Promise<RcsbFv> {
+    elementId: string, url: string, side1: string,
+    trackWidth?: number, rowTitleWidth?: number, parent?: TmFv1DElement }): Promise<RcsbFv> {
 
     updateSiteColors(params.side1 as any);
 
     const featureTracks = await fetchDescriptor(params.url);
+    if (params.parent) {
+        params.parent.dataReceivedCallback();
+    }
     const blockConfig = featureTracks.blockConfig;
     const boardConfig = blockConfig[0].featureViewConfig[0].boardConfig;
     boardConfig.trackWidth = params.trackWidth ?? 600;