aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/DashDocView.tsx
diff options
context:
space:
mode:
authorusodhi <61431818+usodhi@users.noreply.github.com>2021-03-10 15:40:40 -0500
committerusodhi <61431818+usodhi@users.noreply.github.com>2021-03-10 15:40:40 -0500
commit55aeb2f80dd48e758fcf6b957233d4949c4b063e (patch)
tree1f9910700e21a1594ed65dfed2a05cb704c4eff4 /src/client/views/nodes/formattedText/DashDocView.tsx
parent89b7b2ae27cbab6a7edd5fa3759949afe2cd2f71 (diff)
parent11b6bd8eca19b36fdd28f71a7fc4043134983c5e (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into filters
Diffstat (limited to 'src/client/views/nodes/formattedText/DashDocView.tsx')
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx343
1 files changed, 137 insertions, 206 deletions
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 91d123efe..86a9f4347 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -1,7 +1,6 @@
-import { IReactionDisposer, reaction } from "mobx";
+import { IReactionDisposer, reaction, observable, action } from "mobx";
import { NodeSelection } from "prosemirror-state";
import { Doc, HeightSym, WidthSym } from "../../../../fields/Doc";
-import { Id } from "../../../../fields/FieldSymbols";
import { Cast, StrCast } from "../../../../fields/Types";
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, Utils } from "../../../../Utils";
import { DocServer } from "../../../DocServer";
@@ -11,250 +10,182 @@ import { Transform } from "../../../util/Transform";
import { DocumentView } from "../DocumentView";
import { FormattedTextBox } from "./FormattedTextBox";
import React = require("react");
+import * as ReactDOM from 'react-dom';
+import { observer } from "mobx-react";
+
+export class DashDocView {
+ _fieldWrapper: HTMLSpanElement; // container for label and value
+
+ constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
+ this._fieldWrapper = document.createElement("span");
+ this._fieldWrapper.style.position = "relative";
+ this._fieldWrapper.style.textIndent = "0";
+ this._fieldWrapper.style.border = "1px solid " + StrCast(tbox.layoutDoc.color, (CurrentUserUtils.ActiveDashboard.darkScheme ? "dimGray" : "lightGray"));
+ this._fieldWrapper.style.width = node.attrs.width;
+ this._fieldWrapper.style.height = node.attrs.height;
+ this._fieldWrapper.style.display = node.attrs.hidden ? "none" : "inline-block";
+ (this._fieldWrapper.style as any).float = node.attrs.float;
+ this._fieldWrapper.onkeypress = function (e: any) { e.stopPropagation(); };
+ this._fieldWrapper.onkeydown = function (e: any) { e.stopPropagation(); };
+ this._fieldWrapper.onkeyup = function (e: any) { e.stopPropagation(); };
+ this._fieldWrapper.onmousedown = function (e: any) { e.stopPropagation(); };
+
+ ReactDOM.render(<DashDocViewInternal
+ docid={node.attrs.docid}
+ alias={node.attrs.alias}
+ width={node.attrs.width}
+ height={node.attrs.height}
+ hidden={node.attrs.hidden}
+ fieldKey={node.attrs.fieldKey}
+ tbox={tbox}
+ view={view}
+ node={node}
+ getPos={getPos}
+ />, this._fieldWrapper);
+ (this as any).dom = this._fieldWrapper;
+ }
+ destroy() { ReactDOM.unmountComponentAtNode(this._fieldWrapper); }
+ selectNode() { }
+}
-interface IDashDocView {
- node: any;
+interface IDashDocViewInternal {
+ docid: string;
+ alias: string;
+ tbox: FormattedTextBox;
+ width: string;
+ height: string;
+ hidden: boolean;
+ fieldKey: string;
view: any;
+ node: any;
getPos: any;
- tbox?: FormattedTextBox;
- self: any;
}
-
-export class DashDocView extends React.Component<IDashDocView> {
-
- _dashDoc: Doc | undefined;
- _reactionDisposer: IReactionDisposer | undefined;
- _renderDisposer: IReactionDisposer | undefined;
+@observer
+export class DashDocViewInternal extends React.Component<IDashDocViewInternal> {
+ _spanRef = React.createRef<HTMLDivElement>();
+ _disposers: { [name: string]: IReactionDisposer } = {};
_textBox: FormattedTextBox;
- _finalLayout: any;
- _resolvedDataDoc: any;
-
-
- // constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
+ @observable _dashDoc: Doc | undefined;
+ @observable _finalLayout: any;
+ @observable _resolvedDataDoc: any;
- constructor(props: IDashDocView) {
+ constructor(props: IDashDocViewInternal) {
super(props);
-
- const node = this.props.node;
this._textBox = this.props.tbox as FormattedTextBox;
- const alias = node.attrs.alias;
- const docid = node.attrs.docid || this._textBox.props.Document[Id];
+ const updateDoc = action((dashDoc: Doc) => {
+ this._dashDoc = dashDoc;
+ this._finalLayout = this.props.docid ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc, this.props.fieldKey);
- DocServer.GetRefField(docid + alias).then(async dashDoc => {
+ if (this._finalLayout) {
+ if (!Doc.AreProtosEqual(this._finalLayout, dashDoc)) {
+ this._finalLayout.rootDocument = dashDoc.aliasOf;
+ }
+ this._resolvedDataDoc = Cast(this._finalLayout.resolvedDataDoc, Doc, null);
+ }
+ if (this.props.width !== (this._dashDoc?._width ?? "") + "px" || this.props.height !== (this._dashDoc?._height ?? "") + "px") {
+ try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made
+ this.props.view.dispatch(this.props.view.state.tr.setNodeMarkup(this.props.getPos(), null, {
+ ...this.props.node.attrs, width: (this._dashDoc?._width ?? "") + "px", height: (this._dashDoc?._height ?? "") + "px"
+ }));
+ } catch (e) {
+ console.log("DashDocView:" + e);
+ }
+ }
+ });
+
+ DocServer.GetRefField(this.props.docid + this.props.alias).then(async dashDoc => {
if (!(dashDoc instanceof Doc)) {
- alias && DocServer.GetRefField(docid).then(async dashDocBase => {
+ this.props.alias && DocServer.GetRefField(this.props.docid).then(async dashDocBase => {
if (dashDocBase instanceof Doc) {
- const aliasedDoc = Doc.MakeAlias(dashDocBase, docid + alias);
+ const aliasedDoc = Doc.MakeAlias(dashDocBase, this.props.docid + this.props.alias);
aliasedDoc.layoutKey = "layout";
- node.attrs.fieldKey && DocUtils.makeCustomViewClicked(aliasedDoc, Docs.Create.StackingDocument, node.attrs.fieldKey, undefined);
- this._dashDoc = aliasedDoc;
- // self.doRender(aliasedDoc, removeDoc, node, view, getPos);
+ this.props.fieldKey && DocUtils.makeCustomViewClicked(aliasedDoc, Docs.Create.StackingDocument, this.props.fieldKey, undefined);
+ updateDoc(aliasedDoc)
}
});
} else {
- this._dashDoc = dashDoc;
- // self.doRender(dashDoc, removeDoc, node, view, getPos);
+ updateDoc(dashDoc);
}
});
-
- this.onPointerLeave = this.onPointerLeave.bind(this);
- this.onPointerEnter = this.onPointerEnter.bind(this);
- this.onKeyDown = this.onKeyDown.bind(this);
- this.onKeyPress = this.onKeyPress.bind(this);
- this.onKeyUp = this.onKeyUp.bind(this);
- this.onWheel = this.onWheel.bind(this);
}
- /* #region Internal functions */
removeDoc = () => {
- const view = this.props.view;
- const pos = this.props.getPos();
- const ns = new NodeSelection(view.state.doc.resolve(pos));
- view.dispatch(view.state.tr.setSelection(ns).deleteSelection());
+ this.props.view.dispatch(this.props.view.state.tr
+ .setSelection(new NodeSelection(this.props.view.state.doc.resolve(this.props.getPos())))
+ .deleteSelection());
return true;
}
getDocTransform = () => {
- const outerElement = document.getElementById('dash-document-view-outer') as HTMLElement;
- const { scale, translateX, translateY } = Utils.GetScreenTransform(outerElement);
- return new Transform(-translateX, -translateY, 1).scale(1 / this.contentScaling() / scale);
+ if (!this._spanRef.current) return Transform.Identity();
+ const { scale, translateX, translateY } = Utils.GetScreenTransform(this._spanRef.current);
+ return new Transform(-translateX, -translateY, 1).scale(1 / scale);
}
- contentScaling = () => Doc.NativeWidth(this._dashDoc) > 0 ? this._dashDoc![WidthSym]() / Doc.NativeWidth(this._dashDoc) : 1;
-
outerFocus = (target: Doc) => this._textBox.props.focus(this._textBox.props.Document); // ideally, this would scroll to show the focus target
- onKeyPress = (e: any) => {
- e.stopPropagation();
- }
- onWheel = (e: any) => {
- e.preventDefault();
- }
- onKeyUp = (e: any) => {
- e.stopPropagation();
- }
onKeyDown = (e: any) => {
e.stopPropagation();
if (e.key === "Tab" || e.key === "Enter") {
e.preventDefault();
}
}
+
onPointerLeave = () => {
- const ele = document.getElementById("DashDocCommentView-" + this.props.node.attrs.docid);
- if (ele) {
- (ele as HTMLDivElement).style.backgroundColor = "";
- }
+ const ele = document.getElementById("DashDocCommentView-" + this.props.docid) as HTMLDivElement;
+ ele && (ele.style.backgroundColor = "");
}
- onPointerEnter = () => {
- const ele = document.getElementById("DashDocCommentView-" + this.props.node.attrs.docid);
- if (ele) {
- (ele as HTMLDivElement).style.backgroundColor = "orange";
- }
- }
- /*endregion*/
- componentWillUnmount = () => {
- this._reactionDisposer?.();
+ onPointerEnter = () => {
+ const ele = document.getElementById("DashDocCommentView-" + this.props.docid) as HTMLDivElement;
+ ele && (ele.style.backgroundColor = "orange");
}
- componentDidUpdate = () => {
-
- this._renderDisposer?.();
- this._renderDisposer = reaction(() => {
-
- const dashDoc = this._dashDoc as Doc;
- const dashLayoutDoc = Doc.Layout(dashDoc);
- const finalLayout = this.props.node.attrs.docid ? dashDoc : Doc.expandTemplateLayout(dashLayoutDoc, dashDoc, this.props.node.attrs.fieldKey);
-
- if (finalLayout) {
- if (!Doc.AreProtosEqual(finalLayout, dashDoc)) {
- finalLayout.rootDocument = dashDoc.aliasOf;
- }
- this._finalLayout = finalLayout;
- this._resolvedDataDoc = Cast(finalLayout.resolvedDataDoc, Doc, null);
- return { finalLayout, resolvedDataDoc: Cast(finalLayout.resolvedDataDoc, Doc, null) };
- }
- },
- (res) => {
-
- if (res) {
- this._finalLayout = res.finalLayout;
- this._resolvedDataDoc = res.resolvedDataDoc;
-
- this.forceUpdate(); // doReactRender(res.finalLayout, res.resolvedDataDoc),
- }
- },
- { fireImmediately: true });
-
- }
+ componentWillUnmount = () => Object.values(this._disposers).forEach(disposer => disposer?.());
render() {
- // doRender(dashDoc: Doc, removeDoc: any, node: any, view: any, getPos: any) {
-
- const node = this.props.node;
- const view = this.props.view;
- const getPos = this.props.getPos;
-
- const spanStyle = {
- width: this.props.node.props.width,
- height: this.props.node.props.height,
- position: 'absolute' as 'absolute',
- display: 'inline-block'
- };
-
-
- const outerStyle = {
- position: "relative" as "relative",
- textIndent: "0",
- border: "1px solid " + StrCast(this._textBox.Document.color, (CurrentUserUtils.ActiveDashboard.darkScheme ? "dimGray" : "lightGray")),
- width: this.props.node.props.width,
- height: this.props.node.props.height,
- display: this.props.node.props.hidden ? "none" : "inline-block",
- float: this.props.node.props.float,
- };
-
- const dashDoc = this._dashDoc as Doc;
- const self = this;
- const dashLayoutDoc = Doc.Layout(dashDoc);
- const finalLayout = node.attrs.docid ? dashDoc : Doc.expandTemplateLayout(dashLayoutDoc, dashDoc, node.attrs.fieldKey);
- const resolvedDataDoc = this._resolvedDataDoc; //Added this
-
- if (!finalLayout) {
- return <div></div>;
- // if (!finalLayout) setTimeout(() => self.doRender(dashDoc, removeDoc, node, view, getPos), 0);
- } else {
-
- this._reactionDisposer?.();
- this._reactionDisposer = reaction(() =>
- ({
- dim: [finalLayout[WidthSym](), finalLayout[HeightSym]()],
- color: finalLayout.color
- }),
- ({ dim, color }) => {
- spanStyle.width = outerStyle.width = Math.max(20, dim[0]) + "px";
- spanStyle.height = outerStyle.height = Math.max(20, dim[1]) + "px";
- outerStyle.border = "1px solid " + StrCast(finalLayout.color, (CurrentUserUtils.ActiveDashboard.darkScheme ? "dimGray" : "lightGray"));
- }, { fireImmediately: true });
-
- if (node.attrs.width !== dashDoc._width + "px" || node.attrs.height !== dashDoc._height + "px") {
- try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made
- view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc._width + "px", height: dashDoc._height + "px" }));
- } catch (e) {
- console.log("DashDocView:" + e);
- }
- }
-
-
- //const doReactRender = (finalLayout: Doc, resolvedDataDoc: Doc) => {
- // ReactDOM.unmountComponentAtNode(this._dashSpan);
-
- return (
- <span id="dash-document-view-outer"
- className="outer"
- style={outerStyle}
- >
- <div id="dashSpan"
- className="dash-span"
- style={spanStyle}
- onPointerLeave={this.onPointerLeave}
- onPointerEnter={this.onPointerEnter}
- onKeyDown={this.onKeyDown}
- onKeyPress={this.onKeyPress}
- onKeyUp={this.onKeyUp}
- onWheel={this.onWheel}
- >
- <DocumentView
- Document={finalLayout}
- DataDoc={resolvedDataDoc}
- addDocument={returnFalse}
- rootSelected={this._textBox.props.isSelected}
- removeDocument={this.removeDoc}
- ScreenToLocalTransform={this.getDocTransform}
- addDocTab={this._textBox.props.addDocTab}
- pinToPres={returnFalse}
- renderDepth={self._textBox.props.renderDepth + 1}
- PanelWidth={finalLayout[WidthSym]}
- PanelHeight={finalLayout[HeightSym]}
- focus={this.outerFocus}
- styleProvider={self._textBox.props.styleProvider}
- layerProvider={self._textBox.props.layerProvider}
- docViewPath={self._textBox.props.docViewPath}
- parentActive={returnFalse}
- whenActiveChanged={returnFalse}
- bringToFront={emptyFunction}
- dontRegisterView={false}
- docFilters={this.props.tbox?.props.docFilters || returnEmptyFilter}
- docRangeFilters={this.props.tbox?.props.docRangeFilters || returnEmptyFilter}
- searchFilterDocs={this.props.tbox?.props.searchFilterDocs || returnEmptyDoclist}
- ContainingCollectionView={this._textBox.props.ContainingCollectionView}
- ContainingCollectionDoc={this._textBox.props.ContainingCollectionDoc}
- />
-
- </div>
- </span>
- );
-
- }
+ return !this._dashDoc || !this._finalLayout || this.props.hidden ? null :
+ <div ref={this._spanRef}
+ className="dash-span"
+ style={{
+ width: this.props.width,
+ height: this.props.height,
+ position: 'absolute',
+ display: 'inline-block'
+ }}
+ onPointerLeave={this.onPointerLeave}
+ onPointerEnter={this.onPointerEnter}
+ onKeyDown={this.onKeyDown}
+ onKeyPress={e => e.stopPropagation()}
+ onKeyUp={e => e.stopPropagation()}
+ onWheel={e => e.preventDefault()}
+ >
+ <DocumentView
+ Document={this._finalLayout}
+ DataDoc={this._resolvedDataDoc}
+ addDocument={returnFalse}
+ rootSelected={this._textBox.props.isSelected}
+ removeDocument={this.removeDoc}
+ layerProvider={this._textBox.props.layerProvider}
+ styleProvider={this._textBox.props.styleProvider}
+ docViewPath={this._textBox.props.docViewPath}
+ ScreenToLocalTransform={this.getDocTransform}
+ addDocTab={this._textBox.props.addDocTab}
+ pinToPres={returnFalse}
+ renderDepth={this._textBox.props.renderDepth + 1}
+ PanelWidth={this._finalLayout[WidthSym]}
+ PanelHeight={this._finalLayout[HeightSym]}
+ focus={this.outerFocus}
+ parentActive={returnFalse}
+ whenActiveChanged={returnFalse}
+ bringToFront={emptyFunction}
+ dontRegisterView={false}
+ docFilters={this.props.tbox?.props.docFilters}
+ docRangeFilters={this.props.tbox?.props.docRangeFilters}
+ searchFilterDocs={this.props.tbox?.props.searchFilterDocs}
+ ContainingCollectionView={this._textBox.props.ContainingCollectionView}
+ ContainingCollectionDoc={this._textBox.props.ContainingCollectionDoc}
+ />
+ </div>;
}
-
} \ No newline at end of file