From 40d5c3acab6dbdc67f6d4bfd15c802da9fe08ca0 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 2 May 2020 00:17:21 -0400 Subject: cleaned up a lot of layoutTemplate/String props. fixed link drawing. --- src/client/views/nodes/DocumentContentsView.tsx | 44 +++++++++++-------------- 1 file changed, 20 insertions(+), 24 deletions(-) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 4d20d3e2c..749fb98be 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -96,8 +96,6 @@ export class DocumentContentsView extends React.Component boolean, select: (ctrl: boolean) => void, layoutKey: string, - forceLayout?: string, - forceFieldKey?: string, hideOnLeave?: boolean, makeLink?: () => Opt, // function to call when a link is made }> { @@ -105,6 +103,7 @@ export class DocumentContentsView extends React.Componentawaiting layout

"; // const layout = Cast(this.layoutDoc[StrCast(this.layoutDoc.layoutKey, this.layoutDoc === this.props.Document ? this.props.layoutKey : "layout")], "string"); // bcz: replaced this with below... is it right? + if (this.props.LayoutTemplateString) return this.props.LayoutTemplateString; const layout = Cast(this.layoutDoc[this.layoutDoc === this.props.Document && this.props.layoutKey ? this.props.layoutKey : StrCast(this.layoutDoc.layoutKey, "layout")], "string"); if (this.props.layoutKey === "layout_keyValue") { return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString("data")); @@ -127,8 +126,8 @@ export class DocumentContentsView extends React.Component 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc) ? (null) : - this.props.forceLayout === "FormattedTextBox" && this.props.forceFieldKey ? - - : - { console.log(test); }} - />; + { console.log(test); }} + />; } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 9de627f9d11777482029e81168004140766cbb3d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 3 May 2020 02:55:55 -0400 Subject: cleaned up freeformdocview. changed descriptionView template to test start of processing scripts for dash tag nodes. --- .../views/nodes/CollectionFreeFormDocumentView.tsx | 18 +++++------------- src/client/views/nodes/DocumentContentsView.tsx | 6 +++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 11 +++++++++++ src/server/authentication/models/current_user_utils.ts | 4 +++- 4 files changed, 22 insertions(+), 17 deletions(-) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 2894d9b65..cdbe506a5 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -14,13 +14,8 @@ import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, highlight?: boolean, z: number, transition?: string } | undefined; sizeProvider?: (doc: Doc, replica: string) => { width: number, height: number } | undefined; - x?: number; - y?: number; - z?: number; zIndex?: number; highlight?: boolean; - width?: number; - height?: number; jitterRotation: number; transition?: string; fitToBox?: boolean; @@ -38,13 +33,13 @@ export class CollectionFreeFormDocumentView extends DocComponent this.nativeWidth > 0 && !this.props.fitToBox && !this.freezeDimensions ? this.width / this.nativeWidth : 1; panelWidth = () => (this.sizeProvider?.width || this.props.PanelWidth?.()); panelHeight = () => (this.sizeProvider?.height || this.props.PanelHeight?.()); - getTransform = (): Transform => this.props.ScreenToLocalTransform() - .translate(-this.X, -this.Y) - .scale(1 / this.contentScaling()) - + getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.X, -this.Y).scale(1 / this.contentScaling()); focusDoc = (doc: Doc) => this.props.focus(doc, false); NativeWidth = () => this.nativeWidth; NativeHeight = () => this.nativeHeight; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 749fb98be..81667e549 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -77,11 +77,11 @@ export class HTMLtag extends React.Component { render() { const style: { [key: string]: any } = {}; const divKeys = OmitKeys(this.props, ["children", "htmltag", "RootDoc", "Document", "key", "onInput", "onClick", "__proto__"]).omit; + const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a propery expression string: { script } into a value + return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ self: this.props.RootDoc, this: this.props.Document }).result as string || ""; + }; Object.keys(divKeys).map((prop: string) => { const p = (this.props as any)[prop] as string; - const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a propery expression string: { script } into a value - return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ self: this.props.RootDoc, this: this.props.Document }).result as string || ""; - }; style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer); }); const Tag = this.props.htmltag as keyof JSX.IntrinsicElements; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 4a75816a8..09047a07a 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -58,6 +58,7 @@ import { FieldView, FieldViewProps } from "../FieldView"; import "./FormattedTextBox.scss"; import { FormattedTextBoxComment, formattedTextBoxCommentPlugin } from './FormattedTextBoxComment'; import React = require("react"); +import { ScriptField } from '../../../../new_fields/ScriptField'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); @@ -1239,6 +1240,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); } render() { TraceMobx(); + const style: { [key: string]: any } = {}; + const divKeys = ["width", "height", "background"]; + const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a propery expression string: { script } into a value + return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ self: this.rootDoc, this: this.layoutDoc }).result as string || ""; + }; + divKeys.map((prop: string) => { + const p = (this.props as any)[prop] as string; + p && (style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer)); + }); const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; const interactive = InkingControl.Instance.selectedTool || this.layoutDoc.isBackground; if (this.props.isSelected()) { @@ -1257,6 +1267,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp pointerEvents: interactive ? "none" : undefined, fontSize: Cast(this.layoutDoc._fontSize, "number", null), fontFamily: StrCast(this.layoutDoc._fontFamily, "inherit"), + ...style }} onContextMenu={this.specificContextMenu} onKeyDown={this.onKeyPress} diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 7f0fd5a8d..a5b84a0a1 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -73,7 +73,9 @@ export class CurrentUserUtils { if (doc["template-button-description"] === undefined) { const descriptionTemplate = Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header"); // text needs to be a space to allow templateText to be created - Doc.GetProto(descriptionTemplate).layout = "
"; + Doc.GetProto(descriptionTemplate).layout = + "
" + + "
"; descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView"); doc["template-button-description"] = CurrentUserUtils.ficon({ -- cgit v1.2.3-70-g09d2 From d9227908ba8e8db5084c468a242b2839ab11a33d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 4 May 2020 12:50:46 -0400 Subject: fixed links and snap lines broken by moving things into DragManager. --- src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 34 ++-- src/client/util/SelectionManager.ts | 3 + src/client/util/SnappingManager.ts | 29 +++ src/client/views/DocumentDecorations.tsx | 5 +- src/client/views/MainView.scss | 9 + src/client/views/MainView.tsx | 18 +- .../views/collections/CollectionDockingView.tsx | 5 +- .../collections/CollectionMasonryViewFieldRow.tsx | 4 +- .../views/collections/CollectionPileView.tsx | 6 +- .../views/collections/CollectionSchemaCells.tsx | 4 +- .../CollectionSchemaMovableTableHOC.tsx | 6 +- .../views/collections/CollectionStackingView.tsx | 7 +- .../CollectionStackingViewFieldColumn.tsx | 6 +- .../views/collections/CollectionTreeView.tsx | 7 +- .../CollectionFreeFormLinkView.tsx | 9 +- .../CollectionFreeFormLinksView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 7 +- src/client/views/nodes/DocHolderBox.scss | 15 ++ src/client/views/nodes/DocHolderBox.tsx | 207 +++++++++++++++++++++ src/client/views/nodes/DocumentBox.scss | 15 -- src/client/views/nodes/DocumentBox.tsx | 207 --------------------- src/client/views/nodes/DocumentContentsView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 3 +- src/client/views/nodes/QueryBox.tsx | 5 +- 25 files changed, 328 insertions(+), 291 deletions(-) create mode 100644 src/client/util/SnappingManager.ts create mode 100644 src/client/views/nodes/DocHolderBox.scss create mode 100644 src/client/views/nodes/DocHolderBox.tsx delete mode 100644 src/client/views/nodes/DocumentBox.scss delete mode 100644 src/client/views/nodes/DocumentBox.tsx (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 45687f597..f5d6cd7f6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -37,7 +37,7 @@ import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { QueryBox } from "../views/nodes/QueryBox"; import { ColorBox } from "../views/nodes/ColorBox"; import { LinkAnchorBox } from "../views/nodes/LinkAnchorBox"; -import { DocHolderBox } from "../views/nodes/DocumentBox"; +import { DocHolderBox } from "../views/nodes/DocHolderBox"; import { InkingStroke } from "../views/InkingStroke"; import { InkField } from "../../new_fields/InkField"; import { InkingControl } from "../views/InkingControl"; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 348aba588..0d208cf1b 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -11,6 +11,7 @@ import { emptyFunction } from "../../Utils"; import { Docs, DocUtils } from "../documents/Documents"; import * as globalCssVariables from "../views/globalCssVariables.scss"; import { UndoManager } from "./UndoManager"; +import { SnappingManager } from "./SnappingManager"; export type dropActionType = "alias" | "copy" | "move" | undefined; // undefined = move export function SetupDrag( @@ -49,7 +50,7 @@ export function SetupDrag( if (e.shiftKey) { e.persist(); const dragDoc = await docFunc(); - dragDoc && DragManager.Vals.Instance.StartWindowDrag?.({ + dragDoc && DragManager.StartWindowDrag?.({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, @@ -66,19 +67,7 @@ export function SetupDrag( export namespace DragManager { let dragDiv: HTMLDivElement; - export class Vals { - static Instance: Vals = new Vals(); - @observable public IsDragging: boolean = false; - @observable public horizSnapLines: number[] = []; - @observable public vertSnapLines: number[] = []; - public StartWindowDrag: Opt<((e: any, dragDocs: Doc[]) => void)> = undefined; - public SetIsDragging(dragging: boolean) { runInAction(() => this.IsDragging = dragging); } - public GetIsDragging() { return this.IsDragging; } - @action public clearSnapLines() { - this.vertSnapLines.length = 0; - this.horizSnapLines.length = 0; - } - } + export let StartWindowDrag: Opt<((e: any, dragDocs: Doc[]) => void)> = undefined; export function Root() { const root = document.getElementById("root"); @@ -267,8 +256,7 @@ export namespace DragManager { } export function SetSnapLines(horizLines: number[], vertLines: number[]) { - DragManager.Vals.Instance.horizSnapLines.push(...horizLines); - DragManager.Vals.Instance.vertSnapLines.push(...vertLines); + SnappingManager.setSnapLines(horizLines, vertLines); } export function snapDrag(e: PointerEvent, xFromLeft: number, yFromTop: number, xFromRight: number, yFromBottom: number) { @@ -286,8 +274,8 @@ export namespace DragManager { }; return { - thisX: snapVal([xFromLeft, xFromRight], e.pageX, DragManager.Vals.Instance.vertSnapLines), - thisY: snapVal([yFromTop, yFromBottom], e.pageY, DragManager.Vals.Instance.horizSnapLines) + thisX: snapVal([xFromLeft, xFromRight], e.pageX, SnappingManager.vertSnapLines()), + thisY: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.horizSnapLines()) }; } export let docsBeingDragged: Doc[] = []; @@ -299,7 +287,7 @@ export namespace DragManager { dragDiv.style.pointerEvents = "none"; DragManager.Root().appendChild(dragDiv); } - DragManager.Vals.Instance.SetIsDragging(true); + SnappingManager.SetIsDragging(true); const scaleXs: number[] = []; const scaleYs: number[] = []; const xs: number[] = []; @@ -388,7 +376,7 @@ export namespace DragManager { } AbortDrag(); finishDrag?.(new DragCompleteEvent(true, dragData)); - DragManager.Vals.Instance.StartWindowDrag?.({ + DragManager.StartWindowDrag?.({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, @@ -415,19 +403,19 @@ export namespace DragManager { const endDrag = action(() => { document.removeEventListener("pointermove", moveHandler, true); document.removeEventListener("pointerup", upHandler); - DragManager.Vals.Instance.clearSnapLines(); + SnappingManager.clearSnapLines(); }); AbortDrag = () => { hideDragShowOriginalElements(); - DragManager.Vals.Instance.SetIsDragging(false); + SnappingManager.SetIsDragging(false); options?.dragComplete?.(new DragCompleteEvent(true, dragData)); endDrag(); }; const upHandler = (e: PointerEvent) => { hideDragShowOriginalElements(); dispatchDrag(eles, e, dragData, xFromLeft, yFromTop, xFromRight, yFromBottom, options, finishDrag); - DragManager.Vals.Instance.SetIsDragging(false); + SnappingManager.SetIsDragging(false); endDrag(); options?.dragComplete?.(new DragCompleteEvent(false, dragData)); }; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index d509168b6..11d2cafb2 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -8,6 +8,7 @@ export namespace SelectionManager { class Manager { + @observable IsDragging: boolean = false; SelectedDocuments: ObservableMap = new ObservableMap(); @action @@ -53,6 +54,8 @@ export namespace SelectionManager { manager.SelectDoc(docView, ctrlPressed); } + export function SetIsDragging(dragging: boolean) { runInAction(() => manager.IsDragging = dragging); } + export function GetIsDragging() { return manager.IsDragging; } // computed functions, such as used in IsSelected generate errors if they're called outside of a // reaction context. Specifying the context with 'outsideReaction' allows an efficiency feature // to avoid unnecessary mobx invalidations when running inside a reaction. diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts new file mode 100644 index 000000000..fc07e8ab4 --- /dev/null +++ b/src/client/util/SnappingManager.ts @@ -0,0 +1,29 @@ +import { observable, action, runInAction } from "mobx"; + +export namespace SnappingManager { + + class Manager { + @observable IsDragging: boolean = false; + @observable public horizSnapLines: number[] = []; + @observable public vertSnapLines: number[] = []; + @action public clearSnapLines() { + this.vertSnapLines = []; + this.horizSnapLines = []; + } + @action public setSnapLines(horizLines: number[], vertLines: number[]) { + this.horizSnapLines = horizLines; + this.vertSnapLines = vertLines; + } + } + + const manager = new Manager(); + + export function clearSnapLines() { manager.clearSnapLines(); } + export function setSnapLines(horizLines: number[], vertLines: number[]) { manager.setSnapLines(horizLines, vertLines); } + export function horizSnapLines() { return manager.horizSnapLines; } + export function vertSnapLines() { return manager.vertSnapLines; } + + export function SetIsDragging(dragging: boolean) { runInAction(() => manager.IsDragging = dragging); } + export function GetIsDragging() { return manager.IsDragging; } +} + diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index f8e77d90a..b89806656 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -21,6 +21,7 @@ import { Id } from '../../new_fields/FieldSymbols'; import e = require('express'); import { CollectionDockingView } from './collections/CollectionDockingView'; import { MainView } from './MainView'; +import { SnappingManager } from '../util/SnappingManager'; library.add(faCaretUp); library.add(faObjectGroup); @@ -364,7 +365,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> this.Interacting = false; (e.button === 0) && this._resizeUndo?.end(); this._resizeUndo = undefined; - DragManager.Vals.Instance.clearSnapLines(); + SnappingManager.clearSnapLines(); } @computed @@ -403,7 +404,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> const darkScheme = Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ? "dimgray" : undefined; const bounds = this.Bounds; const seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; - if (DragManager.Vals.Instance.GetIsDragging() || bounds.r - bounds.x < 2 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { + if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 2 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { return (null); } const minimal = bounds.r - bounds.x < 100 ? true : false; diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 04288a9e1..753ba700c 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -22,6 +22,15 @@ z-index: 1; } +.mainView-snapLines { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events:none; +} + .mainView-container, .mainView-container-dark { input { color: unset !important; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 71c2bf245..9ebd60c52 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -44,6 +44,7 @@ import { PreviewCursor } from './PreviewCursor'; import { ScriptField } from '../../new_fields/ScriptField'; import { TimelineMenu } from './animationtimeline/TimelineMenu'; import { DragManager } from '../util/DragManager'; +import { SnappingManager } from '../util/SnappingManager'; @observer export class MainView extends React.Component { @@ -575,6 +576,15 @@ export class MainView extends React.Component { return this._mainViewRef; } + @computed get snapLines() { + return
+ + {SnappingManager.horizSnapLines().map(l => )} + {SnappingManager.vertSnapLines().map(l => )} + +
+ } + render() { return (
@@ -592,14 +602,8 @@ export class MainView extends React.Component { - {// TO VIEW SNAP LINES -
- - {DragManager.Vals.Instance.horizSnapLines.map((l: any) => )} - {DragManager.Vals.Instance.vertSnapLines.map((l: any) => )} - -
} + {this.snapLines}
); } } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 33ece13cc..6cd5d1b1b 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -30,6 +30,7 @@ import { SubCollectionViewProps } from "./CollectionSubView"; import { DockingViewButtonSelector } from './ParentDocumentSelector'; import React = require("react"); import { CollectionViewType } from './CollectionView'; +import { SnappingManager } from '../../util/SnappingManager'; library.add(faFile); const _global = (window /* browser */ || global /* node */) as any; @@ -68,7 +69,7 @@ export class CollectionDockingView extends React.Component { - if (!this._isPointerDown || !DragManager.Vals.Instance.GetIsDragging()) return; + if (!this._isPointerDown || !SnappingManager.GetIsDragging()) return; const activeContentItem = tab.header.parent.getActiveContentItem(); if (tab.contentItem !== activeContentItem) { tab.header.parent.setActiveContentItem(tab.contentItem); diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index c74cfbcf4..95c7643c9 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -12,12 +12,12 @@ import { numberRange, setupMoveUpEvents, emptyFunction } from "../../../Utils"; import { Docs } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; import { CompileScript } from "../../util/Scripting"; -import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { EditableView } from "../EditableView"; import { CollectionStackingView } from "./CollectionStackingView"; import "./CollectionStackingView.scss"; +import { SnappingManager } from "../../util/SnappingManager"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -132,7 +132,7 @@ export class CollectionMasonryViewFieldRow extends React.Component DragManager.Vals.Instance.GetIsDragging() && (this._background = "#b4b4b4")); + pointerEnteredRow = action(() => SnappingManager.GetIsDragging() && (this._background = "#b4b4b4")); @action pointerLeaveRow = () => { diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index 0a10c24b3..d3ae21f3a 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -12,7 +12,7 @@ import React = require("react"); import { setupMoveUpEvents, emptyFunction, returnFalse } from "../../../Utils"; import { SelectionManager } from "../../util/SelectionManager"; import { UndoManager } from "../../util/UndoManager"; -import { DragManager } from "../../util/DragManager"; +import { SnappingManager } from "../../util/SnappingManager"; @observer export class CollectionPileView extends CollectionSubView(doc => doc) { @@ -79,7 +79,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { _undoBatch: UndoManager.Batch | undefined; pointerDown = (e: React.PointerEvent) => { let dist = 0; - DragManager.Vals.Instance.SetIsDragging(true); + SnappingManager.SetIsDragging(true); // this._lastTap should be set to 0, and this._doubleTap should be set to false in the class header setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => { if (this.layoutEngine() === "pass" && this.childDocs.length && this.props.isSelected(true)) { @@ -99,7 +99,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { }, () => { this._undoBatch?.end(); this._undoBatch = undefined; - DragManager.Vals.Instance.SetIsDragging(false); + SnappingManager.SetIsDragging(false); if (!this.childDocs.length) { this.props.ContainingCollectionView?.removeDocument(this.props.Document); } diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 0e6489947..5253ee0b9 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -18,11 +18,11 @@ import "./CollectionSchemaView.scss"; import { CollectionView } from "./CollectionView"; import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../new_fields/Types"; import { Docs } from "../../documents/Documents"; -import { SelectionManager } from "../../util/SelectionManager"; import { library } from '@fortawesome/fontawesome-svg-core'; import { faExpand } from '@fortawesome/free-solid-svg-icons'; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { undoBatch } from "../../util/UndoManager"; +import { SnappingManager } from "../../util/SnappingManager"; library.add(faExpand); @@ -189,7 +189,7 @@ export class CollectionSchemaCell extends React.Component { this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); }; const onPointerEnter = (e: React.PointerEvent): void => { - if (e.buttons === 1 && DragManager.Vals.Instance.GetIsDragging() && (type === "document" || type === undefined)) { + if (e.buttons === 1 && SnappingManager.GetIsDragging() && (type === "document" || type === undefined)) { dragRef.current!.className = "collectionSchemaView-cellContainer doc-drag-over"; } }; diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index f9cd9a628..8636e3eb5 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -4,7 +4,6 @@ import "./CollectionSchemaView.scss"; import { Transform } from "../../util/Transform"; import { Doc } from "../../../new_fields/Doc"; import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager"; -import { SelectionManager } from "../../util/SelectionManager"; import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { ContextMenu } from "../ContextMenu"; import { action } from "mobx"; @@ -14,6 +13,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { DocumentManager } from "../../util/DocumentManager"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { undoBatch } from "../../util/UndoManager"; +import { SnappingManager } from "../../util/SnappingManager"; library.add(faGripVertical, faTrash); @@ -32,7 +32,7 @@ export class MovableColumn extends React.Component { private _dragRef: React.RefObject = React.createRef(); onPointerEnter = (e: React.PointerEvent): void => { - if (e.buttons === 1 && DragManager.Vals.Instance.GetIsDragging()) { + if (e.buttons === 1 && SnappingManager.GetIsDragging()) { this._header!.current!.className = "collectionSchema-col-wrapper"; document.addEventListener("pointermove", this.onDragMove, true); } @@ -143,7 +143,7 @@ export class MovableRow extends React.Component { private _rowDropDisposer?: DragManager.DragDropDisposer; onPointerEnter = (e: React.PointerEvent): void => { - if (e.buttons === 1 && DragManager.Vals.Instance.GetIsDragging()) { + if (e.buttons === 1 && SnappingManager.GetIsDragging()) { this._header!.current!.className = "collectionSchema-row-wrapper"; document.addEventListener("pointermove", this.onDragMove, true); } diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index f6cdebc9b..b6faea845 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -14,7 +14,6 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../new_field import { TraceMobx } from "../../../new_fields/util"; import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from "../../../Utils"; import { DragManager, dropActionType } from "../../util/DragManager"; -import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { ContextMenu } from "../ContextMenu"; @@ -26,7 +25,7 @@ import "./CollectionStackingView.scss"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionViewType } from "./CollectionView"; -import { ScriptField } from "../../../new_fields/ScriptField"; +import { SnappingManager } from "../../util/SnappingManager"; const _global = (window /* browser */ || global /* node */) as any; type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>; @@ -312,7 +311,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) this.refList.push(ref); const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; this.observer = new _global.ResizeObserver(action((entries: any) => { - if (this.props.Document._autoHeight && ref && this.refList.length && !DragManager.Vals.Instance.GetIsDragging()) { + if (this.props.Document._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { Doc.Layout(doc)._height = Math.min(1200, Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))); } })); @@ -359,7 +358,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) this.refList.push(ref); const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; this.observer = new _global.ResizeObserver(action((entries: any) => { - if (this.props.Document._autoHeight && ref && this.refList.length && !DragManager.Vals.Instance.GetIsDragging()) { + if (this.props.Document._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { Doc.Layout(doc)._height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); } })); diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 1d16a5478..dccef7983 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -13,7 +13,6 @@ import { ImageField } from "../../../new_fields/URLField"; import { TraceMobx } from "../../../new_fields/util"; import { Docs, DocUtils } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; -import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { ContextMenu } from "../ContextMenu"; @@ -23,6 +22,7 @@ import { CollectionStackingView } from "./CollectionStackingView"; import { setupMoveUpEvents, emptyFunction } from "../../../Utils"; import "./CollectionStackingView.scss"; import { listSpec } from "../../../new_fields/Schema"; +import { SnappingManager } from "../../util/SnappingManager"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -120,7 +120,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { - if (DragManager.Vals.Instance.GetIsDragging()) { + if (SnappingManager.GetIsDragging()) { this._background = "#b4b4b4"; } } @@ -355,7 +355,7 @@ export class CollectionStackingViewFieldColumn extends React.Component diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 288fa8794..f2b0e3155 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -6,6 +6,7 @@ import { observer } from "mobx-react"; import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; +import { PrefetchProxy } from '../../../new_fields/Proxy'; import { Document, listSpec } from '../../../new_fields/Schema'; import { ComputedField, ScriptField } from '../../../new_fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../new_fields/Types'; @@ -13,6 +14,7 @@ import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZer import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from '../../util/DocumentManager'; +import { SnappingManager } from '../../util/SnappingManager'; import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager"; import { Scripting } from '../../util/Scripting'; import { SelectionManager } from '../../util/SelectionManager'; @@ -31,7 +33,6 @@ import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import { CollectionViewType } from './CollectionView'; import React = require("react"); -import { PrefetchProxy } from '../../../new_fields/Proxy'; export interface TreeViewProps { @@ -147,7 +148,7 @@ class TreeView extends React.Component { onPointerEnter = (e: React.PointerEvent): void => { this.props.active(true) && Doc.BrushDoc(this.dataDoc); - if (e.buttons === 1 && DragManager.Vals.Instance.GetIsDragging()) { + if (e.buttons === 1 && SnappingManager.GetIsDragging()) { this._header!.current!.className = "treeViewItem-header"; document.addEventListener("pointermove", this.onDragMove, true); } @@ -451,7 +452,7 @@ class TreeView extends React.Component { fontWeight: this.props.document.searchMatch ? "bold" : undefined, textDecoration: Doc.GetT(this.props.document, "title", "string", true) ? "underline" : undefined, outline: BoolCast(this.props.document.workspaceBrush) ? "dashed 1px #06123232" : undefined, - pointerEvents: this.props.active() || DragManager.Vals.Instance.GetIsDragging() ? undefined : "none" + pointerEvents: this.props.active() || SnappingManager.GetIsDragging() ? undefined : "none" }} > {Doc.GetT(this.props.document, "editTitle", "boolean", true) ? this.editableView("title") : diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 0c9a1aa9a..695898ca9 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -9,7 +9,7 @@ import { DocumentType } from "../../../documents/DocumentTypes"; import { observable, action, reaction, IReactionDisposer } from "mobx"; import { StrCast } from "../../../../new_fields/Types"; import { Id } from "../../../../new_fields/FieldSymbols"; -import { DragManager } from "../../../util/DragManager"; +import { SnappingManager } from "../../../util/SnappingManager"; export interface CollectionFreeFormLinkViewProps { A: DocumentView; @@ -25,7 +25,7 @@ export class CollectionFreeFormLinkView extends React.Component [this.props.A.props.ScreenToLocalTransform(), this.props.B.props.ScreenToLocalTransform(), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document)], action(() => { - if (DragManager.Vals.Instance.GetIsDragging()) return; + if (SnappingManager.GetIsDragging()) return; setTimeout(action(() => this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!this.props.LinkDocs.length || !this.props.LinkDocs[0].linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont") : []; @@ -83,7 +83,7 @@ export class CollectionFreeFormLinkView extends React.Component - + {text !== "-ungrouped-" ? text : ""} + return SnappingManager.GetIsDragging() ? (null) :
{this.uniqueConnections} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2aa9b1f5f..37957b0f6 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -45,6 +45,7 @@ import { MarqueeView } from "./MarqueeView"; import React = require("react"); import { CollectionViewType } from "../CollectionView"; import { Timeline } from "../../animationtimeline/Timeline"; +import { SnappingManager } from "../../../util/SnappingManager"; library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); @@ -1174,7 +1175,7 @@ export class CollectionFreeFormView extends CollectionSubView { - if (DragManager.Vals.Instance.GetIsDragging()) { + if (SnappingManager.GetIsDragging()) { this.setupDragLines(); } e.stopPropagation(); @@ -1233,7 +1234,7 @@ export class CollectionFreeFormView extends CollectionSubView; +const DocHolderBoxDocument = makeInterface(documentSchema, collectionSchema); + +@observer +export class DocHolderBox extends ViewBoxAnnotatableComponent(DocHolderBoxDocument) { + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocHolderBox, fieldKey); } + _prevSelectionDisposer: IReactionDisposer | undefined; + _dropDisposer?: DragManager.DragDropDisposer; + _selections: Doc[] = []; + _contRef = React.createRef(); + _curSelection = -1; + componentDidMount() { + this._prevSelectionDisposer = reaction(() => this.layoutDoc[this.props.fieldKey], (data) => { + if (data instanceof Doc && !this.isSelectionLocked()) { + this._selections.indexOf(data) !== -1 && this._selections.splice(this._selections.indexOf(data), 1); + this._selections.push(data); + this._curSelection = this._selections.length - 1; + } + }); + } + componentWillUnmount() { + this._prevSelectionDisposer?.(); + } + specificContextMenu = (e: React.MouseEvent): void => { + const funcs: ContextMenuProps[] = []; + funcs.push({ description: (this.isSelectionLocked() ? "Show" : "Lock") + " Selection", event: () => this.toggleLockSelection, icon: "expand-arrows-alt" }); + funcs.push({ description: (this.layoutDoc.excludeCollections ? "Include" : "Exclude") + " Collections", event: () => this.layoutDoc.excludeCollections = !this.layoutDoc.excludeCollections, icon: "expand-arrows-alt" }); + funcs.push({ description: `${this.layoutDoc.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.layoutDoc.forceActive = !this.layoutDoc.forceActive, icon: "project-diagram" }); + funcs.push({ description: `Show ${this.layoutDoc.childLayoutTemplateName !== "keyValue" ? "key values" : "contents"}`, event: () => this.layoutDoc.childLayoutString = this.layoutDoc.childLayoutString ? undefined : "", icon: "project-diagram" }); + + ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); + } + lockSelection = () => { + this.layoutDoc[this.props.fieldKey] = this.layoutDoc[this.props.fieldKey]; + } + showSelection = () => { + this.layoutDoc[this.props.fieldKey] = ComputedField.MakeFunction(`selectedDocs(self,this.excludeCollections,[_last_])?.[0]`); + } + isSelectionLocked = () => { + const kvpstring = Field.toKeyValueString(this.layoutDoc, this.props.fieldKey); + return !kvpstring || kvpstring.includes("DOC"); + } + toggleLockSelection = () => { + !this.isSelectionLocked() ? this.lockSelection() : this.showSelection(); + return true; + } + prevSelection = () => { + this.lockSelection(); + if (this._curSelection > 0) { + this.layoutDoc[this.props.fieldKey] = this._selections[--this._curSelection]; + return true; + } + } + nextSelection = () => { + if (this._curSelection < this._selections.length - 1 && this._selections.length) { + this.layoutDoc[this.props.fieldKey] = this._selections[++this._curSelection]; + return true; + } + } + onPointerDown = (e: React.PointerEvent) => { + if (this.active() && e.button === 0 && !e.ctrlKey) { + e.stopPropagation(); + } + } + onLockClick = (e: React.MouseEvent) => { + this.toggleLockSelection(); + (e.nativeEvent as any).formattedHandled = true; + e.stopPropagation(); + } + get xPad() { return NumCast(this.props.Document._xPadding); } + get yPad() { return NumCast(this.props.Document._yPadding); } + onClick = (e: React.MouseEvent) => { + let hitWidget: boolean | undefined = false; + if (this._contRef.current!.getBoundingClientRect().top + this.yPad > e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); + else if (this._contRef.current!.getBoundingClientRect().bottom - this.yPad < e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); + else { + if (this._contRef.current!.getBoundingClientRect().left + this.xPad > e.clientX) hitWidget = this.prevSelection(); + if (this._contRef.current!.getBoundingClientRect().right - this.xPad < e.clientX) hitWidget = this.nextSelection(); + } + if (hitWidget) { + (e.nativeEvent as any).formattedHandled = true; + e.stopPropagation(); + } + } + pwidth = () => this.props.PanelWidth() - 2 * this.xPad; + pheight = () => this.props.PanelHeight() - 2 * this.yPad; + getTransform = () => this.props.ScreenToLocalTransform().translate(-this.xPad, -this.yPad); + isActive = () => this.active() || !this.props.renderDepth; + layoutTemplateDoc = () => Cast(this.props.Document.childLayoutTemplate, Doc, null); + get renderContents() { + const containedDoc = Cast(this.dataDoc[this.props.fieldKey], Doc, null); + const layoutTemplate = StrCast(this.layoutDoc.childLayoutString); + const contents = !(containedDoc instanceof Doc) ? (null) : this.layoutDoc.childLayoutString || this.layoutTemplateDoc() ? + : + ; + return contents; + } + render() { + TraceMobx(); + return
+ {this.renderContents} +
+ +
+
; + } + + @undoBatch + @action + drop = (e: Event, de: DragManager.DropEvent) => { + if (de.complete.docDragData) { + if (de.complete.docDragData.draggedDocuments[0].type === DocumentType.FONTICON) { + const doc = Cast(de.complete.docDragData.draggedDocuments[0].dragFactory, Doc, null); + this.props.Document.childLayoutTemplate = doc; + } + } + } + protected createDropTarget = (ele: HTMLDivElement) => { + this._dropDisposer?.(); + ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document)); + } + +} diff --git a/src/client/views/nodes/DocumentBox.scss b/src/client/views/nodes/DocumentBox.scss deleted file mode 100644 index 3a27c16c1..000000000 --- a/src/client/views/nodes/DocumentBox.scss +++ /dev/null @@ -1,15 +0,0 @@ -.documentBox-container { - width: 100%; - height: 100%; - pointer-events: all; - background: rgb(241, 239, 235); - position: absolute; - .documentBox-lock { - margin: auto; - color: white; - position: absolute; - } - .contentFittingDocumentView { - position: absolute; - } -} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx deleted file mode 100644 index b53c7cfe6..000000000 --- a/src/client/views/nodes/DocumentBox.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, IReactionDisposer, reaction } from "mobx"; -import { observer } from "mobx-react"; -import { Doc, Field } from "../../../new_fields/Doc"; -import { collectionSchema, documentSchema } from "../../../new_fields/documentSchemas"; -import { makeInterface } from "../../../new_fields/Schema"; -import { ComputedField } from "../../../new_fields/ScriptField"; -import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; -import { TraceMobx } from "../../../new_fields/util"; -import { emptyPath, returnFalse, returnOne, returnZero } from "../../../Utils"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { DragManager } from "../../util/DragManager"; -import { undoBatch } from "../../util/UndoManager"; -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; -import { ViewBoxAnnotatableComponent } from "../DocComponent"; -import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; -import "./DocumentBox.scss"; -import { DocumentView } from "./DocumentView"; -import { FieldView, FieldViewProps } from "./FieldView"; -import React = require("react"); - -type DocHolderBoxSchema = makeInterface<[typeof documentSchema, typeof collectionSchema]>; -const DocHolderBoxDocument = makeInterface(documentSchema, collectionSchema); - -@observer -export class DocHolderBox extends ViewBoxAnnotatableComponent(DocHolderBoxDocument) { - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocHolderBox, fieldKey); } - _prevSelectionDisposer: IReactionDisposer | undefined; - _dropDisposer?: DragManager.DragDropDisposer; - _selections: Doc[] = []; - _contRef = React.createRef(); - _curSelection = -1; - componentDidMount() { - this._prevSelectionDisposer = reaction(() => this.layoutDoc[this.props.fieldKey], (data) => { - if (data instanceof Doc && !this.isSelectionLocked()) { - this._selections.indexOf(data) !== -1 && this._selections.splice(this._selections.indexOf(data), 1); - this._selections.push(data); - this._curSelection = this._selections.length - 1; - } - }); - } - componentWillUnmount() { - this._prevSelectionDisposer?.(); - } - specificContextMenu = (e: React.MouseEvent): void => { - const funcs: ContextMenuProps[] = []; - funcs.push({ description: (this.isSelectionLocked() ? "Show" : "Lock") + " Selection", event: () => this.toggleLockSelection, icon: "expand-arrows-alt" }); - funcs.push({ description: (this.layoutDoc.excludeCollections ? "Include" : "Exclude") + " Collections", event: () => this.layoutDoc.excludeCollections = !this.layoutDoc.excludeCollections, icon: "expand-arrows-alt" }); - funcs.push({ description: `${this.layoutDoc.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.layoutDoc.forceActive = !this.layoutDoc.forceActive, icon: "project-diagram" }); - funcs.push({ description: `Show ${this.layoutDoc.childLayoutTemplateName !== "keyValue" ? "key values" : "contents"}`, event: () => this.layoutDoc.childLayoutString = this.layoutDoc.childLayoutString ? undefined : "", icon: "project-diagram" }); - - ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); - } - lockSelection = () => { - this.layoutDoc[this.props.fieldKey] = this.layoutDoc[this.props.fieldKey]; - } - showSelection = () => { - this.layoutDoc[this.props.fieldKey] = ComputedField.MakeFunction(`selectedDocs(self,this.excludeCollections,[_last_])?.[0]`); - } - isSelectionLocked = () => { - const kvpstring = Field.toKeyValueString(this.layoutDoc, this.props.fieldKey); - return !kvpstring || kvpstring.includes("DOC"); - } - toggleLockSelection = () => { - !this.isSelectionLocked() ? this.lockSelection() : this.showSelection(); - return true; - } - prevSelection = () => { - this.lockSelection(); - if (this._curSelection > 0) { - this.layoutDoc[this.props.fieldKey] = this._selections[--this._curSelection]; - return true; - } - } - nextSelection = () => { - if (this._curSelection < this._selections.length - 1 && this._selections.length) { - this.layoutDoc[this.props.fieldKey] = this._selections[++this._curSelection]; - return true; - } - } - onPointerDown = (e: React.PointerEvent) => { - if (this.active() && e.button === 0 && !e.ctrlKey) { - e.stopPropagation(); - } - } - onLockClick = (e: React.MouseEvent) => { - this.toggleLockSelection(); - (e.nativeEvent as any).formattedHandled = true; - e.stopPropagation(); - } - get xPad() { return NumCast(this.props.Document._xPadding); } - get yPad() { return NumCast(this.props.Document._yPadding); } - onClick = (e: React.MouseEvent) => { - let hitWidget: boolean | undefined = false; - if (this._contRef.current!.getBoundingClientRect().top + this.yPad > e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); - else if (this._contRef.current!.getBoundingClientRect().bottom - this.yPad < e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); - else { - if (this._contRef.current!.getBoundingClientRect().left + this.xPad > e.clientX) hitWidget = this.prevSelection(); - if (this._contRef.current!.getBoundingClientRect().right - this.xPad < e.clientX) hitWidget = this.nextSelection(); - } - if (hitWidget) { - (e.nativeEvent as any).formattedHandled = true; - e.stopPropagation(); - } - } - pwidth = () => this.props.PanelWidth() - 2 * this.xPad; - pheight = () => this.props.PanelHeight() - 2 * this.yPad; - getTransform = () => this.props.ScreenToLocalTransform().translate(-this.xPad, -this.yPad); - isActive = () => this.active() || !this.props.renderDepth; - layoutTemplateDoc = () => Cast(this.props.Document.childLayoutTemplate, Doc, null); - get renderContents() { - const containedDoc = Cast(this.dataDoc[this.props.fieldKey], Doc, null); - const layoutTemplate = StrCast(this.layoutDoc.childLayoutString); - const contents = !(containedDoc instanceof Doc) ? (null) : this.layoutDoc.childLayoutString || this.layoutTemplateDoc() ? - : - ; - return contents; - } - render() { - TraceMobx(); - return
- {this.renderContents} -
- -
-
; - } - - @undoBatch - @action - drop = (e: Event, de: DragManager.DropEvent) => { - if (de.complete.docDragData) { - if (de.complete.docDragData.draggedDocuments[0].type === DocumentType.FONTICON) { - const doc = Cast(de.complete.docDragData.draggedDocuments[0].dragFactory, Doc, null); - this.props.Document.childLayoutTemplate = doc; - } - } - } - protected createDropTarget = (ele: HTMLDivElement) => { - this._dropDisposer?.(); - ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document)); - } - -} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 81667e549..395a6e0b2 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -14,7 +14,7 @@ import { LabelBox } from "./LabelBox"; import { SliderBox } from "./SliderBox"; import { LinkBox } from "./LinkBox"; import { ScriptingBox } from "./ScriptingBox"; -import { DocHolderBox } from "./DocumentBox"; +import { DocHolderBox } from "./DocHolderBox"; import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import { FontIconBox } from "./FontIconBox"; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7a81801e1..86e58ca7a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -23,6 +23,7 @@ import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; import { ClientUtils } from '../../util/ClientUtils'; import { DocumentManager } from "../../util/DocumentManager"; +import { SnappingManager } from '../../util/SnappingManager'; import { DragManager, dropActionType } from "../../util/DragManager"; import { InteractionUtils } from '../../util/InteractionUtils'; import { Scripting } from '../../util/Scripting'; @@ -1105,7 +1106,7 @@ export class DocumentView extends DocComponent(Docu } @computed get ignorePointerEvents() { return this.props.pointerEvents === false || - (this.Document.isBackground && !this.isSelected() && !DragManager.Vals.Instance.GetIsDragging()) || + (this.Document.isBackground && !this.isSelected() && !SnappingManager.GetIsDragging()) || (this.Document.type === DocumentType.INK && InkingControl.Instance.selectedTool !== InkTool.None); } @undoBatch diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx index d248b098c..2a21a380d 100644 --- a/src/client/views/nodes/QueryBox.tsx +++ b/src/client/views/nodes/QueryBox.tsx @@ -5,13 +5,12 @@ import { documentSchema } from "../../../new_fields/documentSchemas"; import { Id } from '../../../new_fields/FieldSymbols'; import { makeInterface, listSpec } from "../../../new_fields/Schema"; import { StrCast, Cast } from "../../../new_fields/Types"; -import { SelectionManager } from "../../util/SelectionManager"; import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { SearchBox } from "../search/SearchBox"; import { FieldView, FieldViewProps } from './FieldView'; import "./QueryBox.scss"; import { List } from "../../../new_fields/List"; -import { DragManager } from "../../util/DragManager"; +import { SnappingManager } from "../../util/SnappingManager"; type QueryDocument = makeInterface<[typeof documentSchema]>; const QueryDocument = makeInterface(documentSchema); @@ -28,7 +27,7 @@ export class QueryBox extends ViewBoxAnnotatableComponent e.stopPropagation()} > Date: Tue, 5 May 2020 01:36:00 -0400 Subject: fixes for parameterized templates. added a pendingMap to fix issues with expandTemplateLayout. added a switchbox template to test templates. changed dimUnits/dimMagnitude to _dimUnits/_dimMagnitude --- src/Utils.ts | 8 ++++++-- src/client/documents/Documents.ts | 9 ++++----- .../CollectionMulticolumnView.tsx | 22 +++++++++++----------- .../CollectionMultirowView.tsx | 22 +++++++++++----------- .../collectionMulticolumn/MulticolumnResizer.tsx | 14 +++++++------- .../collectionMulticolumn/MultirowResizer.tsx | 14 +++++++------- src/client/views/nodes/DocumentContentsView.tsx | 2 +- .../views/nodes/formattedText/DashFieldView.tsx | 14 +++++++++----- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/client/views/nodes/formattedText/nodes_rts.ts | 3 ++- src/new_fields/Doc.ts | 9 +++++++-- .../authentication/models/current_user_utils.ts | 19 ++++++++++++++++--- 12 files changed, 82 insertions(+), 56 deletions(-) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 23b59ac9d..732f74bfc 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -313,14 +313,18 @@ export namespace Utils { } } -export function OmitKeys(obj: any, keys: string[], addKeyFunc?: (dup: any) => void): { omit: any, extract: any } { +export function OmitKeys(obj: any, keys: string[], pattern?: string, addKeyFunc?: (dup: any) => void): { omit: any, extract: any } { const omit: any = { ...obj }; const extract: any = {}; keys.forEach(key => { extract[key] = omit[key]; delete omit[key]; }); - addKeyFunc && addKeyFunc(omit); + pattern && Array.from(Object.keys(omit)).filter(key => key.match(pattern)).forEach(key => { + extract[key] = omit[key]; + delete omit[key]; + }) + addKeyFunc?.(omit); return { omit, extract }; } diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f5d6cd7f6..a87a77e1d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -58,6 +58,8 @@ export interface DocumentOptions { _height?: number; _nativeWidth?: number; _nativeHeight?: number; + _dimMagnitude?: number; // magnitude of collectionMulti{row,col} view element + _dimUnit?: string; // "px" or "*" (default = "*") _fitWidth?: boolean; _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents _LODdisable?: boolean; @@ -455,10 +457,7 @@ export namespace Docs { Scripting.addGlobal(Buxton); - const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "dropAction", "childDropAction", "_annotationOn", - "_chromeStatus", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", "_backgroundColor", - "_xMargin", "_yMargin", "_xPadding", "_yPadding", "_singleLine", "_scrollTop", - "_color", "isLinkButton", "isBackground", "removeDropProperties", "treeViewOpen"]; + const delegateKeys = ["x", "y", "layoutKey", "dropAction", "childDropAction", "isLinkButton", "isBackground", "removeDropProperties", "treeViewOpen"]; /** * This function receives the relevant document prototype and uses @@ -479,7 +478,7 @@ export namespace Docs { * main document. */ export function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = "data") { - const { omit: protoProps, extract: delegateProps } = OmitKeys(options, delegateKeys); + const { omit: protoProps, extract: delegateProps } = OmitKeys(options, delegateKeys, "^_"); if (!("author" in protoProps)) { protoProps.author = Doc.CurrentUserEmail; diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 38b16e184..a09124304 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -46,12 +46,12 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu */ @computed private get ratioDefinedDocs() { - return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout.dimUnit, "*") === DimUnit.Ratio); + return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, "*") === DimUnit.Ratio); } /** - * This loops through all childLayoutPairs and extracts the values for dimUnit - * and dimMagnitude, ignoring any that are malformed. Additionally, it then + * This loops through all childLayoutPairs and extracts the values for _dimUnit + * and _dimMagnitude, ignoring any that are malformed. Additionally, it then * normalizes the ratio values so that one * value is always 1, with the remaining * values proportionate to that easily readable metric. * @returns the list of the resolved width specifiers (unit and magnitude pairs) @@ -62,8 +62,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu let starSum = 0; const widthSpecifiers: WidthSpecifier[] = []; this.childLayoutPairs.map(pair => { - const unit = StrCast(pair.layout.dimUnit, "*"); - const magnitude = NumCast(pair.layout.dimMagnitude, 1); + const unit = StrCast(pair.layout._dimUnit, "*"); + const magnitude = NumCast(pair.layout._dimMagnitude, 1); if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) { (unit === DimUnit.Ratio) && (starSum += magnitude); widthSpecifiers.push({ magnitude, unit }); @@ -83,9 +83,9 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu setTimeout(() => { const { ratioDefinedDocs } = this; if (this.childLayoutPairs.length) { - const minimum = Math.min(...ratioDefinedDocs.map(doc => NumCast(doc.dimMagnitude, 1))); + const minimum = Math.min(...ratioDefinedDocs.map(doc => NumCast(doc._dimMagnitude, 1))); if (minimum !== 0) { - ratioDefinedDocs.forEach(layout => layout.dimMagnitude = NumCast(layout.dimMagnitude, 1) / minimum, 1); + ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum, 1); } } }); @@ -161,8 +161,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu if (columnUnitLength === undefined) { return 0; // we're still waiting on promises to resolve } - let width = NumCast(layout.dimMagnitude, 1); - if (StrCast(layout.dimUnit, "*") === DimUnit.Ratio) { + let width = NumCast(layout._dimMagnitude, 1); + if (StrCast(layout._dimUnit, "*") === DimUnit.Ratio) { width *= columnUnitLength; } return width; @@ -194,8 +194,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu onInternalDrop = (e: Event, de: DragManager.DropEvent) => { if (super.onInternalDrop(e, de)) { de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => { - d.dimUnit = "*"; - d.dimMagnitude = 1; + d._dimUnit = "*"; + d._dimMagnitude = 1; })); } return false; diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index b55b67a9e..4326723b1 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -46,12 +46,12 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) */ @computed private get ratioDefinedDocs() { - return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout.dimUnit, "*") === DimUnit.Ratio); + return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, "*") === DimUnit.Ratio); } /** - * This loops through all childLayoutPairs and extracts the values for dimUnit - * and dimUnit, ignoring any that are malformed. Additionally, it then + * This loops through all childLayoutPairs and extracts the values for _dimUnit + * and _dimUnit, ignoring any that are malformed. Additionally, it then * normalizes the ratio values so that one * value is always 1, with the remaining * values proportionate to that easily readable metric. * @returns the list of the resolved width specifiers (unit and magnitude pairs) @@ -62,8 +62,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) let starSum = 0; const heightSpecifiers: HeightSpecifier[] = []; this.childLayoutPairs.map(pair => { - const unit = StrCast(pair.layout.dimUnit, "*"); - const magnitude = NumCast(pair.layout.dimMagnitude, 1); + const unit = StrCast(pair.layout._dimUnit, "*"); + const magnitude = NumCast(pair.layout._dimMagnitude, 1); if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) { (unit === DimUnit.Ratio) && (starSum += magnitude); heightSpecifiers.push({ magnitude, unit }); @@ -83,9 +83,9 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) setTimeout(() => { const { ratioDefinedDocs } = this; if (this.childLayoutPairs.length) { - const minimum = Math.min(...ratioDefinedDocs.map(layout => NumCast(layout.dimMagnitude, 1))); + const minimum = Math.min(...ratioDefinedDocs.map(layout => NumCast(layout._dimMagnitude, 1))); if (minimum !== 0) { - ratioDefinedDocs.forEach(layout => layout.dimMagnitude = NumCast(layout.dimMagnitude, 1) / minimum); + ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum); } } }); @@ -161,8 +161,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) if (rowUnitLength === undefined) { return 0; // we're still waiting on promises to resolve } - let height = NumCast(layout.dimMagnitude, 1); - if (StrCast(layout.dimUnit, "*") === DimUnit.Ratio) { + let height = NumCast(layout._dimMagnitude, 1); + if (StrCast(layout._dimUnit, "*") === DimUnit.Ratio) { height *= rowUnitLength; } return height; @@ -194,8 +194,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) onInternalDrop = (e: Event, de: DragManager.DropEvent) => { if (super.onInternalDrop(e, de)) { de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => { - d.dimUnit = "*"; - d.dimMagnitude = 1; + d._dimUnit = "*"; + d._dimMagnitude = 1; })); } return false; diff --git a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx index e1e604686..a24eb1631 100644 --- a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx +++ b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx @@ -43,12 +43,12 @@ export default class ResizeBar extends React.Component { const unitLength = columnUnitLength(); if (unitLength) { if (toNarrow) { - const scale = StrCast(toNarrow.dimUnit, "*") === DimUnit.Ratio ? unitLength : 1; - toNarrow.dimMagnitude = Math.max(0.05, NumCast(toNarrow.dimMagnitude, 1) - Math.abs(movementX) / scale); + const scale = StrCast(toNarrow._dimUnit, "*") === DimUnit.Ratio ? unitLength : 1; + toNarrow._dimMagnitude = Math.max(0.05, NumCast(toNarrow._dimMagnitude, 1) - Math.abs(movementX) / scale); } if (toWiden) { - const scale = StrCast(toWiden.dimUnit, "*") === DimUnit.Ratio ? unitLength : 1; - toWiden.dimMagnitude = Math.max(0.05, NumCast(toWiden.dimMagnitude, 1) + Math.abs(movementX) / scale); + const scale = StrCast(toWiden._dimUnit, "*") === DimUnit.Ratio ? unitLength : 1; + toWiden._dimMagnitude = Math.max(0.05, NumCast(toWiden._dimMagnitude, 1) + Math.abs(movementX) / scale); } } } @@ -56,17 +56,17 @@ export default class ResizeBar extends React.Component { private get isActivated() { const { toLeft, toRight } = this.props; if (toLeft && toRight) { - if (StrCast(toLeft.dimUnit, "*") === DimUnit.Pixel && StrCast(toRight.dimUnit, "*") === DimUnit.Pixel) { + if (StrCast(toLeft._dimUnit, "*") === DimUnit.Pixel && StrCast(toRight._dimUnit, "*") === DimUnit.Pixel) { return false; } return true; } else if (toLeft) { - if (StrCast(toLeft.dimUnit, "*") === DimUnit.Pixel) { + if (StrCast(toLeft._dimUnit, "*") === DimUnit.Pixel) { return false; } return true; } else if (toRight) { - if (StrCast(toRight.dimUnit, "*") === DimUnit.Pixel) { + if (StrCast(toRight._dimUnit, "*") === DimUnit.Pixel) { return false; } return true; diff --git a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx index 9df8cc3e2..5f00b18b9 100644 --- a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx +++ b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx @@ -41,12 +41,12 @@ export default class ResizeBar extends React.Component { const unitLength = columnUnitLength(); if (unitLength) { if (toNarrow) { - const scale = StrCast(toNarrow.dimUnit, "*") === DimUnit.Ratio ? unitLength : 1; - toNarrow.dimMagnitude = Math.max(0.05, NumCast(toNarrow.dimMagnitude, 1) - Math.abs(movementY) / scale); + const scale = StrCast(toNarrow._dimUnit, "*") === DimUnit.Ratio ? unitLength : 1; + toNarrow._dimMagnitude = Math.max(0.05, NumCast(toNarrow._dimMagnitude, 1) - Math.abs(movementY) / scale); } if (toWiden) { - const scale = StrCast(toWiden.dimUnit, "*") === DimUnit.Ratio ? unitLength : 1; - toWiden.dimMagnitude = Math.max(0.05, NumCast(toWiden.dimMagnitude, 1) + Math.abs(movementY) / scale); + const scale = StrCast(toWiden._dimUnit, "*") === DimUnit.Ratio ? unitLength : 1; + toWiden._dimMagnitude = Math.max(0.05, NumCast(toWiden._dimMagnitude, 1) + Math.abs(movementY) / scale); } } } @@ -54,17 +54,17 @@ export default class ResizeBar extends React.Component { private get isActivated() { const { toTop, toBottom } = this.props; if (toTop && toBottom) { - if (StrCast(toTop.dimUnit, "*") === DimUnit.Pixel && StrCast(toBottom.dimUnit, "*") === DimUnit.Pixel) { + if (StrCast(toTop._dimUnit, "*") === DimUnit.Pixel && StrCast(toBottom._dimUnit, "*") === DimUnit.Pixel) { return false; } return true; } else if (toTop) { - if (StrCast(toTop.dimUnit, "*") === DimUnit.Pixel) { + if (StrCast(toTop._dimUnit, "*") === DimUnit.Pixel) { return false; } return true; } else if (toBottom) { - if (StrCast(toBottom.dimUnit, "*") === DimUnit.Pixel) { + if (StrCast(toBottom._dimUnit, "*") === DimUnit.Pixel) { return false; } return true; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 395a6e0b2..2fc82e524 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -135,7 +135,7 @@ export class DocumentContentsView extends React.Component, onInput: Opt): JsxBindings { const list = { - ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit, + ...OmitKeys(this.props, ['parentActive'], "", (obj: any) => obj.active = this.props.parentActive).omit, RootDoc: Cast(this.layoutDoc?.rootDocument, Doc, null) || this.layoutDoc, Document: this.layoutDoc, DataDoc: this.dataDoc, diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index d87d6e424..f28057fd7 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -34,6 +34,7 @@ export class DashFieldView { docid={node.attrs.docid} width={node.attrs.width} height={node.attrs.height} + hideKey={node.attrs.hideKey} tbox={tbox} />, this._fieldWrapper); (this as any).dom = this._fieldWrapper; @@ -47,6 +48,7 @@ export class DashFieldView { interface IDashFieldViewInternal { fieldKey: string; docid: string; + hideKey: boolean; tbox: FormattedTextBox; width: number; height: number; @@ -80,7 +82,7 @@ export class DashFieldViewInternal extends React.Component - - {this._fieldKey} - + {this.props.hideKey ? (null) : + + {this._fieldKey} + }
{this.fieldValueContent} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 658a55f51..f5c28b350 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -205,7 +205,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) { this._applyingChange = true; this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); - if ((!curTemp && !curProto) || curText) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) + if ((!curTemp && !curProto) || curText || curLayout?.Data.includes("dash")) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) if (curText !== curLayout?.Text) { this.dataDoc[this.props.fieldKey] = new RichTextField(json, curText); this.dataDoc[this.props.fieldKey + "-noTemplate"] = (curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts index e7bcf444a..af39ef9c7 100644 --- a/src/client/views/nodes/formattedText/nodes_rts.ts +++ b/src/client/views/nodes/formattedText/nodes_rts.ts @@ -166,7 +166,8 @@ export const nodes: { [index: string]: NodeSpec } = { inline: true, attrs: { fieldKey: { default: "" }, - docid: { default: "" } + docid: { default: "" }, + hideKey: { default: false } }, group: "inline", draggable: false, diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 9f75b5ffe..b41007e9c 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -467,6 +467,7 @@ export namespace Doc { return (layoutDoc.isTemplateForField || layoutDoc.isTemplateDoc) && dataDoc && layoutDoc !== dataDoc; } + const _pendingMap: Map = new Map(); // // Returns an expanded template layout for a target data document if there is a template relationship // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties @@ -492,13 +493,16 @@ export namespace Doc { const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc); const expandedLayoutFieldKey = (templateField || layoutFielddKey) + "-layout[" + templateLayoutDoc[Id] + (args ? `(${args})` : "") + "]"; let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey]; + if (templateLayoutDoc.resolvedDataDoc instanceof Promise) { expandedTemplateLayout = undefined; + _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true); } - else if (expandedTemplateLayout === undefined) { - if (templateLayoutDoc.resolvedDataDoc === Doc.GetProto(targetDoc) && templateLayoutDoc.PARAMS === StrCast(targetDoc.PARAMS)) { + else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey + args)) { + if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc)) && templateLayoutDoc.PARAMS === StrCast(targetDoc.PARAMS)) { expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params } else { + _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey + args, true); templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = Cast(templateLayoutDoc.proto, Doc, null) || templateLayoutDoc); // if the template has already been applied (ie, a nested template), then use the template's prototype setTimeout(action(() => { if (!targetDoc[expandedLayoutFieldKey]) { @@ -513,6 +517,7 @@ export namespace Doc { if (dataDoc[templateField] === undefined && templateLayoutDoc[templateField] instanceof List) { dataDoc[templateField] = ComputedField.MakeFunction(`ObjectField.MakeCopy(templateLayoutDoc["${templateField}"] as List)`, { templateLayoutDoc: Doc.name }, { templateLayoutDoc }); } + _pendingMap.delete(targetDoc[Id] + expandedLayoutFieldKey + args); } }), 0); } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index b10c6f119..d3e085b21 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -22,6 +22,7 @@ import { MainView } from "../../../client/views/MainView"; import { DocumentType } from "../../../client/documents/DocumentTypes"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { faBoxOpen } from "@fortawesome/free-solid-svg-icons"; +import { CollectionMulticolumnView, DimUnit } from "../../../client/views/collections/collectionMulticolumn/CollectionMulticolumnView"; export class CurrentUserUtils { private static curr_id: string; @@ -87,16 +88,28 @@ export class CurrentUserUtils { } if (doc["template-button-switch"] === undefined) { - const { FreeformDocument, MulticolumnDocument } = Docs.Create; + const { FreeformDocument, MulticolumnDocument, TextDocument } = Docs.Create; - const yes = FreeformDocument([], { title: "yes", _height: 100, _width: 100, _LODdisable: true }); + const yes = FreeformDocument([], { title: "yes", _height: 35, _width: 50, _LODdisable: true, _dimUnit: DimUnit.Pixel, _dimMagnitude: 40 }); + const name = TextDocument("name", { title: "name", _height: 35, _width: 70, _dimMagnitude: 1 }); const no = FreeformDocument([], { title: "no", _height: 100, _width: 100, _LODdisable: true }); + const labelTemplate = { + doc: { + type: "doc", content: [{ + type: "paragraph", + content: [{ type: "dashField", attrs: { fieldKey: "PARAMS", hideKey: true } }] + }] + }, + selection: { type: "text", anchor: 1, head: 1 }, + storedMarks: [] + }; + Doc.GetProto(name).text = new RichTextField(JSON.stringify(labelTemplate), "PARAMS"); Doc.GetProto(yes).backgroundColor = ComputedField.MakeFunction("self[this.PARAMS] ? 'green':'red'"); // Doc.GetProto(no).backgroundColor = ComputedField.MakeFunction("!self[this.PARAMS] ? 'red':'white'"); // Doc.GetProto(yes).onClick = ScriptField.MakeScript("self[this.PARAMS] = true"); Doc.GetProto(yes).onClick = ScriptField.MakeScript("self[this.PARAMS] = !self[this.PARAMS]"); // Doc.GetProto(no).onClick = ScriptField.MakeScript("self[this.PARAMS] = false"); - const box = MulticolumnDocument([/*no, */ yes], { title: "value", _width: 40, _height: 40, }); + const box = MulticolumnDocument([/*no, */ yes, name], { title: "value", _width: 120, _height: 35, }); box.isTemplateDoc = makeTemplate(box, true, "switch"); doc["template-button-switch"] = CurrentUserUtils.ficon({ -- cgit v1.2.3-70-g09d2