From 5e6352c78be5b2a9fe791bd87da9b2415ced4839 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 1 May 2020 19:35:37 -0400 Subject: added childLayoutTemplate to render collection children w/o modifying them. fixed docComponent's layoutDoc to use LayoutDoc prop. change buxton template to use new template mechanisms. fixed fixed lint errors. --- src/client/views/DocComponent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/DocComponent.tsx') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 0a8f0c9a7..629b0f447 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -20,7 +20,7 @@ export function DocComponent

(schemaCtor: (doc: D // This is the "The Document" -- it encapsulates, data, layout, and any templates @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; } // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info - @computed get layoutDoc() { return Doc.Layout(this.props.Document); } + @computed get layoutDoc() { return Doc.Layout(this.props.Document, this.props.LayoutDoc?.()); } // This is the data part of a document -- ie, the data that is constant across all views of the document @computed get dataDoc() { return this.props.Document[DataSym] as Doc; } -- cgit v1.2.3-70-g09d2 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/documents/Documents.ts | 7 +- src/client/util/DocumentManager.ts | 2 +- src/client/views/DocComponent.tsx | 4 +- src/client/views/DocumentDecorations.scss | 24 +++--- src/client/views/DocumentDecorations.tsx | 4 +- src/client/views/MainView.scss | 6 +- .../views/collections/CollectionCarouselView.tsx | 11 +-- .../views/collections/CollectionStackingView.tsx | 29 ++++--- src/client/views/collections/CollectionSubView.tsx | 2 + .../views/collections/CollectionTimeView.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 8 +- src/client/views/collections/CollectionView.tsx | 14 +++- .../views/collections/CollectionViewChromes.tsx | 6 +- .../CollectionFreeFormLinkView.tsx | 2 +- .../CollectionFreeFormLinksView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 +-- .../CollectionMulticolumnView.tsx | 5 +- .../CollectionMultirowView.tsx | 5 +- src/client/views/nodes/AudioBox.tsx | 4 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 4 +- .../views/nodes/ContentFittingDocumentView.tsx | 5 +- src/client/views/nodes/DocumentBox.tsx | 94 ++++++++++++++------- src/client/views/nodes/DocumentContentsView.tsx | 44 +++++----- src/client/views/nodes/DocumentView.tsx | 29 +++---- src/client/views/nodes/FieldView.tsx | 3 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/LinkAnchorBox.tsx | 1 - src/client/views/nodes/ScreenshotBox.tsx | 6 +- src/client/views/nodes/VideoBox.tsx | 6 +- src/new_fields/Doc.ts | 2 +- src/new_fields/documentSchemas.ts | 95 ++++++++++++---------- .../authentication/models/current_user_utils.ts | 2 +- 32 files changed, 247 insertions(+), 195 deletions(-) (limited to 'src/client/views/DocComponent.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 434b26312..672f94f75 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -95,6 +95,7 @@ export interface DocumentOptions { forceActive?: boolean; layout?: string | Doc; // default layout string for a document childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox or Buxton layout in tree view) + childLayoutString?: string; // template string for collection to use to render its children hideFilterView?: boolean; // whether to hide the filter popout on collections hideHeadings?: boolean; // whether stacking view column headings should be hidden isTemplateForField?: string; // the field key for which the containing document is a rendering template @@ -123,7 +124,7 @@ export interface DocumentOptions { displayTimecode?: number; // the time that a document should be displayed (e.g., time an annotation should be displayed on a video) borderRounding?: string; boxShadow?: string; - dontRegisterChildren?: boolean; + dontRegisterChildViews?: boolean; "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form "onClick-rawScript"?: string; // onClick script in raw text form "onCheckedClick-rawScript"?: string; // onChecked script in raw text form @@ -592,9 +593,7 @@ export namespace Docs { linkDocProto.anchor1_timecode = source.doc.currentTimecode || source.doc.displayTimecode; linkDocProto.anchor2_timecode = target.doc.currentTimecode || target.doc.displayTimecode; - if (linkDocProto.layout_key1 === undefined) { - Cast(linkDocProto.proto, Doc, null).layout_key1 = LinkAnchorBox.LayoutString("anchor1"); - Cast(linkDocProto.proto, Doc, null).layout_key2 = LinkAnchorBox.LayoutString("anchor2"); + if (linkDocProto.linkBoxExcludedKeys === undefined) { Cast(linkDocProto.proto, Doc, null).linkBoxExcludedKeys = new List(["treeViewExpandedView", "treeViewHideTitle", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); Cast(linkDocProto.proto, Doc, null).layoutKey = undefined; } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 4683e77a8..1ba6f0248 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -117,7 +117,7 @@ export class DocumentManager { pairs.push(...linksList.reduce((pairs, link) => { const linkToDoc = link && LinkManager.Instance.getOppositeAnchor(link, dv.props.Document); linkToDoc && DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => { - if (dv.props.Document.type !== DocumentType.LINK || dv.props.layoutKey !== docView1.props.layoutKey) { + if (dv.props.Document.type !== DocumentType.LINK || dv.props.LayoutTemplateString !== docView1.props.LayoutTemplateString) { pairs.push({ a: dv, b: docView1, l: link }); } }); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 629b0f447..fd0d2bdbb 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -11,7 +11,7 @@ import { InteractionUtils } from '../util/InteractionUtils'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) interface DocComponentProps { Document: Doc; - LayoutDoc?: () => Opt; + LayoutTemplate?: () => Opt; } export function DocComponent

(schemaCtor: (doc: Doc) => T) { class Component extends Touchable

{ @@ -20,7 +20,7 @@ export function DocComponent

(schemaCtor: (doc: D // This is the "The Document" -- it encapsulates, data, layout, and any templates @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; } // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info - @computed get layoutDoc() { return Doc.Layout(this.props.Document, this.props.LayoutDoc?.()); } + @computed get layoutDoc() { return Doc.Layout(this.props.Document, this.props.LayoutTemplate?.()); } // This is the data part of a document -- ie, the data that is constant across all views of the document @computed get dataDoc() { return this.props.Document[DataSym] as Doc; } diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 61d517d43..4f34eb9e3 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -44,7 +44,6 @@ $linkGap : 3px; .documentDecorations-radius { pointer-events: auto; - background: black; opacity: 1; transform: translate(10px, 10px); grid-row: 4; @@ -88,12 +87,12 @@ $linkGap : 3px; opacity: 1; } #documentDecorations-topLeftResizer { - border-left: black 2px solid; - border-top: black solid 2px; + border-left: 2px solid; + border-top: solid 2px; } #documentDecorations-bottomRightResizer { - border-right: black 2px solid; - border-bottom: black solid 2px; + border-right: 2px solid; + border-bottom: solid 2px; } #documentDecorations-topLeftResizer:hover, #documentDecorations-bottomRightResizer:hover { @@ -111,12 +110,12 @@ $linkGap : 3px; opacity: 1; } #documentDecorations-topRightResizer { - border-right: black 2px solid; - border-top: black 2px solid; + border-right: 2px solid; + border-top: 2px solid; } #documentDecorations-bottomLeftResizer { - border-left: black 2px solid; - border-bottom: black 2px solid; + border-left: 2px solid; + border-bottom: 2px solid; } #documentDecorations-topRightResizer:hover, #documentDecorations-bottomLeftResizer:hover { @@ -136,7 +135,6 @@ $linkGap : 3px; } .documentDecorations-contextMenu { - background: $alt-accent; width: 25px; height: calc(100% + 8px); // 8px for the height of the top resizer bar grid-column-start: 1; @@ -144,14 +142,14 @@ $linkGap : 3px; pointer-events: all; } .documentDecorations-title { - background: $alt-accent; opacity: 1; grid-column-start: 3; grid-column-end: 4; pointer-events: auto; overflow: hidden; text-align: center; - display:flex; + display: flex; + border-bottom: solid 1px; } .publishBox { width: 20px; @@ -168,7 +166,6 @@ $linkGap : 3px; .documentDecorations-closeButton { - background: $alt-accent; opacity: 1; grid-column-start: 4; grid-column-end: 6; @@ -178,7 +175,6 @@ $linkGap : 3px; } .documentDecorations-minimizeButton { - background: $alt-accent; opacity: 1; grid-column-start: 1; grid-column-end: 3; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index e2759291a..396fe12b5 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -4,7 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DataSym, Field } from "../../new_fields/Doc"; -import { PositionDocument } from '../../new_fields/documentSchemas'; +import { Document } from '../../new_fields/documentSchemas'; import { ScriptField } from '../../new_fields/ScriptField'; import { Cast, StrCast, NumCast } from "../../new_fields/Types"; import { Utils, setupMoveUpEvents, emptyFunction, returnFalse, simulateMouseClick } from "../../Utils"; @@ -301,7 +301,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { - const doc = PositionDocument(element.rootDoc); + const doc = Document(element.rootDoc); let nwidth = doc._nativeWidth || 0; let nheight = doc._nativeHeight || 0; const width = (doc._width || 0); diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 81d427f64..04288a9e1 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -39,7 +39,12 @@ } } +.mainView-container { + color:dimgray; +} + .mainView-container-dark { + color: lightgray; .lm_goldenlayout { background: dimgray; } @@ -54,7 +59,6 @@ } .contextMenu-cont, .contextMenu-item { background: dimGray; - color: lightgray; } .contextMenu-item:hover { background: gray; diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 4086294ad..769b323ae 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -2,9 +2,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observable, computed } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { documentSchema } from '../../../new_fields/documentSchemas'; +import { documentSchema, collectionSchema } from '../../../new_fields/documentSchemas'; import { makeInterface } from '../../../new_fields/Schema'; -import { NumCast, StrCast, ScriptCast } from '../../../new_fields/Types'; +import { NumCast, StrCast, ScriptCast, Cast } from '../../../new_fields/Types'; import { DragManager } from '../../util/DragManager'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; import "./CollectionCarouselView.scss"; @@ -16,8 +16,8 @@ import { ContextMenu } from '../ContextMenu'; import { ObjectField } from '../../../new_fields/ObjectField'; import { returnFalse } from '../../../Utils'; -type CarouselDocument = makeInterface<[typeof documentSchema,]>; -const CarouselDocument = makeInterface(documentSchema); +type CarouselDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>; +const CarouselDocument = makeInterface(documentSchema, collectionSchema); @observer export class CollectionCarouselView extends CollectionSubView(CarouselDocument) { @@ -40,7 +40,6 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument) e.stopPropagation(); this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; } - panelHeight = () => this.props.PanelHeight() - 50; @computed get content() { const index = NumCast(this.layoutDoc._itemIndex); @@ -51,6 +50,8 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument) onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)} onClick={ScriptCast(this.layoutDoc.onChildClick)} renderDepth={this.props.renderDepth + 1} + LayoutTemplate={this.props.ChildLayoutTemplate} + LayoutTemplateString={this.props.ChildLayoutString} Document={this.childLayoutPairs[index].layout} DataDoc={this.childLayoutPairs[index].data} PanelHeight={this.panelHeight} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 01766f65f..eb70cec9d 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -4,15 +4,17 @@ import { CursorProperty } from "csstype"; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import Switch from 'rc-switch'; -import { Doc, HeightSym, WidthSym, DataSym } from "../../../new_fields/Doc"; +import { DataSym, Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; +import { collectionSchema, documentSchema } from "../../../new_fields/documentSchemas"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; -import { listSpec } from "../../../new_fields/Schema"; +import { listSpec, makeInterface } from "../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types"; import { TraceMobx } from "../../../new_fields/util"; -import { Utils, setupMoveUpEvents, emptyFunction, returnZero, returnOne, returnFalse } from "../../../Utils"; +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"; @@ -24,11 +26,14 @@ import "./CollectionStackingView.scss"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionViewType } from "./CollectionView"; -import { SelectionManager } from "../../util/SelectionManager"; +import { ScriptField } from "../../../new_fields/ScriptField"; const _global = (window /* browser */ || global /* node */) as any; +type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>; +const StackingDocument = makeInterface(collectionSchema, documentSchema); + @observer -export class CollectionStackingView extends CollectionSubView(doc => doc) { +export class CollectionStackingView extends CollectionSubView(StackingDocument) { _masonryGridRef: HTMLDivElement | null = null; _draggerRef = React.createRef(); _pivotFieldDisposer?: IReactionDisposer; @@ -116,7 +121,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { getSimpleDocHeight(d?: Doc) { if (!d) return 0; - const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); + const layoutDoc = Doc.Layout(d, this.props.ChildLayoutTemplate?.()); const nw = NumCast(layoutDoc._nativeWidth); const nh = NumCast(layoutDoc._nativeHeight); let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); @@ -160,14 +165,16 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } return this.props.addDocTab(doc, where); } + getDisplayDoc(doc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) { - const layoutDoc = Doc.Layout(doc, this.props.childLayoutTemplate?.()); + const layoutDoc = Doc.Layout(doc, this.props.ChildLayoutTemplate?.()); const height = () => this.getDocHeight(doc); return doc) { PanelHeight={height} NativeHeight={returnZero} NativeWidth={returnZero} - fitToBox={BoolCast(this.props.Document._freezeChildDimensions)} + fitToBox={false} rootSelected={this.rootSelected} dropAction={StrCast(this.props.Document.childDropAction) as dropActionType} onClick={this.onChildClickHandler} @@ -199,13 +206,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { getDocWidth(d?: Doc) { if (!d) return 0; - const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); + const layoutDoc = Doc.Layout(d, this.props.ChildLayoutTemplate?.()); const nw = NumCast(layoutDoc._nativeWidth); return Math.min(nw && !this.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); } getDocHeight(d?: Doc) { if (!d) return 0; - const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); + const layoutDoc = Doc.Layout(d, this.props.ChildLayoutTemplate?.()); const nw = NumCast(layoutDoc._nativeWidth); const nh = NumCast(layoutDoc._nativeHeight); let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index e44bbae78..aaea13ded 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -43,6 +43,8 @@ export interface CollectionViewProps extends FieldViewProps { export interface SubCollectionViewProps extends CollectionViewProps { CollectionView: Opt; children?: never | (() => JSX.Element[]) | React.ReactNode; + ChildLayoutTemplate?: () => Doc; + ChildLayoutString?: string; childClickScript?: ScriptField; childDoubleClickScript?: ScriptField; freezeChildDimensions?: boolean; // used by TimeView to coerce documents to treat their width height as their native width/height diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 045134225..a2d4774c8 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -28,7 +28,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { @observable _childClickedScript: Opt; @observable _viewDefDivClick: Opt; async componentDidMount() { - const detailView = (await DocCastAsync(this.props.Document.childDetailView)) || Doc.findTemplate("detailView", StrCast(this.props.Document.type), ""); + const detailView = (await DocCastAsync(this.props.Document.childClickedOpenTemplateView)) || Doc.findTemplate("detailView", StrCast(this.props.Document.type), ""); const childText = "const alias = getAlias(self); switchView(alias, detailView); alias.dropAction='alias'; alias.removeDropProperties=new List(['dropAction']); useRightSplit(alias, shiftKey); "; runInAction(() => { this._childClickedScript = ScriptField.MakeScript(childText, { this: Doc.name, shiftKey: "boolean" }, { detailView: detailView! }); @@ -84,7 +84,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { @computed get contents() { return

- +
; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 296c1a39c..dc9348664 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -6,7 +6,6 @@ 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 { RichTextField } from '../../../new_fields/RichTextField'; import { Document, listSpec } from '../../../new_fields/Schema'; import { ComputedField, ScriptField } from '../../../new_fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../new_fields/Types'; @@ -15,7 +14,6 @@ import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager"; -import { makeTemplate } from '../../util/DropConverter'; import { Scripting } from '../../util/Scripting'; import { SelectionManager } from '../../util/SelectionManager'; import { Transform } from '../../util/Transform'; @@ -481,7 +479,7 @@ class TreeView extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} - dontRegisterView={BoolCast(this.props.treeViewId.dontRegisterChildren)} + dontRegisterView={BoolCast(this.props.treeViewId.dontRegisterChildViews)} ContainingCollectionView={undefined} ContainingCollectionDoc={this.props.containingCollection} />} @@ -743,11 +741,11 @@ export class CollectionTreeView extends CollectionSubView boolean; + filterAddDocument: (doc: Doc) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) + childLayoutTemplate?: () => Opt; // specify a layout Doc template to use for children of the collection } export interface CollectionRenderProps { @@ -82,6 +83,8 @@ export interface CollectionRenderProps { active: () => boolean; whenActiveChanged: (isActive: boolean) => void; PanelWidth: () => number; + ChildLayoutTemplate?: () => Doc; + ChildLayoutString?: string; } @observer @@ -245,8 +248,8 @@ export class CollectionView extends Touchable this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" }); } - if (this.props.Document.childDetailView instanceof Doc) { - layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailView as Doc, "onRight"), icon: "project-diagram" }); + if (this.props.Document.childClickedOpenTemplateView instanceof Doc) { + layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childClickedOpenTemplateView as Doc, "onRight"), icon: "project-diagram" }); } layoutItems.push({ description: `${this.props.Document.isInPlaceContainer ? "Unset" : "Set"} inPlace Container`, event: () => this.props.Document.isInPlaceContainer = !this.props.Document.isInPlaceContainer, icon: "project-diagram" }); @@ -474,6 +477,7 @@ export class CollectionView extends Touchable ; } + childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null); render() { TraceMobx(); @@ -483,7 +487,9 @@ export class CollectionView extends Touchable click item view", - script: "this.target.childDetailView = getDocTemplate(this.source?.[0])", - immediate: (source: Doc[]) => this.target.childDetailView = Doc.getDocTemplate(source?.[0]), + params: ["target", "source"], title: "=> click clicked open view", + script: "this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])", + immediate: (source: Doc[]) => this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]), initialize: emptyFunction, }; _contentCommand = { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index cf12ef382..d67d1993e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -40,7 +40,7 @@ export class CollectionFreeFormLinkView extends React.Component - c.a.props.layoutKey && c.b.props.layoutKey && c.a.props.Document.type === DocumentType.LINK && + c.a.props.Document.type === DocumentType.LINK && c.a.props.bringToFront !== emptyFunction && c.b.props.bringToFront !== emptyFunction // bcz: this prevents links to be drawn to anchors in CollectionTree views -- this is a hack that should be fixed ).map(c => ); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 45ef0455e..707e103fb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -5,7 +5,7 @@ import { action, computed, IReactionDisposer, observable, ObservableMap, reactio import { observer } from "mobx-react"; import { computedFn } from "mobx-utils"; import { Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../../new_fields/Doc"; -import { documentSchema, positionSchema } from "../../../../new_fields/documentSchemas"; +import { documentSchema, collectionSchema } from "../../../../new_fields/documentSchemas"; import { Id } from "../../../../new_fields/FieldSymbols"; import { InkData, InkField, InkTool, PointData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; @@ -66,8 +66,8 @@ export const panZoomSchema = createSchema({ fitH: "number" }); -type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof documentSchema, typeof positionSchema, typeof pageSchema]>; -const PanZoomDocument = makeInterface(panZoomSchema, documentSchema, positionSchema, pageSchema); +type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof collectionSchema, typeof documentSchema, typeof pageSchema]>; +const PanZoomDocument = makeInterface(panZoomSchema, collectionSchema, documentSchema, pageSchema); export type collectionFreeformViewProps = { forceScaling?: boolean; // whether to force scaling of content (needed by ImageBox) viewDefDivClick?: ScriptField; @@ -858,7 +858,6 @@ export class CollectionFreeFormView extends CollectionSubView BoolCast(this.Document.useClusters); parentActive = () => this.props.active() || this.backgroundActive ? true : false; - childLayoutFunc = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null); getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps { return { ...this.props, @@ -868,7 +867,8 @@ export class CollectionFreeFormView extends CollectionSubView(PositionDocument) { +export class CollectionFreeFormDocumentView extends DocComponent(Document) { @observable _animPos: number[] | undefined = undefined; random(min: number, max: number) { // min should not be equal to max const mseed = Math.abs(this.X * this.Y); diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 637fd5acc..3c2c6c87e 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -14,7 +14,7 @@ import "./ContentFittingDocumentView.scss"; @observer export class ContentFittingDocumentView extends React.Component{ public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive - private get layoutDoc() { return this.props.LayoutDoc?.() || Doc.Layout(this.props.Document); } + private get layoutDoc() { return this.props.LayoutTemplate?.() || Doc.Layout(this.props.Document); } @computed get freezeDimensions() { return this.props.FreezeDimensions; } nativeWidth = () => NumCast(this.layoutDoc?._nativeWidth, this.props.NativeWidth?.() || (this.freezeDimensions && this.layoutDoc ? this.layoutDoc[WidthSym]() : this.props.PanelWidth())); nativeHeight = () => NumCast(this.layoutDoc?._nativeHeight, this.props.NativeHeight?.() || (this.freezeDimensions && this.layoutDoc ? this.layoutDoc[HeightSym]() : this.props.PanelHeight())); @@ -56,7 +56,8 @@ export class ContentFittingDocumentView extends React.Component; -const DocHolderBoxDocument = makeInterface(documentSchema); +type DocHolderBoxSchema = makeInterface<[typeof documentSchema, typeof collectionSchema]>; +const DocHolderBoxDocument = makeInterface(documentSchema, collectionSchema); @observer export class DocHolderBox extends ViewBoxAnnotatableComponent(DocHolderBoxDocument) { @@ -43,7 +45,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent 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.childTemplateName !== "keyValue" ? "key values" : "contents"}`, event: () => this.layoutDoc.childTemplateName = this.layoutDoc.childTemplateName ? undefined : "keyValue", 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" }); } @@ -103,6 +105,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent 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; get renderContents() { const containedDoc = Cast(this.dataDoc[this.props.fieldKey], Doc, null); const childTemplateName = StrCast(this.layoutDoc.childTemplateName); @@ -112,33 +115,62 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent; + const contents = !(containedDoc instanceof Doc) ? (null) : this.layoutDoc.childLayoutString ? + : + ; return contents; } render() { 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 diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f1efa48f4..7c7c03db2 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -5,22 +5,21 @@ import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as rp from "request-promise"; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; -import { Document, PositionDocument } from '../../../new_fields/documentSchemas'; +import { Document } from '../../../new_fields/documentSchemas'; import { Id } from '../../../new_fields/FieldSymbols'; import { InkTool } from '../../../new_fields/InkField'; -import { RichTextField } from '../../../new_fields/RichTextField'; import { listSpec } from "../../../new_fields/Schema"; import { SchemaHeaderField } from '../../../new_fields/SchemaHeaderField'; import { ScriptField } from '../../../new_fields/ScriptField'; import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; -import { AudioField, ImageField, PdfField, VideoField } from '../../../new_fields/URLField'; +import { ImageField } from '../../../new_fields/URLField'; import { TraceMobx } from '../../../new_fields/util'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; import { emptyFunction, OmitKeys, returnOne, returnTransparent, Utils } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { ClientRecommender } from '../../ClientRecommender'; import { DocServer } from "../../DocServer"; -import { Docs, DocumentOptions, DocUtils } from "../../documents/Documents"; +import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; import { ClientUtils } from '../../util/ClientUtils'; import { DocumentManager } from "../../util/DocumentManager"; @@ -42,6 +41,7 @@ import { InkingControl } from '../InkingControl'; import { KeyphraseQueryView } from '../KeyphraseQueryView'; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; +import { LinkAnchorBox } from './LinkAnchorBox'; import { RadialMenu } from './RadialMenu'; import React = require("react"); @@ -58,7 +58,8 @@ export interface DocumentViewProps { NativeHeight: () => number; Document: Doc; DataDoc?: Doc; - LayoutDoc?: () => Opt; + LayoutTemplateString?: string; + LayoutTemplate?: () => Opt; LibraryPath: Doc[]; fitToBox?: boolean; contextMenuItems?: () => { script: ScriptField, label: string }[]; @@ -454,8 +455,8 @@ export class DocumentView extends DocComponent(Docu const dY = -1 * Math.sign(dH); if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { - const doc = PositionDocument(this.props.Document); - const layoutDoc = PositionDocument(Doc.Layout(this.props.Document)); + const doc = Document(this.props.Document); + const layoutDoc = Document(Doc.Layout(this.props.Document)); let nwidth = layoutDoc._nativeWidth || 0; let nheight = layoutDoc._nativeHeight || 0; const width = (layoutDoc._width || 0); @@ -984,13 +985,15 @@ export class DocumentView extends DocComponent(Docu @computed get contents() { TraceMobx(); return (<> - (Docu ); } - linkEndpoint = (linkDoc: Doc) => Doc.LinkEndpoint(linkDoc, this.props.Document); // used to decide whether a link anchor view should be created or not. // if it's a tempoarl link (currently just for Audio), then the audioBox will display the anchor and we don't want to display it here. @@ -1049,12 +1051,12 @@ export class DocumentView extends DocComponent(Docu ContainingCollectionDoc={this.props.Document} // bcz: hack this.props.Document is not a collection Need a better prop for passing the containing document to the LinkAnchorBox PanelWidth={this.anchorPanelWidth} PanelHeight={this.anchorPanelHeight} - layoutKey={this.linkEndpoint(d)} ContentScaling={returnOne} backgroundColor={returnTransparent} removeDocument={this.hideLinkAnchor} pointerEvents={false} - LayoutDoc={undefined} + LayoutTemplate={undefined} + LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(d, this.props.Document)}`)} />); } @computed get innards() { @@ -1073,8 +1075,7 @@ export class DocumentView extends DocComponent(Docu
`} ContentScaling={this.childScaling} ChromeHeight={this.chromeHeight} isSelected={this.isSelected} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 1efee4f5a..40d55ce38 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -50,13 +50,12 @@ export interface FieldViewProps { setVideoBox?: (player: VideoBox) => void; ContentScaling: () => number; ChromeHeight?: () => number; - childLayoutTemplate?: () => Opt; + RenderData?: () => Doc; // properties intended to be used from within layout strings (otherwise use the function equivalents that work more efficiently with React) height?: number; width?: number; background?: string; color?: string; - RenderData?: () => Doc; } @observer diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 2970674a2..d43936949 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -36,7 +36,7 @@ export class KeyValueBox extends React.Component { @observable private _keyInput: string = ""; @observable private _valueInput: string = ""; @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); } - get fieldDocToLayout() { return this.props.fieldKey ? Cast(this.props.Document[this.props.fieldKey], Doc, null) : this.props.Document; } + get fieldDocToLayout() { return this.props.Document; } @action onEnterKey = (e: React.KeyboardEvent): void => { diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 6c50abf21..bc36e056e 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -17,7 +17,6 @@ import { LinkEditor } from "../linking/LinkEditor"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { SelectionManager } from "../../util/SelectionManager"; import { TraceMobx } from "../../../new_fields/util"; -import { DocumentView } from "./DocumentView"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 125690dc7..a0ecc9ff5 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -5,7 +5,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, IReactionDisposer, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as rp from 'request-promise'; -import { documentSchema, positionSchema } from "../../../new_fields/documentSchemas"; +import { documentSchema } from "../../../new_fields/documentSchemas"; import { makeInterface } from "../../../new_fields/Schema"; import { Cast, NumCast } from "../../../new_fields/Types"; import { VideoField } from "../../../new_fields/URLField"; @@ -20,8 +20,8 @@ import { FieldView, FieldViewProps } from './FieldView'; import "./ScreenshotBox.scss"; const path = require('path'); -type ScreenshotDocument = makeInterface<[typeof documentSchema, typeof positionSchema]>; -const ScreenshotDocument = makeInterface(documentSchema, positionSchema); +type ScreenshotDocument = makeInterface<[typeof documentSchema]>; +const ScreenshotDocument = makeInterface(documentSchema); library.add(faVideo); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 613929bca..266b7f43f 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -21,14 +21,14 @@ import { DocumentDecorations } from "../DocumentDecorations"; import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; import "./VideoBox.scss"; -import { documentSchema, positionSchema } from "../../../new_fields/documentSchemas"; +import { documentSchema } from "../../../new_fields/documentSchemas"; const path = require('path'); export const timeSchema = createSchema({ currentTimecode: "number", // the current time of a video or other linear, time-based document. Note, should really get set on an extension field, but that's more complicated when it needs to be set since the extension doc needs to be found first }); -type VideoDocument = makeInterface<[typeof documentSchema, typeof positionSchema, typeof timeSchema]>; -const VideoDocument = makeInterface(documentSchema, positionSchema, timeSchema); +type VideoDocument = makeInterface<[typeof documentSchema, typeof timeSchema]>; +const VideoDocument = makeInterface(documentSchema, timeSchema); library.add(faVideo); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 71325d94f..9256f82c2 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -772,7 +772,7 @@ export namespace Doc { export function LinkOtherAnchor(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? Cast(linkDoc.anchor2, Doc) as Doc : Cast(linkDoc.anchor1, Doc) as Doc; } - export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? "layout_key1" : "layout_key2"; } + export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) { return Doc.AreProtosEqual(anchorDoc, Cast(linkDoc.anchor1, Doc) as Doc) ? "1" : "2"; } export function linkFollowUnhighlight() { Doc.UnhighlightAll(); diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index fd9a304f9..e71fc27f3 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -4,13 +4,25 @@ import { Doc } from "./Doc"; import { DateField } from "./DateField"; export const documentSchema = createSchema({ + // content properties type: "string", // enumerated type of document -- should be template-specific (ie, start with an '_') - layout: "string", // this is the native layout string for the document. templates can be added using other fields and setting layoutKey below - layoutKey: "string", // holds the field key for the field that actually holds the current lyoat title: "string", // document title (can be on either data document or layout) - dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias", "copy", "move") - targetDropAction: "string", // allows the target of a drop event to specify the dropAction ("alias", "copy", "move") - childDropAction: "string", // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "alias" or "copy") + isTemplateForField: "string",// if specified, it indicates the document is a template that renders the specified field + creationDate: DateField, // when the document was created + links: listSpec(Doc), // computed (readonly) list of links associated with this document + + // "Location" properties in a very general sense + currentTimecode: "number", // current play back time of a temporal document (video / audio) + displayTimecode: "number", // the time that a document should be displayed (e.g., time an annotation should be displayed on a video) + inOverlay: "boolean", // whether the document is rendered in an OverlayView which handles selection/dragging differently + x: "number", // x coordinate when in a freeform view + y: "number", // y coordinate when in a freeform view + z: "number", // z "coordinate" - non-zero specifies the overlay layer of a freeformview + zIndex: "number", // zIndex of a document in a freeform view + scrollY: "number", // "command" to scroll a document to a position on load (the value will be reset to 0 after that ) + scrollTop: "number", // scroll position of a scrollable document (pdf, text, web) + + // appearance properties on the layout _autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents _nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set _nativeHeight: "number", // " @@ -27,59 +39,57 @@ export const documentSchema = createSchema({ _showAudio: "boolean", // whether to show the audio record icon on documents _freeformLayoutEngine: "string",// the string ID for the layout engine to use to layout freeform view documents _LODdisable: "boolean", // whether to disbale LOD switching for CollectionFreeFormViews - _pivotField: "string", // specifies which field should be used as the timeline/pivot axis + _pivotField: "string", // specifies which field key should be used as the timeline/pivot axis _replacedChrome: "string", // what the default chrome is replaced with. Currently only supports the value of 'replaced' for PresBox's. _chromeStatus: "string", // determines the state of the collection chrome. values allowed are 'replaced', 'enabled', 'disabled', 'collapsed' - _freezeChildDimensions: "boolean", // freezes child document dimensions (e.g., used by time/pivot view to make sure all children will be scaled to fit their display rectangle) _fontSize: "number", _fontFamily: "string", - isInPlaceContainer: "boolean",// whether the marked object will display addDocTab() calls that target "inPlace" destinations - color: "string", // foreground color of document + + // appearance properties on the data document backgroundColor: "string", // background color of document + borderRounding: "string", // border radius rounding of document + boxShadow: "string", // the amount of shadow around the perimeter of a document + color: "string", // foreground color of document + fitToBox: "boolean", // whether freeform view contents should be zoomed/panned to fill the area of the document view + fontSize: "string", + layout: "string", // this is the native layout string for the document. templates can be added using other fields and setting layoutKey below + layoutKey: "string", // holds the field key for the field that actually holds the current lyoat + letterSpacing: "string", opacity: "number", // opacity of document - creationDate: DateField, // when the document was created - links: listSpec(Doc), // computed (readonly) list of links associated with this document + strokeWidth: "number", + textTransform: "string", + treeViewOpen: "boolean", // flag denoting whether the documents sub-tree (contents) is visible or hidden + treeViewExpandedView: "string", // name of field whose contents are being displayed as the document's subtree + treeViewPreventOpen: "boolean", // ignores the treeViewOpen flag (for allowing a view to not be slaved to other views of the document) + + // interaction and linking properties + ignoreClick: "boolean", // whether documents ignores input clicks (but does not ignore manipulation and other events) onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) onPointerDown: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) onPointerUp: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) onDragStart: ScriptField, // script to run when document is dragged (without being selected). the script should return the Doc to be dropped. - dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document. - removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped - isTemplateForField: "string",// when specifies a field key, then the containing document is a template that renders the specified field - isBackground: "boolean", // whether document is a background element and ignores input events (can only select with marquee) - treeViewOpen: "boolean", // flag denoting whether the documents sub-tree (contents) is visible or hidden - treeViewExpandedView: "string", // name of field whose contents are being displayed as the document's subtree - treeViewPreventOpen: "boolean", // ignores the treeViewOpen flag (for allowing a view to not be slaved to other views of the document) - currentTimecode: "number", // current play back time of a temporal document (video / audio) followLinkLocation: "string",// flag for where to place content when following a click interaction (e.g., onRight, inPlace, inTab, ) + isInPlaceContainer: "boolean",// whether the marked object will display addDocTab() calls that target "inPlace" destinations + isLinkButton: "boolean", // whether document functions as a link follow button to follow the first link on the document when clicked + isBackground: "boolean", // whether document is a background element and ignores input events (can only select with marquee) lockedPosition: "boolean", // whether the document can be moved (dragged) lockedTransform: "boolean", // whether the document can be panned/zoomed - inOverlay: "boolean", // whether the document is rendered in an OverlayView which handles selection/dragging differently - borderRounding: "string", // border radius rounding of document - heading: "number", // the logical layout 'heading' of this document (used by rule provider to stylize h1 header elements, from h2, etc) - isLinkButton: "boolean", // whether document functions as a link follow button to follow the first link on the document when clicked - ignoreClick: "boolean", // whether documents ignores input clicks (but does not ignore manipulation and other events) - scrollToLinkID: "string", // id of link being traversed. allows this doc to scroll/highlight/etc its link anchor. scrollToLinkID should be set to undefined by this doc after it sets up its scroll,etc. - scrollY: "number", // "command" to scroll a document to a position on load (the value will be reset to 0 after that ) - scrollTop: "number", // scroll position of a scrollable document (pdf, text, web) - strokeWidth: "number", - fontSize: "string", - fitToBox: "boolean", // whether freeform view contents should be zoomed/panned to fill the area of the document view - letterSpacing: "string", - textTransform: "string", - childTemplateName: "string" // the name of a template to use to override the layoutKey when rendering a document in DocHolderBox -}); -export const positionSchema = createSchema({ - zIndex: "number", - x: "number", - y: "number", - z: "number", + // drag drop properties + dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document. + dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias", "copy", "move") + targetDropAction: "string", // allows the target of a drop event to specify the dropAction ("alias", "copy", "move") + childDropAction: "string", // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "alias" or "copy") + removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped }); + export const collectionSchema = createSchema({ - childLayoutTemplate: Doc, // layout template for children of a collecion - childDetailView: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to use this field) + childLayoutTemplateName: "string", // the name of a template to use to override the layoutKey when rendering a document -- ONLY used in DocHolderBox + childLayoutTemplate: Doc, // layout template to use to render children of a collecion + childLayoutString: "string", //layout string to use to render children of a collection + childClickedOpenTemplateView: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to read this value and apply template) + dontRegisterChildViews: "boolean", // whether views made of this document are registered so that they can be found when drawing links scrollToLinkID: "string", // id of link being traversed. allows this doc to scroll/highlight/etc its link anchor. scrollToLinkID should be set to undefined by this doc after it sets up its scroll,etc. onChildClick: ScriptField, // script to run for each child when its clicked onChildDoubleClick: ScriptField, // script to run for each child when its clicked onCheckedClick: ScriptField, // script to run when a checkbox is clicked next to a child in a tree view @@ -87,6 +97,3 @@ export const collectionSchema = createSchema({ export type Document = makeInterface<[typeof documentSchema]>; export const Document = makeInterface(documentSchema); - -export type PositionDocument = makeInterface<[typeof documentSchema, typeof positionSchema]>; -export const PositionDocument = makeInterface(documentSchema, positionSchema); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 2ae42bf52..b9de93559 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -485,7 +485,7 @@ export class CurrentUserUtils { _width: 50, _height: 25, title: "Library", _fontSize: 10, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: new PrefetchProxy(Docs.Create.TreeDocument([workspaces, documents, recentlyClosed, doc], { - title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "move", lockedPosition: true, boxShadow: "0 0", dontRegisterChildren: true + title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "move", lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true })) as any as Doc, targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc, onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel;") -- cgit v1.2.3-70-g09d2 From 18dc6b3c66c28d0e78a579479b80786aa6589970 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 2 May 2020 18:01:49 -0400 Subject: cleaned up presbox to not use reactions but to use a lookup script. put lookupField into DocComponent for general use --- src/client/views/DocComponent.tsx | 7 +++++- .../views/collections/CollectionDockingView.tsx | 1 + src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/PresBox.tsx | 27 ++++++++++++---------- .../views/presentationview/PresElementBox.tsx | 7 +++--- 5 files changed, 27 insertions(+), 17 deletions(-) (limited to 'src/client/views/DocComponent.tsx') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index fd0d2bdbb..11866aebe 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,7 +1,7 @@ import { Doc, Opt, DataSym } from '../../new_fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; -import { Cast, BoolCast } from '../../new_fields/Types'; +import { Cast, BoolCast, ScriptCast } from '../../new_fields/Types'; import { listSpec } from '../../new_fields/Schema'; import { InkingControl } from './InkingControl'; import { InkTool } from '../../new_fields/InkField'; @@ -33,6 +33,7 @@ export function DocComponent

(schemaCtor: (doc: D interface ViewBoxBaseProps { Document: Doc; DataDoc?: Doc; + ContainingCollectionDoc: Opt; fieldKey: string; isSelected: (outsideReaction?: boolean) => boolean; renderDepth: number; @@ -53,6 +54,8 @@ export function ViewBoxBaseComponent

(schemaCtor: // key where data is stored @computed get fieldKey() { return this.props.fieldKey; } + lookupField = (field: string) => ScriptCast(this.layoutDoc.lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field, container: this.props.ContainingCollectionDoc }).result; + active = (outsideReaction?: boolean) => !this.props.Document.isBackground && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0 || this.layoutDoc.forceActive);// && !InkingControl.Instance.selectedTool; // bcz: inking state shouldn't affect static tools protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; } @@ -87,6 +90,8 @@ export function ViewBoxAnnotatableComponent

ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result; + protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; _annotationKey: string = "annotations"; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 0d859c3f1..822f44f5a 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -685,6 +685,7 @@ export class DockedFrameRenderer extends React.Component { if (curPres) { const pinDoc = Doc.MakeAlias(doc); pinDoc.presentationTargetDoc = doc; + pinDoc.presZoomButton = true; Doc.AddDocToList(curPres, "data", pinDoc); if (!DocumentManager.Instance.getDocumentView(curPres)) { CollectionDockingView.AddRightSplit(curPres); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 2970674a2..39d7109b1 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -238,8 +238,8 @@ export class KeyValueBox extends React.Component { const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; openItems.push({ description: "Default Perspective", event: () => { - this.props.addDocTab(this.fieldDocToLayout, "inTab"); this.props.addDocTab(this.props.Document, "close"); + this.props.addDocTab(this.fieldDocToLayout, "onRight"); }, icon: "image" }); !open && cm.addItem({ description: "Change Perspective...", subitems: openItems, icon: "external-link-alt" }); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 53b6aa408..57975c3af 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -19,6 +19,8 @@ import { makeInterface } from "../../../new_fields/Schema"; import { List } from "../../../new_fields/List"; import { Docs } from "../../documents/Documents"; import { PrefetchProxy } from "../../../new_fields/Proxy"; +import { ScriptField } from "../../../new_fields/ScriptField"; +import { Scripting } from "../../util/Scripting"; type PresBoxSchema = makeInterface<[typeof documentSchema]>; const PresBoxDocument = makeInterface(documentSchema); @@ -26,32 +28,30 @@ const PresBoxDocument = makeInterface(documentSchema); @observer export class PresBox extends ViewBoxBaseComponent(PresBoxDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } - _docsDisposer: IReactionDisposer | undefined; - _viewDisposer: IReactionDisposer | undefined; @observable _isChildActive = false; @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); } @computed get currentIndex() { return NumCast(this.presElement?.currentIndex); } - @computed get presElement() { return Cast(this.rootDoc.presElement, Doc, null); } + @computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); } constructor(props: any) { super(props); - if (!this.presElement) { - this.rootDoc.presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ + if (!this.presElement) { // create exactly one presElmentBox template to use by any and all presentations. Save it to the user doc. + Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ title: "pres element template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data" })); + (this.presElement as Doc).lookupField = ScriptField.MakeScript( + "const presDoc = container.presentationDoc;" + + `if (field === 'indexInPres') return docList(presDoc[presDoc.presentationFieldKey]).indexOf(data);` + + "if (field === 'presCollapsedHeight') return presDoc._viewType === CollectionViewType.Stacking ? 50 : 46;" + + "return undefined;", { field: "string", data: Doc.name, container: Doc.name }); } - } - - componentWillUnmount() { - this._docsDisposer?.(); - this._viewDisposer?.(); + this.props.Document.presentationDoc = this.props.Document; + this.props.Document.presentationFieldKey = this.fieldKey; } componentDidMount() { this.rootDoc.presBox = this.rootDoc; this.rootDoc._forceRenderEngine = "timeline"; this.rootDoc._replacedChrome = "replaced"; - this._docsDisposer = reaction(() => this.childDocs, docs => this.presElement.presOrderedDocs = new List(docs), { fireImmediately: true }); - this._viewDisposer = reaction(() => this.rootDoc._viewType, viewType => this.presElement.presCollapsedHeight = viewType === CollectionViewType.Tree ? 50 : 46, { fireImmediately: true }); } updateCurrentPresentation = () => Doc.UserDoc().activePresentation = this.rootDoc; @@ -309,6 +309,7 @@ export class PresBox extends ViewBoxBaseComponent

{mode !== CollectionViewType.Invalid ?
; } } +Scripting.addGlobal(function lookupPresBoxField(presLayout: Doc, data: Doc, fieldKey: string) { +}); diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index fd202cdc1..999f907c9 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -5,7 +5,7 @@ import { Doc, DataSym, DocListCast } from "../../../new_fields/Doc"; import { documentSchema } from '../../../new_fields/documentSchemas'; import { Id } from "../../../new_fields/FieldSymbols"; import { createSchema, makeInterface } from '../../../new_fields/Schema'; -import { Cast, NumCast, BoolCast } from "../../../new_fields/Types"; +import { Cast, NumCast, BoolCast, ScriptCast } from "../../../new_fields/Types"; import { emptyFunction, emptyPath, returnFalse, returnTrue, returnOne, returnZero } from "../../../Utils"; import { Transform } from "../../util/Transform"; import { CollectionViewType } from '../collections/CollectionView'; @@ -38,8 +38,9 @@ export class PresElementBox extends ViewBoxBaseComponent d === this.rootDoc); } - @computed get collapsedHeight() { return NumCast(this.layoutDoc.presCollapsedHeight); } + // these fields are conditionally computed fields on the layout document that take this document as a parameter + @computed get indexInPres() { return Number(this.lookupField("indexInPres")); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements) + @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation elmeent template if it's guaranteed to be used only once - but if it's shared by different presentations, then this value must be looked up @computed get presStatus() { return BoolCast(this.layoutDoc.presStatus); } @computed get currentIndex() { return NumCast(this.layoutDoc.currentIndex); } @computed get targetDoc() { return this.rootDoc.presentationTargetDoc as Doc; } -- cgit v1.2.3-70-g09d2 From fcd0895e5933270718b9c1a262e7e377eaabb024 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 7 May 2020 19:18:52 -0400 Subject: fixed most add/remove/move documents to support doc[]'s --- src/client/util/DragManager.ts | 4 +- src/client/views/DocComponent.tsx | 37 +++++++++---- src/client/views/MainView.tsx | 6 +- src/client/views/TemplateMenu.tsx | 6 +- src/client/views/collections/CollectionSubView.tsx | 14 ++--- .../views/collections/CollectionTreeView.tsx | 64 +++++++++++++--------- src/client/views/collections/CollectionView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- .../collections/collectionFreeForm/MarqueeView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 12 ++-- src/client/views/nodes/FieldView.tsx | 6 +- src/client/views/nodes/PresBox.tsx | 9 ++- src/client/views/nodes/VideoBox.tsx | 9 ++- 13 files changed, 107 insertions(+), 72 deletions(-) (limited to 'src/client/views/DocComponent.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 0d208cf1b..cc8cc38dd 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -77,8 +77,8 @@ export namespace DragManager { return root; } export let AbortDrag: () => void = emptyFunction; - export type MoveFunction = (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; - export type RemoveFunction = (document: Doc) => boolean; + export type MoveFunction = (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; + export type RemoveFunction = (document: Doc | Doc[]) => boolean; export interface DragDropDisposer { (): void; } export interface DragOptions { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 11866aebe..f602cbb15 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,4 +1,4 @@ -import { Doc, Opt, DataSym } from '../../new_fields/Doc'; +import { Doc, Opt, DataSym, DocListCast } from '../../new_fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; import { Cast, BoolCast, ScriptCast } from '../../new_fields/Types'; @@ -6,6 +6,8 @@ import { listSpec } from '../../new_fields/Schema'; import { InkingControl } from './InkingControl'; import { InkTool } from '../../new_fields/InkField'; import { InteractionUtils } from '../util/InteractionUtils'; +import { List } from '../../new_fields/List'; +import { DateField } from '../../new_fields/DateField'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) @@ -99,22 +101,37 @@ export function ViewBoxAnnotatableComponent

d as Doc), true) : -1; - return index !== -1 && value && value.splice(index, 1) ? true : false; + removeDocument(doc: Doc | Doc[]): boolean { + const docs = doc instanceof Doc ? [doc] : doc; + docs.map(doc => doc.annotationOn = undefined); + const targetDataDoc = this.dataDoc; + const value = DocListCast(targetDataDoc[this.props.fieldKey + "-" + this._annotationKey]); + const result = value.filter(v => !docs.includes(v)); + if (result.length !== value.length) { + targetDataDoc[this.props.fieldKey] = new List(result); + return true; + } + return false; } // if the moved document is already in this overlay collection nothing needs to be done. // otherwise, if the document can be removed from where it was, it will then be added to this document's overlay collection. @action.bound - moveDocument(doc: Doc, targetCollection: Doc | undefined, addDocument: (doc: Doc) => boolean): boolean { + moveDocument(doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean { return Doc.AreProtosEqual(this.props.Document, targetCollection) ? true : this.removeDocument(doc) ? addDocument(doc) : false; } @action.bound - addDocument(doc: Doc): boolean { - doc.context = Doc.GetProto(doc).annotationOn = this.props.Document; - return Doc.AddDocToList(this.dataDoc, this.props.fieldKey + "-" + this._annotationKey, doc) ? true : false; + addDocument(doc: Doc | Doc[]): boolean { + const docs = doc instanceof Doc ? [doc] : doc; + docs.map(doc => doc.context = Doc.GetProto(doc).annotationOn = this.props.Document); + const targetDataDoc = this.props.Document[DataSym]; + const docList = DocListCast(targetDataDoc[this.props.fieldKey + "-" + this._annotationKey]); + const added = docs.filter(d => !docList.includes(d)); + if (added.length) { + added.map(doc => doc.context = this.props.Document); + targetDataDoc[this.props.fieldKey + "-" + this._annotationKey] = new List([...docList, ...added]); + targetDataDoc[this.props.fieldKey + "-" + this._annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); + } + return true; } whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e67f2f3a2..5b838446d 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -520,9 +520,9 @@ export class MainView extends React.Component { return !this._flyoutTranslate ? (

) : (null); } - addButtonDoc = (doc: Doc) => Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc); - remButtonDoc = (doc: Doc) => Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc); - moveButtonDoc = (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => this.remButtonDoc(doc) && addDocument(doc); + addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); + remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); + moveButtonDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(doc) && addDocument(doc); buttonBarXf = () => { if (!this._docBtnRef.current) return Transform.Identity(); diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 665ab4e41..5f300372f 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -158,9 +158,9 @@ export class TemplateMenu extends React.Component { annotationsKey={""} dontRegisterView={true} fieldKey={"data"} - moveDocument={(doc: Doc) => false} - removeDocument={(doc: Doc) => false} - addDocument={(doc: Doc) => false} /> + moveDocument={returnFalse} + removeDocument={returnFalse} + addDocument={returnFalse} /> ; } } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 250c9b3b0..ae84b1923 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -27,9 +27,9 @@ import { CollectionView } from "./CollectionView"; import React = require("react"); export interface CollectionViewProps extends FieldViewProps { - addDocument: (document: Doc) => boolean; - removeDocument: (document: Doc) => boolean; - moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; + addDocument: (document: Doc | Doc[]) => boolean; + removeDocument: (document: Doc | Doc[]) => boolean; + moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; PanelWidth: () => number; PanelHeight: () => number; VisibleHeight?: () => number; @@ -212,14 +212,14 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: if (docDragData) { let added = false; if (docDragData.dropAction || docDragData.userDropAction) { - added = this.props.addDocument(docDragData.droppedDocuments as any as Doc); + added = this.props.addDocument(docDragData.droppedDocuments); } else if (docDragData.moveDocument) { const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d); const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d); - const res = addedDocs.length ? this.props.addDocument(addedDocs as any as Doc) : true; - added = movedDocs.length ? docDragData.moveDocument(movedDocs as any as Doc, this.props.Document, this.props.addDocument) : res; + const res = addedDocs.length ? this.props.addDocument(addedDocs) : true; + added = movedDocs.length ? docDragData.moveDocument(movedDocs, this.props.Document, this.props.addDocument) : res; } else { - added = this.props.addDocument(docDragData.droppedDocuments as any as Doc); + added = this.props.addDocument(docDragData.droppedDocuments); } e.stopPropagation(); return added; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 4fb54cc07..815202cfe 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -44,7 +44,7 @@ export interface TreeViewProps { containingCollection: Doc; prevSibling?: Doc; renderDepth: number; - deleteDoc: (doc: Doc) => boolean; + deleteDoc: (doc: Doc | Doc[]) => boolean; moveDocument: DragManager.MoveFunction; dropAction: dropActionType; addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean; @@ -52,7 +52,7 @@ export interface TreeViewProps { panelWidth: () => number; panelHeight: () => number; ChromeHeight: undefined | (() => number); - addDocument: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean; + addDocument: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean; indentDocument?: () => void; outdentDocument?: () => void; ScreenToLocalTransform: () => Transform; @@ -133,14 +133,16 @@ class TreeView extends React.Component { @undoBatch delete = () => this.props.deleteDoc(this.props.document); @undoBatch openRight = () => this.props.addDocTab(this.props.dropAction === "alias" ? Doc.MakeAlias(this.props.document) : this.props.document, "onRight", this.props.libraryPath); @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete(); - @undoBatch move = (doc: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => { + @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); } - @undoBatch @action remove = (document: Document, key: string) => { - return Doc.RemoveDocFromList(this.dataDoc, key, document); + @undoBatch @action remove = (doc: Doc | Doc[], key: string) => { + return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => + flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true); } - @undoBatch @action removeDoc = (document: Document) => { - return Doc.RemoveDocFromList(this.props.containingCollection, Doc.LayoutFieldKey(this.props.containingCollection), document); + @undoBatch @action removeDoc = (doc: Doc | Doc[]) => { + return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => + flg && Doc.RemoveDocFromList(this.props.containingCollection, Doc.LayoutFieldKey(this.props.containingCollection), doc), true); } protected createTreeDropTarget = (ele: HTMLDivElement) => { @@ -224,9 +226,10 @@ class TreeView extends React.Component { if (de.complete.docDragData) { e.stopPropagation(); if (de.complete.docDragData.draggedDocuments[0] === this.props.document) return true; - let addDoc = (doc: Doc) => this.props.addDocument(doc, undefined, before); + let addDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before); if (inside) { - addDoc = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) || addDoc(doc); + addDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce( + ((flg: boolean, doc) => flg && Doc.AddDocToList(this.dataDoc, this.fieldKey, doc)), true) || addDoc(doc); } const movedDocs = (de.complete.docDragData.treeViewId === this.props.treeViewId[Id] ? de.complete.docDragData.draggedDocuments : de.complete.docDragData.droppedDocuments); const move = de.complete.docDragData.dropAction === "move" || de.complete.docDragData.dropAction; @@ -286,8 +289,9 @@ class TreeView extends React.Component { let contentElement: (JSX.Element | null)[] | JSX.Element = []; if (contents instanceof Doc || (Cast(contents, listSpec(Doc)) && (Cast(contents, listSpec(Doc))!.length && Cast(contents, listSpec(Doc))![0] instanceof Doc))) { - const remDoc = (doc: Doc) => this.remove(doc, key); - const addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); + const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key); + const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce( + (flg, doc) => flg && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true), true); contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, @@ -330,8 +334,9 @@ class TreeView extends React.Component { TraceMobx(); const expandKey = this.treeViewExpandedView === this.fieldKey ? this.fieldKey : this.treeViewExpandedView === "links" ? "links" : undefined; if (expandKey !== undefined) { - const remDoc = (doc: Doc) => this.remove(doc, expandKey); - const addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true); + const remDoc = (doc: Doc | Doc[]) => this.remove(doc, expandKey); + const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => + (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true), true); const docs = expandKey === "links" ? this.childLinks : this.childDocs; const sortKey = `${this.fieldKey}-sortAscending`; return
    { @@ -464,6 +469,7 @@ class TreeView extends React.Component { ref={this._docRef} Document={this.props.document} DataDoc={undefined} + treeViewId={this.props.treeViewId[Id]} LibraryPath={this.props.libraryPath || emptyPath} addDocument={undefined} addDocTab={this.props.addDocTab} @@ -529,8 +535,8 @@ class TreeView extends React.Component { key: string, parentCollectionDoc: Doc | undefined, parentPrevSibling: Doc | undefined, - add: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean, - remove: ((doc: Doc) => boolean), + add: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean, + remove: ((doc: Doc | Doc[]) => boolean), move: DragManager.MoveFunction, dropAction: dropActionType, addDocTab: (doc: Doc, where: string) => boolean, @@ -619,7 +625,7 @@ class TreeView extends React.Component { remove(child); } }; - const addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => { + const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => { return add(doc, relativeTo ? relativeTo : docs[i], before !== undefined ? before : false); }; const childLayout = Doc.Layout(pair.layout); @@ -689,22 +695,26 @@ export class CollectionTreeView extends CollectionSubView { - const children = Cast(this.props.Document[DataSym][this.props.fieldKey], listSpec(Doc), []); - if (children.indexOf(document) !== -1) { - children.splice(children.indexOf(document), 1); + remove = (doc: Doc | Doc[]): boolean => { + const docs = doc instanceof Doc ? [doc] : doc as Doc[]; + const targetDataDoc = this.props.Document[DataSym]; + const value = DocListCast(targetDataDoc[this.props.fieldKey]); + const result = value.filter(v => !docs.includes(v)); + if (result.length !== value.length) { + targetDataDoc[this.props.fieldKey] = new List(result); return true; } return false; } @action - addDoc = (doc: Document, relativeTo: Opt, before?: boolean): boolean => { - const doAddDoc = () => - Doc.AddDocToList(this.props.Document[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false); + addDoc = (doc: Doc | Doc[], relativeTo: Opt, before?: boolean): boolean => { + const doAddDoc = (doc: Doc | Doc[]) => + (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => + flg && Doc.AddDocToList(this.props.Document[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false), true); if (this.props.Document.resolvedDataDoc instanceof Promise) { - this.props.Document.resolvedDataDoc.then((resolved: any) => doAddDoc()); + this.props.Document.resolvedDataDoc.then((resolved: any) => doAddDoc(doc)); } else { - doAddDoc(); + doAddDoc(doc); } return true; } @@ -788,8 +798,8 @@ export class CollectionTreeView extends CollectionSubView this.addDoc(doc, relativeTo, before); - const moveDoc = (d: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); + const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before); + const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(d, target, addDoc); const childDocs = this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs; return !childDocs ? (null) : (
    this.props.whenActiveChanged(this._isChildActive = isActive); @action.bound - addDocument = (doc: Doc): boolean => { + addDocument = (doc: Doc | Doc[]): boolean => { if (doc instanceof Doc) { if (this.props.filterAddDocument?.(doc) === false) { return false; } } - const docs = doc instanceof Doc ? [doc] : doc as any as Doc[]; + const docs = doc instanceof Doc ? [doc] : doc; const targetDataDoc = this.props.Document[DataSym]; const docList = DocListCast(targetDataDoc[this.props.fieldKey]); const added = docs.filter(d => !docList.includes(d)); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 6011d5f9c..b32318d66 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -123,7 +123,7 @@ export class CollectionFreeFormView extends CollectionSubView { + private addDocument = (newBox: Doc | Doc[]) => { if (newBox instanceof Doc) { const added = this.props.addDocument(newBox); added && this.bringToFront(newBox); @@ -184,7 +184,7 @@ export class CollectionFreeFormView extends CollectionSubView { - this.props.removeDocument(this.marqueeSelect(false) as any as Doc); + this.props.removeDocument(this.marqueeSelect(false)); SelectionManager.DeselectAll(); this.cleanupInteractions(false); MarqueeOptionsMenu.Instance.fadeOut(true); @@ -352,7 +352,7 @@ export class MarqueeView extends React.Component void; - addDocument?: (doc: Doc) => boolean; - removeDocument?: (doc: Doc) => boolean; - moveDocument?: (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; + addDocument?: (doc: Doc | Doc[]) => boolean; + removeDocument?: (doc: Doc | Doc[]) => boolean; + moveDocument?: (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; ScreenToLocalTransform: () => Transform; setupDragLines?: () => void; renderDepth: number; @@ -243,6 +244,7 @@ export class DocumentView extends DocComponent(Docu dragData.removeDocument = this.props.removeDocument; dragData.moveDocument = this.props.moveDocument;// this.Document.onDragStart ? undefined : this.props.moveDocument; dragData.dragDivName = this.props.dragDivName; + dragData.treeViewId = this.props.treeViewId; DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.Document.onDragStart }); } } @@ -1043,7 +1045,7 @@ export class DocumentView extends DocComponent(Docu makeLink = () => this._link; // pass the link placeholde to child views so they can react to make a specialized anchor. This is essentially a function call to the descendants since the value of the _link variable will immediately get set back to undefined. @undoBatch - hideLinkAnchor = (doc: Doc) => doc.hidden = true + hideLinkAnchor = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && (doc.hidden = true), true) anchorPanelWidth = () => this.props.PanelWidth() || 1; anchorPanelHeight = () => this.props.PanelHeight() || 1; @computed get anchors() { @@ -1143,7 +1145,7 @@ export class DocumentView extends DocComponent(Docu const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"]; let highlighting = fullDegree && this.layoutDoc.type !== DocumentType.FONTICON && this.layoutDoc._viewType !== CollectionViewType.Linear; highlighting = highlighting && this.props.focus !== emptyFunction; // bcz: hack to turn off highlighting onsidebar panel documents. need to flag a document as not highlightable in a more direct way - return
    void; rootSelected: (outsideReaction?: boolean) => boolean; renderDepth: number; - addDocument?: (document: Doc) => boolean; + addDocument?: (document: Doc | Doc[]) => boolean; addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; - removeDocument?: (document: Doc) => boolean; - moveDocument?: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; + removeDocument?: (document: Doc | Doc[]) => boolean; + moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; backgroundColor?: (document: Doc) => string | undefined; ScreenToLocalTransform: () => Transform; bringToFront: (doc: Doc, sendToBack?: boolean) => void; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 343e74c87..49862d39a 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -271,9 +271,12 @@ export class PresBox extends ViewBoxBaseComponent }); whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); - addDocumentFilter = (doc: Doc) => { - doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf); - !this.childDocs.includes(doc) && (doc.presZoomButton = true); + addDocumentFilter = (doc: Doc|Doc[]) => { + const docs = doc instanceof Doc ? [doc]: doc; + docs.forEach(doc => { + doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf); + !this.childDocs.includes(doc) && (doc.presZoomButton = true); + }); return true; } childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 266b7f43f..208b93ba6 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -337,9 +337,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent { + const curTime = (this.layoutDoc.currentTimecode || -1); + curTime !== -1 && (doc.displayTimecode = curTime); + }) return this.addDocument(doc); } -- cgit v1.2.3-70-g09d2 From 136165e9c960be255396830e3a9d44532ee0cda7 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 7 May 2020 23:41:08 -0400 Subject: fixed tree view title editing. cleaned up annotation keys in DocComponent --- src/client/views/DocComponent.tsx | 15 ++++++------- src/client/views/collections/CollectionSubView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 26 +++++++--------------- src/client/views/nodes/DocumentView.tsx | 2 +- 4 files changed, 17 insertions(+), 28 deletions(-) (limited to 'src/client/views/DocComponent.tsx') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index f602cbb15..4e7d4c5ed 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -97,18 +97,17 @@ export function ViewBoxAnnotatableComponent

    doc.annotationOn = undefined); - const targetDataDoc = this.dataDoc; - const value = DocListCast(targetDataDoc[this.props.fieldKey + "-" + this._annotationKey]); + const targetDataDoc = this.dataDoc; this + const value = DocListCast(targetDataDoc[this.annotationKey]); const result = value.filter(v => !docs.includes(v)); if (result.length !== value.length) { - targetDataDoc[this.props.fieldKey] = new List(result); + targetDataDoc[this.annotationKey] = new List(result); return true; } return false; @@ -124,12 +123,12 @@ export function ViewBoxAnnotatableComponent

    doc.context = Doc.GetProto(doc).annotationOn = this.props.Document); const targetDataDoc = this.props.Document[DataSym]; - const docList = DocListCast(targetDataDoc[this.props.fieldKey + "-" + this._annotationKey]); + const docList = DocListCast(targetDataDoc[this.annotationKey]); const added = docs.filter(d => !docList.includes(d)); if (added.length) { added.map(doc => doc.context = this.props.Document); - targetDataDoc[this.props.fieldKey + "-" + this._annotationKey] = new List([...docList, ...added]); - targetDataDoc[this.props.fieldKey + "-" + this._annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); + targetDataDoc[this.annotationKey] = new List([...docList, ...added]); + targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); } return true; } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index ae84b1923..d1c2d9a76 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -95,7 +95,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: // to its children which may be templates. // If 'annotationField' is specified, then all children exist on that field of the extension document, otherwise, they exist directly on the data document under 'fieldKey' @computed get dataField() { - return this.dataDoc[this.props.fieldKey + (this.props.annotationsKey ? "-" + this.props.annotationsKey : "")]; + return this.dataDoc[this.props.annotationsKey || this.props.fieldKey]; } get childLayoutPairs(): { layout: Doc; data: Doc; }[] { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 92018a5b8..52ffd74c9 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -90,35 +90,25 @@ class TreeView extends React.Component { @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.props.document.treeViewPreventOpen && BoolCast(this.props.document.treeViewOpen)) || this._overrideTreeViewOpen; } @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, this.defaultExpandedView); } @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); } - @computed get dataDoc() { return this.templateDataDoc ? this.templateDataDoc : this.props.document; } + @computed get dataDoc() { return this.props.document[DataSym]; } @computed get fieldKey() { const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\'"); return splits.length > 1 ? splits[1].split("\'")[0] : "data"; } childDocList(field: string) { const layout = Doc.LayoutField(this.props.document) instanceof Doc ? Doc.LayoutField(this.props.document) as Doc : undefined; - return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || - (layout ? Cast(layout[field], listSpec(Doc)) : undefined) || - Cast(this.props.document[field], listSpec(Doc))) as Doc[]; + return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field + (layout ? Cast(layout[field], listSpec(Doc)) : undefined) || // else if there's a layout doc, display it's fields + Cast(this.props.document[field], listSpec(Doc))) as Doc[]; // otherwise use the document's data field } @computed get childDocs() { return this.childDocList(this.fieldKey); } @computed get childLinks() { return this.childDocList("links"); } - @computed get templateDataDoc() { - if (this.props.dataDoc === undefined && Doc.LayoutField(this.props.document) !== "string") { - // if there is no dataDoc (ie, we're not rendering a template layout), but this document has a layout document (not a layout string), - // then we render the layout document as a template and use this document as the data context for the template layout. - return this.props.document; - } - return this.props.dataDoc; - } @computed get boundsOfCollectionDocument() { return StrCast(this.props.document.type).indexOf(DocumentType.COL) === -1 || !DocListCast(this.props.document[this.fieldKey]).length ? undefined : Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey])); } - @undoBatch delete = () => this.props.deleteDoc(this.props.document); @undoBatch openRight = () => this.props.addDocTab(this.props.dropAction === "alias" ? Doc.MakeAlias(this.props.document) : this.props.document, "onRight", this.props.libraryPath); - @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete(); @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); } @@ -132,7 +122,7 @@ class TreeView extends React.Component { } protected createTreeDropTarget = (ele: HTMLDivElement) => { - this._treedropDisposer && this._treedropDisposer(); + this._treedropDisposer?.(); ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this)), this.props.document); } @@ -331,7 +321,7 @@ class TreeView extends React.Component { }}> {!docs ? (null) : TreeView.GetChildElements(docs, this.props.treeViewId, Doc.Layout(this.props.document), - this.templateDataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, + this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, StrCast(this.props.document.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, [...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields)} @@ -347,7 +337,7 @@ class TreeView extends React.Component { return

    { get renderTitle() { TraceMobx(); const onItemDown = SetupDrag(this._tref, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId[Id], true); - (!TreeView._editTitleScript) && (TreeView._editTitleScript = ScriptField.MakeFunction("setInPlace(this, 'editTitle', true)")); + (!TreeView._editTitleScript) && (TreeView._editTitleScript = ScriptField.MakeFunction("setInPlace(self, 'editTitle', true)")); const headerElements = ( <> this.showContextMenu(e)}> diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 042869004..b97b607b9 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1081,7 +1081,7 @@ export class DocumentView extends DocComponent(Docu
    `} + LayoutTemplateString={``} ContentScaling={this.childScaling} ChromeHeight={this.chromeHeight} isSelected={this.isSelected} -- cgit v1.2.3-70-g09d2 From 5c876f2f456f75e9886946f738f07a730688f38a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 9 May 2020 17:44:14 -0400 Subject: lint fixes --- src/Utils.ts | 2 +- src/client/DocServer.ts | 2 +- src/client/views/DocComponent.tsx | 2 +- src/client/views/collections/CollectionSchemaCells.tsx | 6 +++--- .../views/collections/CollectionSchemaMovableTableHOC.tsx | 8 ++++---- src/client/views/collections/CollectionSchemaView.tsx | 6 +++--- src/client/views/collections/CollectionSubView.tsx | 6 +++--- src/client/views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/linking/LinkMenuItem.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 2 +- src/client/views/nodes/formattedText/DashFieldView.tsx | 5 +++-- src/new_fields/Doc.ts | 12 ++++++------ 14 files changed, 30 insertions(+), 29 deletions(-) (limited to 'src/client/views/DocComponent.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 732f74bfc..bcb215804 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -323,7 +323,7 @@ export function OmitKeys(obj: any, keys: string[], pattern?: string, addKeyFunc? 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/DocServer.ts b/src/client/DocServer.ts index bf9fd232c..34ef502ad 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -250,7 +250,7 @@ export namespace DocServer { if (cached !== undefined && !(cached instanceof Promise)) { return cached; } - } + }; let _GetRefField: (id: string) => Promise> = errorFunc; let _GetCachedRefField: (id: string) => Opt = errorFunc; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 4e7d4c5ed..881e352a6 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -103,7 +103,7 @@ export function ViewBoxAnnotatableComponent

    doc.annotationOn = undefined); - const targetDataDoc = this.dataDoc; this + const targetDataDoc = this.dataDoc; const value = DocListCast(targetDataDoc[this.annotationKey]); const result = value.filter(v => !docs.includes(v)); if (result.length !== value.length) { diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 5253ee0b9..8a5450b0c 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -37,8 +37,8 @@ export interface CellProps { renderDepth: number; addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; - moveDocument: (document: Doc, targetCollection: Doc | undefined, - addDocument: (document: Doc) => boolean) => boolean; + moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined, + addDocument: (document: Doc | Doc[]) => boolean) => boolean; isFocused: boolean; changeFocusedCellByIndex: (row: number, col: number) => void; setIsEditing: (isEditing: boolean) => void; @@ -185,7 +185,7 @@ export class CollectionSchemaCell extends React.Component { const onItemDown = (e: React.PointerEvent) => { fieldIsDoc && SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, - this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc | undefined, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, + this._document[props.fieldKey] instanceof Doc ? (doc: Doc | Doc[], target: Doc | undefined, addDoc: (newDoc: Doc | Doc[]) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); }; const onPointerEnter = (e: React.PointerEvent): void => { diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 8636e3eb5..5aec46a83 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -130,8 +130,8 @@ export class MovableColumn extends React.Component { export interface MovableRowProps { rowInfo: RowInfo; ScreenToLocalTransform: () => Transform; - addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean; - removeDoc: (doc: Doc) => boolean; + addDoc: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean; + removeDoc: (doc: Doc | Doc[]) => boolean; rowFocused: boolean; textWrapRow: (doc: Doc) => void; rowWrapped: boolean; @@ -183,7 +183,7 @@ export class MovableRow extends React.Component { if (docDragData) { e.stopPropagation(); if (docDragData.draggedDocuments[0] === rowDoc) return true; - const addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before); + const addDocument = (doc: Doc | Doc[]) => this.props.addDoc(doc, rowDoc, before); const movedDocs = docDragData.draggedDocuments; return (docDragData.dropAction || docDragData.userDropAction) ? docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) @@ -201,7 +201,7 @@ export class MovableRow extends React.Component { @undoBatch @action - move: DragManager.MoveFunction = (doc: Doc, targetCollection: Doc | undefined, addDoc) => { + move: DragManager.MoveFunction = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc) => { const targetView = targetCollection && DocumentManager.Instance.getDocumentView(targetCollection); if (targetView && targetView.props.ContainingCollectionDoc) { return doc !== targetCollection && doc !== targetView.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc); diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index c0024293f..51ad6c81b 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -207,9 +207,9 @@ export interface SchemaTableProps { ContainingCollectionDoc: Opt; fieldKey: string; renderDepth: number; - deleteDocument: (document: Doc) => boolean; - addDocument: (document: Doc) => boolean; - moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; + deleteDocument: (document: Doc | Doc[]) => boolean; + addDocument: (document: Doc | Doc[]) => boolean; + moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; ScreenToLocalTransform: () => Transform; active: (outsideReaction: boolean) => boolean; onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined) => void; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 4fef16315..8b50bd8fc 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -246,7 +246,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: }; temporaryFileReader.readAsText(inputFile); }); - }; + } @undoBatch @action protected async onExternalDrop(e: React.DragEvent, options: DocumentOptions, completed?: () => void) { @@ -388,11 +388,11 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: file?.type === "application/json" && this.readUploadedFileAsText(file).then(result => { console.log(result); - const json = JSON.parse(result as string) as any; + const json = JSON.parse(result as string); addDocument(Docs.Create.TreeDocument( json["rectangular-puzzle"].crossword.clues[0].clue.map((c: any) => { const label = Docs.Create.LabelDocument({ title: c["#text"], _width: 120, _height: 20 }); - const proto = Doc.GetProto(label) + const proto = Doc.GetProto(label); proto._width = 120; proto._height = 20; return proto; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 7086ba380..f6fcc1ac4 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -673,7 +673,7 @@ export class CollectionTreeView extends CollectionSubView { - const docs = doc instanceof Doc ? [doc] : doc as Doc[]; + const docs = doc instanceof Doc ? [doc] : doc; const targetDataDoc = this.props.Document[DataSym]; const value = DocListCast(targetDataDoc[this.props.fieldKey]); const result = value.filter(v => !docs.includes(v)); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 6c96baede..0841d9680 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -152,7 +152,7 @@ export class CollectionView extends Touchable boolean): boolean => { + moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { if (Doc.AreProtosEqual(this.props.Document, targetCollection)) { return true; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index dfcb30588..6cc0cfcd2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -786,7 +786,7 @@ export class CollectionFreeFormView extends CollectionSubView boolean): boolean => { + dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { docView.props.removeDocument?.(doc); addDocument(doc); return true; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 208b93ba6..9602eac52 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -342,7 +342,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { const curTime = (this.layoutDoc.currentTimecode || -1); curTime !== -1 && (doc.displayTimecode = curTime); - }) + }); return this.addDocument(doc); } diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index f28057fd7..d5a28fd14 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -82,7 +82,7 @@ export class DashFieldViewInternal extends React.Component(); - let rtfMap: { copy: Doc, key: string, field: RichTextField }[] = []; + const cloneMap = new Map(); + const rtfMap: { copy: Doc, key: string, field: RichTextField }[] = []; const copy = Doc.makeClone(doc, cloneMap, rtfMap); rtfMap.map(({ copy, key, field }) => { const replacer = (match: any, attr: string, id: string, offset: any, string: any) => { @@ -605,7 +605,7 @@ export namespace Doc { return href + (mapped ? mapped[Id] : id); }; const regex = `(${Utils.prepend("/doc/")})([^"]*)`; - var re = new RegExp(regex, "g"); + const re = new RegExp(regex, "g"); copy[key] = new RichTextField(field.Data.replace(/("docid":|"targetId":|"linkId":)"([^"]+)"/g, replacer).replace(re, replacer2), field.Text); }); return copy; @@ -626,9 +626,9 @@ export namespace Doc { const list = Cast(doc[key], listSpec(Doc)); if (list !== undefined && !(list instanceof Promise)) { copy[key] = new List(list.filter(d => d instanceof Doc).map(d => Doc.makeClone(d as Doc, cloneMap, rtfs))); - } else if (doc[key] instanceof Doc) + } else if (doc[key] instanceof Doc) { copy[key] = key.includes("layout[") ? undefined : Doc.makeClone(doc[key] as Doc, cloneMap, rtfs); // reference documents except copy documents that are expanded teplate fields - else { + } else { copy[key] = ObjectField.MakeCopy(field); if (field instanceof RichTextField) { if (field.Data.includes('"docid":') || field.Data.includes('"targetId":') || field.Data.includes('"linkId":')) { @@ -636,7 +636,7 @@ export namespace Doc { } } } - } + }; if (key === "proto") { if (doc[key] instanceof Doc) { copy[key] = Doc.makeClone(doc[key]!, cloneMap, rtfs); -- cgit v1.2.3-70-g09d2