aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/WebBox.tsx
diff options
context:
space:
mode:
authorusodhi <61431818+usodhi@users.noreply.github.com>2021-03-14 21:21:12 -0400
committerusodhi <61431818+usodhi@users.noreply.github.com>2021-03-14 21:21:12 -0400
commit599656b2dde4ba56e8cb6bbf9fb0fe2dee43c809 (patch)
tree8ae27dcbe9be2ac5c6332381e714db6f83fb644e /src/client/views/nodes/WebBox.tsx
parent8811fb0f177ed1448fa7b3d08ff42145254a0475 (diff)
parent45c89c7b79a84fb918b656490f2bde9d1701d76a (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into filters
Diffstat (limited to 'src/client/views/nodes/WebBox.tsx')
-rw-r--r--src/client/views/nodes/WebBox.tsx195
1 files changed, 144 insertions, 51 deletions
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index b15865c1f..ab17703c8 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -4,7 +4,7 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction
import { observer } from "mobx-react";
import { Dictionary } from "typescript-collections";
import * as WebRequest from 'web-request';
-import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { Doc, DocListCast, HeightSym, Opt, WidthSym, StrListCast } from "../../../fields/Doc";
import { documentSchema } from "../../../fields/documentSchemas";
import { Id } from "../../../fields/FieldSymbols";
import { HtmlField } from "../../../fields/HtmlField";
@@ -14,8 +14,8 @@ import { listSpec, makeInterface } from "../../../fields/Schema";
import { Cast, NumCast, StrCast } from "../../../fields/Types";
import { WebField } from "../../../fields/URLField";
import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, OmitKeys, returnOne, smoothScroll, Utils } from "../../../Utils";
-import { Docs } from "../../documents/Documents";
+import { emptyFunction, OmitKeys, returnOne, smoothScroll, Utils, returnZero, returnTrue } from "../../../Utils";
+import { Docs, DocUtils } from "../../documents/Documents";
import { DragManager } from "../../util/DragManager";
import { ImageUtils } from "../../util/Import & Export/ImageUtils";
import { undoBatch } from "../../util/UndoManager";
@@ -32,6 +32,11 @@ import "./WebBox.scss";
import { DocumentType } from '../../documents/DocumentTypes';
import React = require("react");
import { CurrentUserUtils } from "../../util/CurrentUserUtils";
+import { SearchBox } from "../search/SearchBox";
+import { CollectionStackingView } from "../collections/CollectionStackingView";
+import { StyleProp } from "../StyleProvider";
+import { FormattedTextBox } from "./formattedText/FormattedTextBox";
+import { CollectionViewType } from "../collections/CollectionView";
const htmlToText = require("html-to-text");
type WebDocument = makeInterface<[typeof documentSchema]>;
@@ -461,6 +466,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
const funcs: ContextMenuProps[] = [];
funcs.push({ description: (this.layoutDoc.useCors ? "Don't Use" : "Use") + " Cors", event: () => this.layoutDoc.useCors = !this.layoutDoc.useCors, icon: "snowflake" });
funcs.push({ description: (this.layoutDoc[this.fieldKey + "-contentWidth"] ? "Unfreeze" : "Freeze") + " Content Width", event: () => this.layoutDoc[this.fieldKey + "-contentWidth"] = this.layoutDoc[this.fieldKey + "-contentWidth"] ? undefined : Doc.NativeWidth(this.layoutDoc), icon: "snowflake" });
+ funcs.push({ description: "Toggle Annotation View ", event: () => this.Document._showSidebar = !this.Document._showSidebar, icon: "expand-arrows-alt" });
cm.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
}
@@ -483,6 +489,83 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
return view;
}
+ anchorMenuClick = (anchor: Doc) => {
+ this.Document._showSidebar = true;
+ const startup = StrListCast(this.rootDoc.docFilters).map(filter => filter.split(":")[0]).join(" ");
+ const target = Docs.Create.TextDocument(startup, {
+ title: "anno",
+ annotationOn: this.rootDoc, _width: 200, _height: 50, _fitWidth: true, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize),
+ _fontFamily: StrCast(Doc.UserDoc().fontFamily)
+ });
+ FormattedTextBox.SelectOnLoad = target[Id];
+ FormattedTextBox.DontSelectInitialText = true;
+ this.allTags.map(tag => target[tag] = tag);
+ DocUtils.MakeLink({ doc: anchor }, { doc: target }, "inline markup", "annotation");
+ this.sidebarAddDocument(target);
+ }
+ sidebarKey = () => this.fieldKey + "-sidebar";
+ sidebarFiltersHeight = () => 50;
+ sidebarTransform = () => this.props.ScreenToLocalTransform().translate(Doc.NativeWidth(this.dataDoc), 0).scale(this.props.scaling?.() || 1);
+ sidebarWidth = () => !this.layoutDoc._showSidebar ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
+ sidebarHeight = () => this.props.PanelHeight() - this.sidebarFiltersHeight() - 20;
+ sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.sidebarKey());
+ sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.sidebarKey());
+ sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.sidebarKey());
+ sidebarDocFilters = () => [...StrListCast(this.layoutDoc._docFilters), ...StrListCast(this.layoutDoc[this.sidebarKey() + "-docFilters"])];
+ @computed get allTags() {
+ const keys = new Set<string>();
+ DocListCast(this.rootDoc[this.sidebarKey()]).forEach(doc => SearchBox.documentKeys(doc).forEach(key => keys.add(key)));
+ return Array.from(keys.keys()).filter(key => key[0]).filter(key => !key.startsWith("_") && (key[0] === "#" || key[0] === key[0].toUpperCase())).sort();
+ }
+ renderTag = (tag: string) => {
+ const active = StrListCast(this.rootDoc[this.sidebarKey() + "-docFilters"]).includes(`${tag}:${tag}:check`);
+ return <div className={`webBox-filterTag${active ? "-active" : ""}`}
+ onClick={e => Doc.setDocFilter(this.rootDoc, tag, tag, "check", true, this.sidebarKey())}>
+ {tag}
+ </div>;
+ }
+ @computed get sidebarOverlay() {
+ return !this.layoutDoc._showSidebar ? (null) :
+ <div style={{
+ position: "absolute", pointerEvents: this.active() ? "all" : undefined, top: 0, right: 0,
+ background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor),
+ width: `${this.sidebarWidth()}px`,
+ height: "100%"
+ }}>
+ <div style={{ width: "100%", height: this.sidebarHeight(), position: "relative" }}>
+ <CollectionStackingView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
+ NativeWidth={returnZero}
+ NativeHeight={returnZero}
+ PanelHeight={this.sidebarHeight}
+ PanelWidth={this.sidebarWidth}
+ xMargin={0}
+ yMargin={0}
+ docFilters={this.sidebarDocFilters}
+ chromeStatus={"enabled"}
+ scaleField={this.sidebarKey() + "-scale"}
+ isAnnotationOverlay={false}
+ select={emptyFunction}
+ active={this.annotationsActive}
+ scaling={returnOne}
+ whenActiveChanged={this.whenActiveChanged}
+ childHideDecorationTitle={returnTrue}
+ removeDocument={this.sidebarRemDocument}
+ moveDocument={this.sidebarMoveDocument}
+ addDocument={this.sidebarAddDocument}
+ CollectionView={undefined}
+ ScreenToLocalTransform={this.sidebarTransform}
+ renderDepth={this.props.renderDepth + 1}
+ viewType={CollectionViewType.Stacking}
+ fieldKey={this.sidebarKey()}
+ pointerEvents={"all"}
+ />
+ </div>
+ <div className="webBox-tagList" style={{ height: this.sidebarFiltersHeight(), width: this.sidebarWidth() }}>
+ {this.allTags.map(tag => this.renderTag(tag))}
+ </div>
+ </div>;
+ }
+
@computed
get content() {
const frozen = !this.props.isSelected() || DocumentDecorations.Instance?.Interacting;
@@ -521,63 +604,73 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
@action
onMarqueeDown = (e: React.PointerEvent) => {
- if (!e.altKey && e.button === 0 && this.active(true)) this._marqueeing = [e.clientX, e.clientY];
+ if (!e.altKey && e.button === 0 && this.active(true)) {
+ this._marqueeing = [e.clientX, e.clientY];
+ this.props.select(false);
+ }
}
@action
- finishMarquee = () => {
- this._marqueeing = undefined;
- this.props.select(true);
- }
+ finishMarquee = () => this._marqueeing = undefined;
- panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
+ panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth(); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop));
render() {
const inactiveLayer = this.props.layerProvider?.(this.layoutDoc) === false;
const scale = this.props.scaling?.() || 1;
- return (<div className="webBox" ref={this._mainCont} >
- <div className={`webBox-container`}
- style={{ pointerEvents: inactiveLayer ? "none" : undefined }}
- onWheel={this.onWebWheel}
- onContextMenu={this.specificContextMenu}>
- <base target="_blank" />
- {this.content}
- <div className={"webBox-outerContent"} ref={this._outerRef}
- style={{
- width: `${100 / scale}%`, height: `${100 / scale}%`, transform: `scale(${scale})`,
- pointerEvents: !this.layoutDoc.isAnnotating || inactiveLayer ? "none" : "all"
- }}
- onWheel={this.onWheel}
- onPointerDown={this.onMarqueeDown}
- onScroll={this.onScroll}
- >
- <div className={"webBox-innerContent"} style={{
- height: NumCast(this.scrollHeight, 50),
- pointerEvents: inactiveLayer ? "none" : undefined
- }}>
- <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
- renderDepth={this.props.renderDepth + 1}
- CollectionView={undefined}
- fieldKey={this.annotationKey}
- isAnnotationOverlay={true}
- scaling={returnOne}
- PanelWidth={this.panelWidth}
- PanelHeight={this.panelHeight}
- ScreenToLocalTransform={this.scrollXf}
- removeDocument={this.removeDocument}
- moveDocument={this.moveDocument}
- addDocument={this.addDocument}
- select={emptyFunction}
- active={this.active}
- whenActiveChanged={this.whenActiveChanged} />
+ return (
+ <div className="webBox" ref={this._mainCont} >
+ <div className={`webBox-container`}
+ style={{ pointerEvents: inactiveLayer ? "none" : undefined }}
+ onWheel={this.onWebWheel}
+ onContextMenu={this.specificContextMenu}>
+ <base target="_blank" />
+ {this.content}
+ <div className={"webBox-outerContent"} ref={this._outerRef}
+ style={{
+ width: `calc(${100 / scale}% - ${this.sidebarWidth()}px)`, height: `${100 / scale}%`, transform: `scale(${scale})`,
+ pointerEvents: !this.layoutDoc.isAnnotating || inactiveLayer ? "none" : "all"
+ }}
+ onWheel={this.onWheel}
+ onPointerDown={this.onMarqueeDown}
+ onScroll={this.onScroll}
+ >
+ <div className={"webBox-innerContent"} style={{
+ height: NumCast(this.scrollHeight, 50),
+ pointerEvents: inactiveLayer ? "none" : undefined
+ }}>
+ <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
+ renderDepth={this.props.renderDepth + 1}
+ CollectionView={undefined}
+ fieldKey={this.annotationKey}
+ isAnnotationOverlay={true}
+ scaling={returnOne}
+ PanelWidth={this.panelWidth}
+ PanelHeight={this.panelHeight}
+ ScreenToLocalTransform={this.scrollXf}
+ removeDocument={this.removeDocument}
+ moveDocument={this.moveDocument}
+ addDocument={this.addDocument}
+ select={emptyFunction}
+ active={this.active}
+ whenActiveChanged={this.whenActiveChanged} />
+ </div>
</div>
- </div>
- {this.annotationLayer}
- {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) :
- <MarqueeAnnotator rootDoc={this.rootDoc} scrollTop={NumCast(this.rootDoc._scrollTop)} down={this._marqueeing} scaling={this.props.scaling} addDocument={this.addDocument} finishMarquee={this.finishMarquee} savedAnnotations={this._savedAnnotations} annotationLayer={this._annotationLayer.current} mainCont={this._mainCont.current} />}
- </div >
- {this.props.isSelected() ? this.editToggleBtn() : null}
- </div>);
+ {this.annotationLayer}
+ {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) :
+ <MarqueeAnnotator rootDoc={this.rootDoc}
+ anchorMenuClick={this.anchorMenuClick}
+ scrollTop={NumCast(this.rootDoc._scrollTop)}
+ down={this._marqueeing} scaling={this.props.scaling}
+ addDocument={this.addDocument}
+ finishMarquee={this.finishMarquee}
+ savedAnnotations={this._savedAnnotations}
+ annotationLayer={this._annotationLayer.current}
+ mainCont={this._mainCont.current} />}
+ </div >
+ {this.sidebarOverlay}
+ {this.props.isSelected() ? this.editToggleBtn() : null}
+ </div>);
}
} \ No newline at end of file