From b74b5888c7c0eee6c0f7a7e8f6d44b9a21b46f0b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 31 Jan 2020 00:09:07 -0500 Subject: from last --- src/client/views/presentationview/PresElementBox.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index 34c170be2..ac78babef 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -43,9 +43,11 @@ } .presElementBox-closeIcon { - float: right; border-radius: 20px; transform:scale(0.7); + position: absolute; + right: 0; + top: 0; } .presElementBox-interaction { -- cgit v1.2.3-70-g09d2 From f4662822d9dd3280e843c3f088aee310352705ae Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 31 Jan 2020 09:03:55 -0500 Subject: streamlined presentationview --- .../views/collections/CollectionDockingView.tsx | 2 +- src/client/views/nodes/PresBox.scss | 4 +--- src/client/views/nodes/PresBox.tsx | 6 +++--- .../views/presentationview/PresElementBox.scss | 20 +++++++++++++++----- .../authentication/models/current_user_utils.ts | 2 +- 5 files changed, 21 insertions(+), 13 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 82cb3bc88..159a1cded 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -643,7 +643,7 @@ export class DockedFrameRenderer extends React.Component { //add this new doc to props.Document const curPres = Cast(CurrentUserUtils.UserDocument.curPresentation, Doc) as Doc; if (curPres) { - const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); + const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5 }); Doc.GetProto(pinDoc).presentationTargetDoc = doc; Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('(this.presentationTargetDoc instanceof Doc) && this.presentationTargetDoc.title?.toString()'); const data = Cast(curPres.data, listSpec(Doc)); diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index e5a79ab11..01e7f4834 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -6,7 +6,7 @@ top: 0; bottom: 0; width: 100%; - min-width: 200px; + min-width: 100px; height: 100%; min-height: 50px; letter-spacing: 2px; @@ -16,8 +16,6 @@ .presBox-listCont { position: relative; - padding-left: 10px; - padding-right: 10px; } .presBox-buttons { diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 428e9aa7b..8d53f45a6 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -42,7 +42,7 @@ export class PresBox extends React.Component { if (value) { value.forEach((item, i) => { if (item instanceof Doc && item.type !== DocumentType.PRESELEMENT) { - const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); + const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5 }); Doc.GetProto(pinDoc).presentationTargetDoc = item; Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('this.presentationTargetDoc?.title?.toString()'); value.splice(i, 1, pinDoc); @@ -337,7 +337,7 @@ export class PresBox extends React.Component { @action initializeScaleViews = (docList: Doc[], viewtype: number) => { this.props.Document._chromeStatus = "disabled"; - const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 72; + const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 42; docList.forEach((doc: Doc) => { doc.presBox = this.props.Document; doc.presBoxKey = this.props.fieldKey; @@ -357,7 +357,7 @@ export class PresBox extends React.Component { } getTransform = () => { - return this.props.ScreenToLocalTransform().translate(-10, -50);// listBox padding-left and pres-box-cont minHeight + return this.props.ScreenToLocalTransform().translate(0, -50);// listBox padding-left and pres-box-cont minHeight } render() { this.initializeScaleViews(this.childDocs, NumCast(this.props.Document._viewType)); diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index ac78babef..b74b07224 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -6,14 +6,17 @@ width: 100%; outline-color: maroon; outline-style: dashed; - border-radius: 12px; + border-radius: 6px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; - transition: all .1s; + transition: all .1s; + padding: 0px; + padding-left: 5px; + padding-bottom: 3px; .documentView-node { position: absolute; @@ -32,13 +35,13 @@ .presElementBox-item:hover { transition: all .1s; background: #AAAAAA; - border-radius: 12px; + border-radius: 6px; } .presElementBox-selected { background: gray; color: black; - border-radius: 12px; + border-radius: 6px; box-shadow: black 2px 2px 5px; } @@ -48,20 +51,27 @@ position: absolute; right: 0; top: 0; + padding: 8px; } .presElementBox-interaction { color: gray; float: left; + padding: 0px; + width: 20px; + height: 20px; } .presElementBox-interaction-selected { color: white; float: left; + padding: 0px; + width: 22px; + height: 22px; } .presElementBox-name { - font-size: 15px; + font-size: 12px; position: absolute; display: inline-block; width: calc(100% - 45px); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index dbde351b3..6bfc729de 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -55,7 +55,7 @@ export class CurrentUserUtils { { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' }, { title: "record", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` }, { title: "clickable button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, title: "Button" })' }, - { title: "presentation", icon: "tv", ignoreClick: true, drag: `Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { _width: 200, _height: 500, _viewType: ${CollectionViewType.Stacking}, title: "a presentation trail" })` }, + { title: "presentation", icon: "tv", ignoreClick: true, drag: `Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { _width: 200, _height: 500, _xMargin:5, _viewType: ${CollectionViewType.Stacking}, title: "a presentation trail" })` }, { title: "import folder", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, { title: "mobile view", icon: "phone", ignoreClick: true, drag: 'Doc.UserDoc().activeMobile' }, { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, -- cgit v1.2.3-70-g09d2 From 693665069c170983bd76336b804ec73870642fe3 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 1 Feb 2020 16:25:10 -0500 Subject: simplified Presentations a bit by using templates --- .../views/collections/CollectionDockingView.tsx | 15 ++-- src/client/views/nodes/DocumentContentsView.tsx | 7 +- src/client/views/nodes/ImageBox.tsx | 6 +- src/client/views/nodes/PresBox.tsx | 54 +++++++------- .../views/presentationview/PresElementBox.tsx | 85 ++++++++++++---------- src/new_fields/Doc.ts | 16 ++-- 6 files changed, 97 insertions(+), 86 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 159a1cded..e691788ad 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -35,6 +35,7 @@ import { ComputedField } from '../../../new_fields/ScriptField'; import { InteractionUtils } from '../../util/InteractionUtils'; import { TraceMobx } from '../../../new_fields/util'; import { Scripting } from '../../util/Scripting'; +import { PresElementBox } from '../presentationview/PresElementBox'; library.add(faFile); const _global = (window /* browser */ || global /* node */) as any; @@ -326,7 +327,7 @@ export class CollectionDockingView extends React.Component void = () => { if (this._containerRef.current) { this.reactionDisposer = reaction( - () => StrCast(this.props.Document.dockingConfig), + () => this.props.Document.dockingConfig, () => { if (!this._goldenLayout || this._ignoreStateChange !== JSON.stringify(this._goldenLayout.toConfig())) { // Because this is in a set timeout, if this component unmounts right after mounting, @@ -643,15 +644,9 @@ export class DockedFrameRenderer extends React.Component { //add this new doc to props.Document const curPres = Cast(CurrentUserUtils.UserDocument.curPresentation, Doc) as Doc; if (curPres) { - const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5 }); - Doc.GetProto(pinDoc).presentationTargetDoc = doc; - Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('(this.presentationTargetDoc instanceof Doc) && this.presentationTargetDoc.title?.toString()'); - const data = Cast(curPres.data, listSpec(Doc)); - if (data) { - data.push(pinDoc); - } else { - curPres.data = new List([pinDoc]); - } + const pinDoc = Doc.MakeAlias(doc); + pinDoc.presentationTargetDoc = doc; + Doc.AddDocToList(curPres, "data", pinDoc); if (!DocumentManager.Instance.getDocumentView(curPres)) { this.addDocTab(curPres, undefined, "onRight"); } diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 0b01e6471..3b9015994 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -81,6 +81,11 @@ export class DocumentContentsView extends React.Component 7 || !this.layout) ? (null) : + return (this.props.renderDepth > 7 || !this.layout || !this.layoutDoc) ? (null) : console.log(err)); } else if (this.Document._nativeHeight !== cachedNativeSize.width || this.Document._nativeWidth !== cachedNativeSize.height) { !(this.Document[StrCast(this.props.Document.layoutKey)] instanceof Doc) && setTimeout(() => { - this.Document._nativeWidth = cachedNativeSize.width; - this.Document._nativeHeight = cachedNativeSize.height; + if (!(this.Document[StrCast(this.props.Document.layoutKey)] instanceof Doc)) { + this.Document._nativeWidth = cachedNativeSize.width; + this.Document._nativeHeight = cachedNativeSize.height; + } }, 0); } } diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 8d53f45a6..c661b7f4e 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -2,23 +2,22 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, reaction, IReactionDisposer } from "mobx"; +import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { listSpec } from "../../../new_fields/Schema"; +import { ComputedField } from "../../../new_fields/ScriptField"; import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; +import { Docs } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; -import { CollectionViewType } from "../collections/CollectionView"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionView } from "../collections/CollectionView"; +import { CollectionView, CollectionViewType } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { Docs } from "../../documents/Documents"; -import { ComputedField } from "../../../new_fields/ScriptField"; +import { presSchema } from "../presentationview/PresElementBox"; library.add(faArrowLeft); library.add(faArrowRight); @@ -32,28 +31,18 @@ library.add(faEdit); @observer export class PresBox extends React.Component { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } - _docListChangedReaction: IReactionDisposer | undefined; componentDidMount() { - this._docListChangedReaction = reaction(() => { - const value = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); - return value ? value.slice() : value; - }, () => { - const value = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); - if (value) { - value.forEach((item, i) => { - if (item instanceof Doc && item.type !== DocumentType.PRESELEMENT) { - const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5 }); - Doc.GetProto(pinDoc).presentationTargetDoc = item; - Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('this.presentationTargetDoc?.title?.toString()'); - value.splice(i, 1, pinDoc); - } - }); - } - }); - } - - componentWillUnmount() { - this._docListChangedReaction && this._docListChangedReaction(); + const userDoc = CurrentUserUtils.UserDocument; + let presTemp = Cast(userDoc.presentationTemplate, Doc); + if (presTemp instanceof Promise) { + presTemp.then(presTemp => this.props.Document.childLayout = presTemp); + } + else if (presTemp === undefined) { + presTemp = userDoc.presentationTemplate = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5, isTemplateDoc: true, isTemplateForField: "data" }); + } + else { + this.props.Document.childLayout = presTemp; + } } @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } @@ -282,6 +271,13 @@ export class PresBox extends React.Component { } } + addDocument = (doc: Doc) => { + const newPinDoc = Doc.MakeAlias(doc); + newPinDoc.presentationTargetDoc = doc; + return Doc.AddDocToList(this.props.Document, this.props.fieldKey, newPinDoc); + } + + //The function that resets the presentation by removing every action done by it. It also //stops the presentaton. @action @@ -342,7 +338,7 @@ export class PresBox extends React.Component { doc.presBox = this.props.Document; doc.presBoxKey = this.props.fieldKey; doc.collapsedHeight = hgt; - doc._height = ComputedField.MakeFunction("this.collapsedHeight + Number(this.embedOpen ? 100:0)"); + doc._nativeWidth = doc._nativeHeight = undefined; const curScale = NumCast(doc.viewScale, null); if (curScale === undefined) { doc.viewScale = 1; @@ -373,7 +369,7 @@ export class PresBox extends React.Component { {this.props.Document.inOverlay ? (null) :
- +
} diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index dad55e1fd..afc88833e 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -2,7 +2,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons'; import { faArrowDown, faArrowUp, faFile as fileSolid, faFileDownload, faLocationArrow, faSearch } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed } from "mobx"; +import { action, computed, reaction, IReactionDisposer } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../../new_fields/Doc"; import { documentSchema } from '../../../new_fields/documentSchemas'; @@ -14,7 +14,7 @@ import { DocumentType } from "../../documents/DocumentTypes"; import { Transform } from "../../util/Transform"; import { CollectionViewType } from '../collections/CollectionView'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; -import { DocComponent } from '../DocComponent'; +import { DocComponent, DocExtendableComponent } from '../DocComponent'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./PresElementBox.scss"; import React = require("react"); @@ -46,13 +46,23 @@ const PresDocument = makeInterface(presSchema, documentSchema); * It involves some functionality for its buttons and options. */ @observer -export class PresElementBox extends DocComponent(PresDocument) { +export class PresElementBox extends DocExtendableComponent(PresDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); } - @computed get indexInPres() { return DocListCast(this.presentationDoc[this.Document.presBoxKey || ""]).indexOf(this.props.Document); } - @computed get presentationDoc() { return Cast(this.Document.presBox, Doc) as Doc; } - @computed get targetDoc() { return this.Document.presentationTargetDoc as Doc; } - @computed get currentIndex() { return NumCast(this.presentationDoc.selectedDoc); } + _heightDisposer: IReactionDisposer | undefined; + @computed get indexInPres() { return this.originalLayout?.presBoxKey ? DocListCast(this.presentationDoc[StrCast(this.originalLayout?.presBoxKey)]).indexOf(this.originalLayout) : 0; } + @computed get presentationDoc() { return Cast(this.originalLayout?.presBox, Doc) as Doc; } + @computed get originalLayout() { return this.props.Document.expandedTemplate as Doc; } + @computed get targetDoc() { return this.originalLayout?.presentationTargetDoc as Doc; } + @computed get currentIndex() { return NumCast(this.presentationDoc?.selectedDoc); } + + componentDidMount() { + this._heightDisposer = reaction(() => [this.originalLayout.embedOpen, this.originalLayout.collapsedHeight], + params => this.originalLayout._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true }); + } + componentWillUnmount() { + this._heightDisposer?.(); + } /** * The function that is called on click to turn Hiding document till press option on/off. @@ -61,8 +71,8 @@ export class PresElementBox extends DocComponent(P @action onHideDocumentUntilPressClick = (e: React.MouseEvent) => { e.stopPropagation(); - this.Document.hideTillShownButton = !this.Document.hideTillShownButton; - if (!this.Document.hideTillShownButton) { + this.originalLayout.hideTillShownButton = !this.originalLayout.hideTillShownButton; + if (!this.originalLayout.hideTillShownButton) { if (this.indexInPres >= this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 1; } @@ -81,13 +91,13 @@ export class PresElementBox extends DocComponent(P @action onHideDocumentAfterPresentedClick = (e: React.MouseEvent) => { e.stopPropagation(); - this.Document.hideAfterButton = !this.Document.hideAfterButton; - if (!this.Document.hideAfterButton) { + this.originalLayout.hideAfterButton = !this.originalLayout.hideAfterButton; + if (!this.originalLayout.hideAfterButton) { if (this.indexInPres <= this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 1; } } else { - if (this.Document.fadeButton) this.Document.fadeButton = false; + if (this.originalLayout.fadeButton) this.originalLayout.fadeButton = false; if (this.presentationDoc.presStatus && this.indexInPres < this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 0; } @@ -102,13 +112,13 @@ export class PresElementBox extends DocComponent(P @action onFadeDocumentAfterPresentedClick = (e: React.MouseEvent) => { e.stopPropagation(); - this.Document.fadeButton = !this.Document.fadeButton; - if (!this.Document.fadeButton) { + this.originalLayout.fadeButton = !this.originalLayout.fadeButton; + if (!this.originalLayout.fadeButton) { if (this.indexInPres <= this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 1; } } else { - this.Document.hideAfterButton = false; + this.originalLayout.hideAfterButton = false; if (this.presentationDoc.presStatus && (this.indexInPres < this.currentIndex) && this.targetDoc) { this.targetDoc.opacity = 0.5; } @@ -121,11 +131,11 @@ export class PresElementBox extends DocComponent(P @action onNavigateDocumentClick = (e: React.MouseEvent) => { e.stopPropagation(); - this.Document.navButton = !this.Document.navButton; - if (this.Document.navButton) { - this.Document.showButton = false; + this.originalLayout.navButton = !this.originalLayout.navButton; + if (this.originalLayout.navButton) { + this.originalLayout.showButton = false; if (this.currentIndex === this.indexInPres) { - this.props.focus(this.props.Document); + this.props.focus(this.originalLayout); } } } @@ -137,13 +147,13 @@ export class PresElementBox extends DocComponent(P onZoomDocumentClick = (e: React.MouseEvent) => { e.stopPropagation(); - this.Document.showButton = !this.Document.showButton; - if (!this.Document.showButton) { - this.props.Document.viewScale = 1; + this.originalLayout.showButton = !this.originalLayout.showButton; + if (!this.originalLayout.showButton) { + this.originalLayout.viewScale = 1; } else { - this.Document.navButton = false; + this.originalLayout.navButton = false; if (this.currentIndex === this.indexInPres) { - this.props.focus(this.props.Document); + this.props.focus(this.originalLayout); } } } @@ -157,7 +167,7 @@ export class PresElementBox extends DocComponent(P * presentation element. */ renderEmbeddedInline = () => { - if (!this.Document.embedOpen || !this.targetDoc) { + if (!this.originalLayout.embedOpen || !this.targetDoc) { return (null); } @@ -170,7 +180,8 @@ export class PresElementBox extends DocComponent(P width: propDocWidth === 0 ? "auto" : propDocWidth * scale(), }}> (P const treecontainer = this.props.ContainingCollectionDoc?._viewType === CollectionViewType.Tree; const className = "presElementBox-item" + (this.currentIndex === this.indexInPres ? " presElementBox-selected" : ""); const pbi = "presElementBox-interaction"; - return ( + return !this.originalLayout ? (null) : (
{ this.props.focus(this.props.Document); e.stopPropagation(); }}> + onClick={e => { this.props.focus(this.originalLayout); e.stopPropagation(); }}> {treecontainer ? (null) : <> - {`${this.indexInPres + 1}. ${this.Document.title}`} + {`${this.indexInPres + 1}. ${this.targetDoc?.title}`} - +
} - - - - - - - + + + + + + +
{this.renderEmbeddedInline()} diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 5f78636a9..0624d6698 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -445,8 +445,8 @@ export namespace Doc { // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties // of the original layout while allowing for individual layout properties to be overridden in the expanded layout. // - export function expandTemplateLayout(templateLayoutDoc: Doc, dataDoc?: Doc) { - if (!WillExpandTemplateLayout(templateLayoutDoc, dataDoc) || !dataDoc) return templateLayoutDoc; + export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc) { + if (!WillExpandTemplateLayout(templateLayoutDoc, targetDoc) || !targetDoc) return templateLayoutDoc; const templateField = StrCast(templateLayoutDoc.isTemplateForField); // the field that the template renders // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc @@ -455,13 +455,15 @@ export namespace Doc { // saves it on the data doc indexed by the template layout's id. // const expandedLayoutFieldKey = templateField + "-layout[" + templateLayoutDoc[Id] + "]"; - const expandedTemplateLayout = dataDoc?.[expandedLayoutFieldKey]; + const expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey]; if (expandedTemplateLayout === undefined) { setTimeout(() => { - if (!dataDoc[expandedLayoutFieldKey]) { + if (!targetDoc[expandedLayoutFieldKey]) { const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]"); - dataDoc[expandedLayoutFieldKey] = newLayoutDoc; - newLayoutDoc.resolvedDataDoc = dataDoc; + newLayoutDoc.expandedTemplate = targetDoc; + targetDoc[expandedLayoutFieldKey] = newLayoutDoc; + const dataDoc = Doc.GetProto(targetDoc); + newLayoutDoc.resolvedDataDoc = targetDoc; if (dataDoc[templateField] === undefined && templateLayoutDoc[templateField] instanceof List && Cast(templateLayoutDoc[templateField], listSpec(Doc), []).length) { dataDoc[templateField] = ComputedField.MakeFunction(`ObjectField.MakeCopy(templateLayoutDoc["${templateField}"] as List)`, { templateLayoutDoc: Doc.name }, { templateLayoutDoc: templateLayoutDoc }); } @@ -474,7 +476,7 @@ export namespace Doc { // if the childDoc is a template for a field, then this will return the expanded layout with its data doc. // otherwise, it just returns the childDoc export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt, childDoc: Doc) { - const resolvedDataDoc = containerDataDoc === containerDoc || !containerDataDoc ? undefined : Doc.GetDataDoc(containerDataDoc); + const resolvedDataDoc = containerDataDoc === containerDoc || !containerDataDoc ? undefined : containerDataDoc; return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc }; } export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) { -- cgit v1.2.3-70-g09d2 From 1a25ad93d107755320b319db999a1489982e3597 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 1 Feb 2020 17:32:31 -0500 Subject: presenetation bug fixes --- src/client/views/nodes/PresBox.tsx | 2 +- src/client/views/presentationview/PresElementBox.scss | 10 ++++++++-- src/client/views/presentationview/PresElementBox.tsx | 14 ++++++++++---- 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index c661b7f4e..06d8e688b 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -333,7 +333,7 @@ export class PresBox extends React.Component { @action initializeScaleViews = (docList: Doc[], viewtype: number) => { this.props.Document._chromeStatus = "disabled"; - const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 42; + const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 46; docList.forEach((doc: Doc) => { doc.presBox = this.props.Document; doc.presBoxKey = this.props.fieldKey; diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index b74b07224..86ad8fed6 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -4,6 +4,7 @@ background-color: #eeeeee; pointer-events: all; width: 100%; + height: 100%; outline-color: maroon; outline-style: dashed; border-radius: 6px; @@ -17,7 +18,6 @@ padding: 0px; padding-left: 5px; padding-bottom: 3px; - .documentView-node { position: absolute; z-index: 1; @@ -82,7 +82,13 @@ .presElementBox-embedded { position: relative; - margin-top: 30; + margin-top: 22; + display: flex; + justify-content: center; + .contentFittingDocumentView { + position: absolute; + height: 100%; + } } .presElementBox-embeddedMask { diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index afc88833e..ab49fbf1e 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -174,13 +174,19 @@ export class PresElementBox extends DocExtendableComponent 175 / NumCast(this.layoutDoc._nativeWidth, 175); + const layoutDoc = Doc.Layout(this.props.Document); + if (!layoutDoc.embeddedView) { + layoutDoc.embeddedView = Doc.MakeAlias(this.originalLayout); + (layoutDoc.embeddedView as Doc).layoutKey = "layout"; + } + const embedHeight = propDocHeight === 0 ? this.props.PanelHeight() - NumCast(this.originalLayout.collapsedHeight) : propDocHeight * scale(); return (
this.props.PanelWidth() - 20} - PanelHeight={() => 100} + PanelHeight={() => embedHeight} getTransform={Transform.Identity} active={this.props.active} moveDocument={this.props.moveDocument!} - renderDepth={1} + renderDepth={this.props.renderDepth + 1} focus={emptyFunction} whenActiveChanged={returnFalse} /> -- cgit v1.2.3-70-g09d2 From d718a470402e56c4fbc4e5d84f5f5192b32eac88 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 1 Feb 2020 17:48:33 -0500 Subject: more presenetation cleanup --- .../views/presentationview/PresElementBox.scss | 1 + .../views/presentationview/PresElementBox.tsx | 34 ++++++---------------- 2 files changed, 10 insertions(+), 25 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index 86ad8fed6..fd9de90e0 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -84,6 +84,7 @@ position: relative; margin-top: 22; display: flex; + width: auto; justify-content: center; .contentFittingDocumentView { position: absolute; diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index ab49fbf1e..dcc5247d5 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -162,40 +162,25 @@ export class PresElementBox extends DocExtendableComponent [xCord, yCord]; + embedHeight = () => this.props.PanelHeight() - NumCast(this.originalLayout.collapsedHeight); + embedWidth = () => this.props.PanelWidth() - 20; /** * The function that is responsible for rendering the a preview or not for this * presentation element. */ renderEmbeddedInline = () => { - if (!this.originalLayout.embedOpen || !this.targetDoc) { - return (null); - } - - const propDocWidth = NumCast(this.layoutDoc._nativeWidth); - const propDocHeight = NumCast(this.layoutDoc._nativeHeight); - const scale = () => 175 / NumCast(this.layoutDoc._nativeWidth, 175); - const layoutDoc = Doc.Layout(this.props.Document); - if (!layoutDoc.embeddedView) { - layoutDoc.embeddedView = Doc.MakeAlias(this.originalLayout); - (layoutDoc.embeddedView as Doc).layoutKey = "layout"; - } - const embedHeight = propDocHeight === 0 ? this.props.PanelHeight() - NumCast(this.originalLayout.collapsedHeight) : propDocHeight * scale(); - return ( -
+ return !this.originalLayout.embedOpen || !this.targetDoc ? (null) : +
this.props.PanelWidth() - 20} - PanelHeight={() => embedHeight} + PanelWidth={this.embedWidth} + PanelHeight={this.embedHeight} getTransform={Transform.Identity} active={this.props.active} moveDocument={this.props.moveDocument!} @@ -204,8 +189,7 @@ export class PresElementBox extends DocExtendableComponent
-
- ); +
; } render() { -- cgit v1.2.3-70-g09d2 From feaed0e1fbfb505684c87996b020ee36b7e96224 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 1 Feb 2020 21:49:23 -0500 Subject: moved all of pivot view into TimeView. tweaked layout for pivot. better fix is straightforward. --- .../views/collections/CollectionPivotView.scss | 88 ----------- .../views/collections/CollectionPivotView.tsx | 174 --------------------- .../views/collections/CollectionTimeView.scss | 9 +- .../views/collections/CollectionTimeView.tsx | 38 ++++- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 7 +- .../views/collections/CollectionViewChromes.tsx | 34 +--- .../CollectionFreeFormLayoutEngines.tsx | 77 ++++----- .../views/presentationview/PresElementBox.scss | 2 +- 9 files changed, 80 insertions(+), 351 deletions(-) delete mode 100644 src/client/views/collections/CollectionPivotView.scss delete mode 100644 src/client/views/collections/CollectionPivotView.tsx (limited to 'src/client/views/presentationview') diff --git a/src/client/views/collections/CollectionPivotView.scss b/src/client/views/collections/CollectionPivotView.scss deleted file mode 100644 index 505091e98..000000000 --- a/src/client/views/collections/CollectionPivotView.scss +++ /dev/null @@ -1,88 +0,0 @@ -.collectionPivotView { - display: flex; - flex-direction: row; - position: absolute; - height: 100%; - width: 100%; - - .collectionPivotView-flyout { - width: 400px; - height: 300px; - display: inline-block; - - .collectionPivotView-flyout-item { - background-color: lightgray; - text-align: left; - display: inline-block; - position: relative; - width: 100%; - } - } - - .pivotKeyEntry { - position: absolute; - top: 5px; - right: 5px; - z-index: 10; - pointer-events: all; - padding: 5px; - border: 1px solid black; - } - - .collectionPivotView-treeView { - display: flex; - flex-direction: column; - width: 200px; - height: 100%; - - .collectionPivotView-addfacet { - display: inline-block; - width: 200px; - height: 30px; - background: darkGray; - text-align: center; - - .collectionPivotView-button { - align-items: center; - display: flex; - width: 100%; - height: 100%; - - .collectionPivotView-span { - margin: auto; - } - } - - >div, - >div>div { - width: 100%; - height: 100%; - text-align: center; - } - } - - .collectionPivotView-tree { - display: inline-block; - width: 100%; - height: calc(100% - 30px); - } - } - - .collectionPivotView-pivot { - display: inline-block; - width: calc(100% - 200px); - height: 100%; - } - - .collectionPivotView-dragger { - background-color: lightgray; - height: 40px; - width: 20px; - position: absolute; - border-radius: 10px; - top: 55%; - border: 1px black solid; - z-index: 2; - left: -10px; - } -} \ No newline at end of file diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx deleted file mode 100644 index 992018a3f..000000000 --- a/src/client/views/collections/CollectionPivotView.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import { faEdit } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, observable } from "mobx"; -import { observer } from "mobx-react"; -import { Set } from "typescript-collections"; -import { Doc, DocListCast } from "../../../new_fields/Doc"; -import { List } from "../../../new_fields/List"; -import { listSpec } from "../../../new_fields/Schema"; -import { ComputedField, ScriptField } from "../../../new_fields/ScriptField"; -import { Cast, StrCast } from "../../../new_fields/Types"; -import { Docs } from "../../documents/Documents"; -import { EditableView } from "../EditableView"; -import { anchorPoints, Flyout } from "../TemplateMenu"; -import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView"; -import "./CollectionPivotView.scss"; -import { CollectionSubView } from "./CollectionSubView"; -import { CollectionTreeView } from "./CollectionTreeView"; -import React = require("react"); -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; -import { RichTextField } from "../../../new_fields/RichTextField"; - -@observer -export class CollectionPivotView extends CollectionSubView(doc => doc) { - componentDidMount() { - this.props.Document._freeformLayoutEngine = "pivot"; - const childDetailed = this.props.Document.childDetailed; // bcz: needs to be here to make sure the childDetailed layout template has been loaded when the first item is clicked; - if (!this.props.Document._facetCollection) { - const facetCollection = Docs.Create.TreeDocument([], { title: "facetFilters", _yMargin: 0, treeViewHideTitle: true }); - facetCollection.target = this.props.Document; - this.props.Document.excludeFields = new List(["_facetCollection", "_docFilter"]); - - const scriptText = "setDocFilter(containingTreeView.target, heading, this.title, checked)"; - const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(containingCollection.childDetailed, alias, 'layout_detailed'); useRightSplit(alias); "; - facetCollection.onCheckedClick = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "boolean", checked: "boolean", containingTreeView: Doc.name }); - this.props.Document.onChildClick = ScriptField.MakeScript(childText, { this: Doc.name, heading: "boolean", containingCollection: Doc.name }); - this.props.Document._facetCollection = facetCollection; - this.props.Document._fitToBox = true; - } - } - bodyPanelWidth = () => this.props.PanelWidth() - this._facetWidth; - getTransform = () => this.props.ScreenToLocalTransform().translate(-this._facetWidth, 0); - - @computed get _allFacets() { - const facets = new Set(); - this.childDocs.forEach(child => Object.keys(Doc.GetProto(child)).forEach(key => facets.add(key))); - return facets.toArray(); - } - - /** - * Responds to clicking the check box in the flyout menu - */ - facetClick = (facetHeader: string) => { - const facetCollection = this.props.Document._facetCollection; - if (facetCollection instanceof Doc) { - const found = DocListCast(facetCollection.data).findIndex(doc => doc.title === facetHeader); - if (found !== -1) { - (facetCollection.data as List).splice(found, 1); - const docFilter = Cast(this.props.Document._docFilter, listSpec("string")); - if (docFilter) { - let index: number; - while ((index = docFilter.findIndex(item => item === facetHeader)) !== -1) { - docFilter.splice(index, 3); - } - } - } else { - const newFacet = Docs.Create.TreeDocument([], { title: facetHeader, treeViewOpen: true, isFacetFilter: true }); - const capturedVariables = { layoutDoc: this.props.Document, dataDoc: this.dataDoc }; - const params = { layoutDoc: Doc.name, dataDoc: Doc.name, }; - newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, params, capturedVariables); - Doc.AddDocToList(facetCollection, "data", newFacet); - } - } - } - _canClick = false; - _facetWidthOnDown = 0; - @observable _facetWidth = 200; - onPointerDown = (e: React.PointerEvent) => { - this._canClick = true; - this._facetWidthOnDown = e.screenX; - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointerup", this.onPointerUp); - e.stopPropagation(); - e.preventDefault(); - } - - - @action - onPointerMove = (e: PointerEvent) => { - this._facetWidth = Math.max(this.props.ScreenToLocalTransform().transformPoint(e.clientX, 0)[0], 0); - Math.abs(e.movementX) > 6 && (this._canClick = false); - } - @action - onPointerUp = (e: PointerEvent) => { - if (Math.abs(e.screenX - this._facetWidthOnDown) < 6 && this._canClick) { - this._facetWidth = this._facetWidth < 15 ? 200 : 0; - } - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - - menuCallback = (x: number, y: number) => { - ContextMenu.Instance.clearItems(); - const docItems: ContextMenuProps[] = []; - const keySet: Set = new Set(); - - this.childLayoutPairs.map(pair => - Array.from(Object.keys(Doc.GetProto(pair.layout))).filter(fieldKey => pair.layout[fieldKey] instanceof RichTextField || typeof (pair.layout[fieldKey]) === "string").map(fieldKey => - keySet.add(fieldKey))); - keySet.toArray().map(fieldKey => - docItems.push({ description: ":" + fieldKey, event: () => this.props.Document.pivotField = fieldKey, icon: "compress-arrows-alt" })); - docItems.push({ description: ":(null)", event: () => this.props.Document.pivotField = undefined, icon: "compress-arrows-alt" }) - ContextMenu.Instance.addItem({ description: "Pivot Fields ...", subitems: docItems, icon: "eye" }); - const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(x, y); - ContextMenu.Instance.displayMenu(x, y, ":"); - } - - @observable private collapsed: boolean = false; - private toggleVisibility = action(() => this.collapsed = !this.collapsed); - - render() { - const facetCollection = Cast(this.props.Document?._facetCollection, Doc, null); - const flyout = ( -
- {this._allFacets.map(facet => )} -
- ); - const newEditableViewProps = { - GetValue: () => "", - SetValue: (value: any) => { - if (value?.length) { - this.props.Document.pivotField = value; - return true; - } - return false; - }, - showMenuOnLoad: true, - contents: ":" + StrCast(this.props.Document.pivotField), - toggle: this.toggleVisibility, - color: "#f1efeb" // this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; - }; - return !facetCollection ? (null) : -
-
- -
-
- -
-
-
e.stopPropagation()}> - -
- Facet Filters - -
-
-
-
- -
-
-
- -
-
; - } -} \ No newline at end of file diff --git a/src/client/views/collections/CollectionTimeView.scss b/src/client/views/collections/CollectionTimeView.scss index 805d06d3d..3aac2bc75 100644 --- a/src/client/views/collections/CollectionTimeView.scss +++ b/src/client/views/collections/CollectionTimeView.scss @@ -1,4 +1,4 @@ -.collectionTimeView { +.collectionTimeView, .collectionTimeView-pivot { display: flex; flex-direction: row; position: absolute; @@ -93,7 +93,7 @@ } } - .collectionTimeView-pivot { + .collectionTimeView-innards { display: inline-block; width: calc(100% - 200px); height: 100%; @@ -110,4 +110,9 @@ z-index: 2; left: -10px; } +} +.collectionTimeView-pivot { + .collectionFreeform-customText { + text-align: center; + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index b4ab88f9a..253dfa890 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -107,8 +107,10 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { const keySet: Set = new Set(); this.childLayoutPairs.map(pair => - Array.from(Object.keys(Doc.GetProto(pair.layout))).filter(fieldKey => pair.layout[fieldKey] instanceof RichTextField || typeof (pair.layout[fieldKey]) === "number" || typeof (pair.layout[fieldKey]) === "string").map(fieldKey => - keySet.add(fieldKey))); + Array.from(Object.keys(Doc.GetProto(pair.layout))).filter(fieldKey => + pair.layout[fieldKey] instanceof RichTextField || + typeof (pair.layout[fieldKey]) === "number" || + typeof (pair.layout[fieldKey]) === "string").map(fieldKey => keySet.add(fieldKey))); keySet.toArray().map(fieldKey => docItems.push({ description: ":" + fieldKey, event: () => this.props.Document.pivotField = fieldKey, icon: "compress-arrows-alt" })); docItems.push({ description: ":(null)", event: () => this.props.Document.pivotField = undefined, icon: "compress-arrows-alt" }) @@ -189,11 +191,12 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { } @computed get contents() { - return
+ return
; } + _changing = false; render() { const facetCollection = Cast(this.props.Document?._facetCollection, Doc, null); const flyout = ( @@ -219,8 +222,33 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { toggle: this.toggleVisibility, color: "#f1efeb" // this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; }; + + let nonNumbers = 0; + this.childDocs.map(doc => { + const num = NumCast(doc[StrCast(this.props.Document.pivotField)], Number(StrCast(doc[StrCast(this.props.Document.pivotField)]))); + if (Number.isNaN(num)) { + nonNumbers++; + } + }); + const doTimeline = nonNumbers / this.childDocs.length < 0.1; + if (doTimeline !== (this.props.Document._freeformLayoutEngine === "timeline")) { + if (!this._changing) { + this._changing = true; + setTimeout(() => { + if (nonNumbers / this.childDocs.length > 0.1) { + this.childDocs.map(child => child.isMinimized = false); + this.props.Document._freeformLayoutEngine = "pivot"; + } else { + this.props.Document._freeformLayoutEngine = "timeline"; + } + this._changing = false; + }, 0); + } + return (null); + } + return !facetCollection ? (null) : -
+
@@ -243,7 +271,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
{this.contents} - {!this.props.isSelected() ? (null) : <> + {!this.props.isSelected() || !doTimeline ? (null) : <>
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 3cb24f079..631870866 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -659,7 +659,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { Document.childLayout = cardLayout; Document.childDetailed = detailedLayout; - Document._viewType = CollectionViewType.Pivot; + Document._viewType = CollectionViewType.Time; Document.pivotField = "company"; } }); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5a7bdef61..d5d62159b 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -29,7 +29,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV import { CollectionCarouselView } from './CollectionCarouselView'; import { CollectionLinearView } from './CollectionLinearView'; import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView'; -import { CollectionPivotView } from './CollectionPivotView'; import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionStackingView } from './CollectionStackingView'; import { CollectionStaffView } from './CollectionStaffView'; @@ -52,7 +51,6 @@ export enum CollectionViewType { Masonry, Multicolumn, Multirow, - Pivot, Time, Carousel, Linear, @@ -71,7 +69,6 @@ export namespace CollectionViewType { ["masonry", CollectionViewType.Masonry], ["multicolumn", CollectionViewType.Multicolumn], ["multirow", CollectionViewType.Multirow], - ["pivot", CollectionViewType.Pivot], ["time", CollectionViewType.Time], ["carousel", CollectionViewType.Carousel], ["linear", CollectionViewType.Linear], @@ -191,7 +188,6 @@ export class CollectionView extends Touchable { case CollectionViewType.Carousel: { return (); } case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } - case CollectionViewType.Pivot: { return (); } case CollectionViewType.Time: { return (); } case CollectionViewType.Freeform: default: { this.props.Document._freeformLayoutEngine = undefined; return (); } @@ -234,8 +230,7 @@ export class CollectionView extends Touchable { subItems.push({ description: "Multirow", event: () => this.props.Document._viewType = CollectionViewType.Multirow, icon: "columns" }); subItems.push({ description: "Masonry", event: () => this.props.Document._viewType = CollectionViewType.Masonry, icon: "columns" }); subItems.push({ description: "Carousel", event: () => this.props.Document._viewType = CollectionViewType.Carousel, icon: "columns" }); - subItems.push({ description: "Pivot", event: () => this.props.Document._viewType = CollectionViewType.Pivot, icon: "columns" }); - subItems.push({ description: "Time", event: () => this.props.Document._viewType = CollectionViewType.Time, icon: "columns" }); + subItems.push({ description: "Pivot/Time", event: () => this.props.Document._viewType = CollectionViewType.Time, icon: "columns" }); switch (this.props.Document._viewType) { case CollectionViewType.Freeform: { subItems.push({ description: "Custom", icon: "fingerprint", event: AddCustomFreeFormLayout(this.props.Document, this.props.fieldKey) }); diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index c5db6f10f..f00af52cf 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -70,7 +70,6 @@ export class CollectionViewBaseChrome extends React.Component { - if (StrCast(this.document._freeformLayoutEngine) !== "pivot") { - return (null); - } - return () => this.pivotKeyDisplay = e.currentTarget.value)} - onKeyPress={action((e: React.KeyboardEvent) => { - const value = e.currentTarget.value; - if (e.which === 13) { - this.pivotKey = value; - this.pivotKeyDisplay = ""; - } - })} />); - } - @action.bound clearFilter = () => { this.props.CollectionView.props.Document.viewSpecScript = ScriptField.MakeFunction("true", { doc: Doc.name }); @@ -419,10 +392,9 @@ export class CollectionViewBaseChrome extends React.ComponentMasonry - - - - + + +
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index d2a2b42a0..6f84346df 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -46,10 +46,14 @@ export function computePivotLayout( poolData: ObservableMap, pivotDoc: Doc, childDocs: Doc[], - childPairs: { layout: Doc, data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: any) => ViewDefResult[] + childPairs: { layout: Doc, data?: Doc }[], + panelDim: number[], + viewDefsToJSX: (views: any) => ViewDefResult[] ) { - const pivotAxisWidth = NumCast(pivotDoc.pivotWidth, 200); + const fieldKey = "data"; + const pivotAxisWidth = NumCast(pivotDoc.pivotWidth, 1000); const pivotColumnGroups = new Map, Doc[]>(); + const fontSize = NumCast(pivotDoc[fieldKey + "-timelineFontSize"], panelDim[1] > 58 ? 20 : Math.max(7, panelDim[1] / 3)); const pivotFieldKey = toLabel(pivotDoc.pivotField); for (const doc of childDocs) { @@ -69,16 +73,20 @@ export function computePivotLayout( const expander = 1.05; const gap = .15; let x = 0; + let max_text = 60; pivotColumnGroups.forEach((val, key) => { let y = 0; let xCount = 0; + const text = toLabel(key); + max_text = Math.max(max_text, Math.min(500, text.length)); groupNames.push({ type: "text", - text: toLabel(key), + text, x, y: pivotAxisWidth, width: pivotAxisWidth * expander * numCols, - fontSize: NumCast(pivotDoc.pivotFontSize, 20) + height: max_text, + fontSize }); for (const doc of val) { const layoutDoc = Doc.Layout(doc); @@ -103,37 +111,7 @@ export function computePivotLayout( x += pivotAxisWidth * (numCols * expander + gap); }); - const grpEles = groupNames.map(gn => { return { x: gn.x, y: gn.y, width: gn.width, height: undefined } as PivotData; }); - const docEles = childPairs.map(pair => - docMap.get(pair.layout) || { x: NumCast(pair.layout.x), y: NumCast(pair.layout.y), width: NumCast(pair.layout._width), height: NumCast(pair.layout._height) } // new pos is computed pos, or pos written to the document's fields - ); - const minLabelHeight = 56; - const aggBounds = aggregateBounds(docEles.concat(grpEles), 0, 0); - const wscale = panelDim[0] / (aggBounds.r - aggBounds.x); - const scale = wscale * (aggBounds.b - aggBounds.y) > panelDim[1] - (2 * minLabelHeight) ? (panelDim[1] - (2 * minLabelHeight)) / (aggBounds.b - aggBounds.y) : wscale; - const centerY = ((panelDim[1] - 2 * minLabelHeight) - (aggBounds.b - aggBounds.y) * scale) / 2; - const centerX = (panelDim[0] - (aggBounds.r - aggBounds.x) * scale) / 2; - - childPairs.map(pair => { - const fallbackPos = { - x: NumCast(pair.layout.x), - y: NumCast(pair.layout.y), - z: NumCast(pair.layout.z), - width: NumCast(pair.layout._width), - height: NumCast(pair.layout._height) - }; - const newPosRaw = docMap.get(pair.layout) || fallbackPos; // new pos is computed pos, or pos written to the document's fields - const newPos = { x: newPosRaw.x * scale + centerX, y: (newPosRaw.y - aggBounds.y) * scale + centerY, z: newPosRaw.z, width: (newPosRaw.width || 0) * scale, height: newPosRaw.height! * scale }; - const lastPos = poolData.get(pair.layout[Id]); // last computed pos - if (!lastPos || newPos.x !== lastPos.x || newPos.y !== lastPos.y || newPos.z !== lastPos.z || newPos.width !== lastPos.width || newPos.height !== lastPos.height) { - runInAction(() => poolData.set(pair.layout[Id], { transition: "transform 1s", ...newPos })); - } - }); - return { - elements: viewDefsToJSX([{ type: "text", text: "", x: 0, y: -aggBounds.y * scale - minLabelHeight, width: panelDim[0], height: panelDim[1], fontSize: 1 }].concat(groupNames.map(gname => { - return { type: gname.type, text: gname.text, x: gname.x * scale + centerX, y: (gname.y - aggBounds.y) * scale + centerY, width: (gname.width || 0) * scale, height: Math.max(minLabelHeight, centerY), fontSize: gname.fontSize }; - }))) - }; + return normalizeResults(panelDim, max_text, childPairs, docMap, poolData, viewDefsToJSX, groupNames, 0, []); } @@ -186,7 +164,7 @@ export function computeTimelineLayout( groupNames.push({ type: "text", text: prevKey.toString(), x: x, y: 0, height: fontHeight, fontSize }); } - const pivotAxisWidth = NumCast(pivotDoc.pivotWidth, panelDim[1] / 2.5); + const pivotAxisWidth = NumCast(pivotDoc.pivotTimeWidth, panelDim[1] / 2.5); let stacking: number[] = []; sortedKeys.forEach(key => { const keyDocs = pivotDateGroups.get(key)!; @@ -212,12 +190,19 @@ export function computeTimelineLayout( groupNames.push({ type: "text", text: Math.ceil(maxTime).toString(), x: Math.ceil(maxTime - minTime) * scaling, y: 0, height: fontHeight, fontSize }); } - const grpEles = groupNames.map(gn => { return { x: gn.x, y: gn.y, height: gn.height } as PivotData; }); + const divider = { type: "div", color: "black", x: 0, y: 0, width: panelDim[0], height: 1 } as any; + return normalizeResults(panelDim, fontHeight, childPairs, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider]); +} + +function normalizeResults(panelDim: number[], fontHeight: number, childPairs: { data?: Doc, layout: Doc }[], docMap: any, + poolData: any, viewDefsToJSX: any, groupNames: PivotData[], minWidth: number, extras: any[]) { + + const grpEles = groupNames.map(gn => ({ x: gn.x, y: gn.y, height: gn.height }) as PivotData); const docEles = childPairs.filter(d => !d.layout.isMinimized).map(pair => docMap.get(pair.layout) || { x: NumCast(pair.layout.x), y: NumCast(pair.layout.y), width: pair.layout[WidthSym](), height: pair.layout[HeightSym]() } as PivotData // new pos is computed pos, or pos written to the document's fields ); const aggBounds = aggregateBounds(docEles.concat(grpEles), 0, 0); - aggBounds.r = Math.max((maxTime - minTime) * scaling, aggBounds.r - aggBounds.x); + aggBounds.r = Math.max(minWidth, aggBounds.r - aggBounds.x); const wscale = panelDim[0] / (aggBounds.r - aggBounds.x); let scale = wscale * (aggBounds.b - aggBounds.y) > panelDim[1] ? (panelDim[1]) / (aggBounds.b - aggBounds.y) : wscale; if (Number.isNaN(scale)) scale = 1; @@ -237,12 +222,18 @@ export function computeTimelineLayout( runInAction(() => poolData.set(pair.layout[Id], { transition: "transform 1s", ...newPos })); } }); + return { - elements: viewDefsToJSX([ - { type: "div", color: "black", x: 0, y: 0, width: panelDim[0], height: 1 } as any - ].concat(groupNames.map(gname => { - return { type: gname.type, text: gname.text, x: gname.x * scale, y: gname.y * scale, width: gname.width === undefined ? gname.width : gname.width * scale, height: Math.max(fontHeight, gname.height! * scale), fontSize: gname.fontSize }; - }))) + elements: viewDefsToJSX(extras.concat(groupNames.map(gname => ({ + type: gname.type, + text: gname.text, + x: gname.x * scale, + y: gname.y * scale, + width: gname.width === undefined ? undefined : gname.width * scale, + height: Math.max(fontHeight, gname.height! * scale), + // height: gname.height === undefined ? undefined : gname.height * scale, + fontSize: gname.fontSize + })))) }; } diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index fd9de90e0..8370af490 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -71,7 +71,7 @@ } .presElementBox-name { - font-size: 12px; + font-size: 12pxππ; position: absolute; display: inline-block; width: calc(100% - 45px); -- cgit v1.2.3-70-g09d2 From da92903fb49b2c7d34bb44f11bf72a6cd49b8c0d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 4 Feb 2020 23:52:40 -0500 Subject: lots of small fixes to templates, presentations, default templates (icon, slide) --- src/client/views/MainView.tsx | 2 +- src/client/views/OverlayView.tsx | 2 +- .../views/collections/CollectionTimeView.tsx | 10 ++++---- .../CollectionMulticolumnView.scss | 1 + .../CollectionMulticolumnView.tsx | 13 ++++++---- .../CollectionMultirowView.scss | 1 + .../CollectionMultirowView.tsx | 12 ++++++---- src/client/views/nodes/DocumentView.tsx | 28 ++++++++++------------ src/client/views/nodes/PresBox.scss | 2 +- src/client/views/nodes/PresBox.tsx | 8 +++++-- .../views/presentationview/PresElementBox.tsx | 2 +- src/new_fields/Doc.ts | 16 +++++++++---- .../authentication/models/current_user_utils.ts | 20 +++++++++++++++- 13 files changed, 78 insertions(+), 39 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 87a81504c..0cc374cee 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,6 +1,6 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { - faArrowDown, faBullseye, faFilter, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faChevronRight, faClone, faCloudUploadAlt, faCommentAlt, faCut, faEllipsisV, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, + faStickyNote, faArrowDown, faBullseye, faFilter, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faChevronRight, faClone, faCloudUploadAlt, faCommentAlt, faCut, faEllipsisV, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faMousePointer, faPenNib, faFileAudio, faPen, faEraser, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faTv, faUndoAlt, faHighlighter, faMicrophone, faCompressArrowsAlt, faPhone, faStamp, faClipboard } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 295cd7c6e..7a99bf0ae 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -144,7 +144,7 @@ export class OverlayView extends React.Component { return (null); } return CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => { - d.inOverlay = true; + setTimeout(() => d.inOverlay = true, 0); let offsetx = 0, offsety = 0; const onPointerMove = action((e: PointerEvent) => { if (e.buttons === 1) { diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index f999067d3..264423d72 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -46,6 +46,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { @computed get _allFacets() { const facets = new Set(); this.childDocs.forEach(child => Object.keys(Doc.GetProto(child)).forEach(key => facets.add(key))); + Doc.AreProtosEqual(this.dataDoc, this.props.Document) && this.childDocs.forEach(child => Object.keys(child).forEach(key => facets.add(key))); return facets.toArray(); } @@ -108,11 +109,10 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { const docItems: ContextMenuProps[] = []; const keySet: Set = new Set(); - this.childLayoutPairs.map(pair => - Array.from(Object.keys(Doc.GetProto(pair.layout))).filter(fieldKey => - pair.layout[fieldKey] instanceof RichTextField || - typeof (pair.layout[fieldKey]) === "number" || - typeof (pair.layout[fieldKey]) === "string").map(fieldKey => keySet.add(fieldKey))); + this.childLayoutPairs.map(pair => this._allFacets.filter(fieldKey => + pair.layout[fieldKey] instanceof RichTextField || + typeof (pair.layout[fieldKey]) === "number" || + typeof (pair.layout[fieldKey]) === "string").map(fieldKey => keySet.add(fieldKey))); keySet.toArray().map(fieldKey => docItems.push({ description: ":" + fieldKey, event: () => this.props.Document.pivotField = fieldKey, icon: "compress-arrows-alt" })); docItems.push({ description: ":(null)", event: () => this.props.Document.pivotField = undefined, icon: "compress-arrows-alt" }) diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss index f57ba438a..a5d5617bc 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss @@ -7,6 +7,7 @@ .document-wrapper { display: flex; flex-direction: column; + width: 100%; .label-wrapper { display: flex; diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index cbe064ec0..56f777f43 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -224,10 +224,11 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu Document={layout} DataDocument={layout.resolvedDataDoc as Doc} CollectionDoc={this.props.Document} - PanelWidth={() => this.lookupPixels(layout)} - PanelHeight={() => PanelHeight() - (BoolCast(Document.showWidthLabels) ? 20 : 0)} - getTransform={() => this.lookupIndividualTransform(layout)} + PanelWidth={() => this.lookupPixels(layout) - 2 * NumCast(Document._xMargin)} + PanelHeight={() => PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0)} + getTransform={() => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin))} onClick={this.onChildClickHandler} + renderDepth={this.props.renderDepth + 1} /> +
{this.contents}
); diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.scss b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.scss index ef4b4a19c..ed737ea59 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.scss +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.scss @@ -8,6 +8,7 @@ .document-wrapper { display: flex; flex-direction: row; + height: 100%; .label-wrapper { display: flex; diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 434bf14ff..8a2498458 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -224,9 +224,9 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) Document={layout} DataDocument={layout.resolvedDataDoc as Doc} CollectionDoc={this.props.Document} - PanelHeight={() => this.lookupPixels(layout)} - PanelWidth={() => PanelWidth() - (BoolCast(Document.showHeightLabels) ? 20 : 0)} - getTransform={() => this.lookupIndividualTransform(layout)} + PanelHeight={() => this.lookupPixels(layout) - 2 * NumCast(Document._yMargin)} + PanelWidth={() => PanelWidth() - 2 * NumCast(Document._xMargin) - (BoolCast(Document.showHeightLabels) ? 20 : 0)} + getTransform={() => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin))} onClick={this.onChildClickHandler} renderDepth={this.props.renderDepth + 1} /> @@ -250,7 +250,11 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) render(): JSX.Element { return ( -
+
{this.contents}
); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d768dd7cf..c14d11cce 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -111,7 +111,7 @@ export class DocumentView extends DocComponent(Docu @computed get topMost() { return this.props.renderDepth === 0; } @computed get nativeWidth() { return this.layoutDoc._nativeWidth || 0; } @computed get nativeHeight() { return this.layoutDoc._nativeHeight || 0; } - @computed get onClickHandler() { return this.props.onClick ? this.props.onClick : this.Document.onClick; } + @computed get onClickHandler() { return this.props.onClick || this.layoutDoc.onClick || this.Document.onClick; } @computed get onPointerDownHandler() { return this.props.onPointerDown ? this.props.onPointerDown : this.Document.onPointerDown; } @computed get onPointerUpHandler() { return this.props.onPointerUp ? this.props.onPointerUp : this.Document.onPointerUp; } @@ -520,11 +520,8 @@ export class DocumentView extends DocComponent(Docu @undoBatch deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument && this.props.removeDocument(this.props.Document); } - static makeNativeViewClicked = (doc: Doc, prevLayout: string) => { - undoBatch(() => { - if (StrCast(doc.title).endsWith("_" + prevLayout)) doc.title = StrCast(doc.title).replace("_" + prevLayout, ""); - doc.layoutKey = "layout"; - })(); + static makeNativeViewClicked = (doc: Doc) => { + undoBatch(() => Doc.setNativeView(doc))(); } static makeCustomViewClicked = (doc: Doc, dataDoc: Opt, creator: (documents: Array, options: DocumentOptions, id?: string) => Doc, name: string = "custom", docLayoutTemplate?: Doc) => { @@ -653,21 +650,22 @@ export class DocumentView extends DocComponent(Docu @action setCustomView = (custom: boolean, layout: string): void => { - if (this.props.ContainingCollectionView?.props.DataDoc || this.props.ContainingCollectionView?.props.Document.isTemplateDoc) { - Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.Document); - } else if (custom) { - DocumentView.makeNativeViewClicked(this.props.Document, StrCast(this.props.Document.layoutKey).split("_")[1]); - - let foundLayout: Opt = undefined; - DocListCast(Cast(CurrentUserUtils.UserDocument.expandingButtons, Doc, null)?.data)?.map(btnDoc => { + // if (this.props.ContainingCollectionView?.props.DataDoc || this.props.ContainingCollectionView?.props.Document.isTemplateDoc) { + // Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.Document); + // } else + if (custom) { + DocumentView.makeNativeViewClicked(this.props.Document); + + let foundLayout: Opt = Cast(Doc.UserDoc().iconView, Doc, null); + !foundLayout && DocListCast(Cast(CurrentUserUtils.UserDocument.expandingButtons, Doc, null)?.data)?.map(btnDoc => { if (StrCast(Cast(btnDoc?.dragFactory, Doc, null)?.title) === layout) { foundLayout = btnDoc.dragFactory as Doc; } }) DocumentView. - makeCustomViewClicked(this.props.Document, this.props.DataDoc, Docs.Create.StackingDocument, layout, foundLayout && Doc.MakeDelegate(foundLayout)); + makeCustomViewClicked(this.props.Document, this.props.DataDoc, Docs.Create.StackingDocument, layout, foundLayout); } else { - DocumentView.makeNativeViewClicked(this.props.Document, StrCast(this.props.Document.layoutKey).split("_")[1]); + DocumentView.makeNativeViewClicked(this.props.Document); } } diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 01e7f4834..3e1967a18 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -6,7 +6,7 @@ top: 0; bottom: 0; width: 100%; - min-width: 100px; + min-width: 120px; height: 100%; min-height: 50px; letter-spacing: 2px; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 06d8e688b..44411fa30 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -6,7 +6,6 @@ import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { listSpec } from "../../../new_fields/Schema"; -import { ComputedField } from "../../../new_fields/ScriptField"; import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { Docs } from "../../documents/Documents"; @@ -17,7 +16,6 @@ import { CollectionView, CollectionViewType } from "../collections/CollectionVie import { ContextMenu } from "../ContextMenu"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; -import { presSchema } from "../presentationview/PresElementBox"; library.add(faArrowLeft); library.add(faArrowRight); @@ -31,6 +29,7 @@ library.add(faEdit); @observer export class PresBox extends React.Component { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } + _childReaction: IReactionDisposer | undefined; componentDidMount() { const userDoc = CurrentUserUtils.UserDocument; let presTemp = Cast(userDoc.presentationTemplate, Doc); @@ -43,6 +42,11 @@ export class PresBox extends React.Component { else { this.props.Document.childLayout = presTemp; } + this._childReaction = reaction(() => this.childDocs.slice(), + (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); + } + componentWillUnmount() { + this._childReaction?.(); } @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index dcc5247d5..ea3acf75c 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -50,7 +50,7 @@ export class PresElementBox extends DocExtendableComponent d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc)); (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateField.data)); } - if (templateField.data instanceof RichTextField && templateField.data.Text) { + if (templateField.data instanceof RichTextField && (templateField.data.Text || templateField.data.Data.toString().includes("dashField"))) { templateField._textTemplate = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name }); } @@ -780,6 +781,12 @@ export namespace Doc { const fieldStr = Field.toString(fieldVal as Field); return fieldStr === value; } + + export function setNativeView(doc: any) { + const prevLayout = StrCast(doc.layoutKey).split("_")[1]; + if (StrCast(doc.title).endsWith("_" + prevLayout)) doc.title = StrCast(doc.title).replace("_" + prevLayout, ""); + doc.layoutKey = "layout"; + } } Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; }); @@ -792,6 +799,7 @@ Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy Scripting.addGlobal(function aliasDocs(field: any) { return new List(field.map((d: any) => Doc.MakeAlias(d))); }); Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2); }); +Scripting.addGlobal(function setNativeView(doc: any) { Doc.setNativeView(doc); }); Scripting.addGlobal(function undo() { return UndoManager.Undo(); }); Scripting.addGlobal(function redo() { return UndoManager.Redo(); }); Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); }); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 6bfc729de..f2c3aab35 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -15,6 +15,8 @@ import { nullAudio } from "../../../new_fields/URLField"; import { DragManager } from "../../../client/util/DragManager"; import { InkingControl } from "../../../client/views/InkingControl"; import { CollectionViewType } from "../../../client/views/collections/CollectionView"; +import { makeTemplate } from "../../../client/util/DropConverter"; +import { RichTextField } from "../../../new_fields/RichTextField"; export class CurrentUserUtils { private static curr_id: string; @@ -227,14 +229,30 @@ export class CurrentUserUtils { /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupExpandingButtons(doc: Doc) { + const slideTemplate = Docs.Create.StackingDocument( + [ + Docs.Create.MulticolumnDocument([], { title: "images", _height: 200, _xMargin: 10, _yMargin: 10 }), + Docs.Create.TextDocument("", { title: "contents", _height: 100 }) + ], + { _width: 400, _height: 300, title: "slide", _chromeStatus: "disabled", _autoHeight: true }); + slideTemplate.isTemplateDoc = makeTemplate(slideTemplate); + + const iconDoc = Docs.Create.TextDocument("", { title: "icon", _width: 150, _height: 30, onClick: ScriptField.MakeScript("setNativeView(this)") }); + Doc.GetProto(iconDoc).data = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', ""); + doc.isTemplateDoc = makeTemplate(iconDoc); + doc.iconView = iconDoc; + doc.undoBtn = Docs.Create.FontIconDocument( { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onClick: ScriptField.MakeScript("undo()"), removeDropProperties: new List(["dropAction"]), title: "undo button", icon: "undo-alt" }); doc.redoBtn = Docs.Create.FontIconDocument( { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onClick: ScriptField.MakeScript("redo()"), removeDropProperties: new List(["dropAction"]), title: "redo button", icon: "redo-alt" }); + doc.slidesBtn = Docs.Create.FontIconDocument( + { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: slideTemplate, removeDropProperties: new List(["dropAction"]), title: "slide button", icon: "sticky-note" }); - doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc], { + doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc, doc.slidesBtn as Doc], { title: "expanding buttons", _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", backgroundColor: "black", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, + dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }) }); } -- cgit v1.2.3-70-g09d2 From 829872a08cd70675990b96d7388e886d57283c27 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 5 Feb 2020 23:29:46 -0500 Subject: added additional view modes for presenations --- .../views/collections/CollectionCarouselView.tsx | 3 - .../CollectionFreeFormLayoutEngines.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 22 ++---- src/client/views/nodes/PresBox.scss | 17 +++- src/client/views/nodes/PresBox.tsx | 90 +++++++++++++++------- .../views/presentationview/PresElementBox.tsx | 2 +- 6 files changed, 82 insertions(+), 56 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index e30d08592..00edf71dd 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -13,9 +13,6 @@ import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons'; import { Doc } from '../../../new_fields/Doc'; import { FormattedTextBox } from '../nodes/FormattedTextBox'; - - - type CarouselDocument = makeInterface<[typeof documentSchema,]>; const CarouselDocument = makeInterface(documentSchema); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index cee8f159e..84acbe0f0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -108,7 +108,7 @@ export function computePivotLayout( const fontSize = NumCast(pivotDoc[fieldKey + "-timelineFontSize"], panelDim[1] > 58 ? 20 : Math.max(7, panelDim[1] / 3)); const desc = `${fontSize}px ${getComputedStyle(document.body).fontFamily}`; const textlen = Array.from(pivotColumnGroups.keys()).map(c => getTextWidth(toLabel(c), desc)).reduce((p, c) => Math.max(p, c), 0 as number); - const max_text = Math.min(Math.ceil(textlen / 120) * 28, panelDim[1]/2); + const max_text = Math.min(Math.ceil(textlen / 120) * 28, panelDim[1] / 2); let maxInColumn = Array.from(pivotColumnGroups.values()).reduce((p, s) => Math.max(p, s.length), 1); const colWidth = panelDim[0] / pivotColumnGroups.size; @@ -171,7 +171,7 @@ export function computePivotLayout( x += pivotAxisWidth * (numCols * expander + gap); }); - const maxColHeight = pivotAxisWidth * Math.ceil(maxInColumn / numCols) + pivotAxisWidth; + const maxColHeight = pivotAxisWidth * expander * Math.ceil(maxInColumn / numCols); const dividers = Array.from(pivotColumnGroups.values()).map((pg, i) => ({ type: "div", color: "lightGray", x: i * pivotAxisWidth * (numCols * expander + gap), y: -maxColHeight + pivotAxisWidth, width: pivotAxisWidth * numCols * expander, height: maxColHeight } as any)); groupNames.push(...dividers); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 189c06288..06e9209d3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -467,10 +467,10 @@ export class DocumentView extends DocComponent(Docu this._hitTemplateDrag = true; } } - if ((this.active || this.Document.onDragStart || this.onClickHandler) && - !e.ctrlKey && - (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) && - !this.Document.lockedPosition && + if ((this.active || this.Document.onDragStart || this.onClickHandler) && + !e.ctrlKey && + (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) && + !this.Document.lockedPosition && !this.Document.inOverlay) { e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); } @@ -616,18 +616,6 @@ export class DocumentView extends DocComponent(Docu } } - @action - onDrop = (e: React.DragEvent) => { - const text = e.dataTransfer.getData("text/plain"); - if (!e.isDefaultPrevented() && text && text.startsWith(" { @@ -981,7 +969,7 @@ export class DocumentView extends DocComponent(Docu 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
Doc.BrushDoc(this.props.Document)} onPointerLeave={e => Doc.UnBrushDoc(this.props.Document)} style={{ transition: this.Document.isAnimating ? ".5s linear" : StrCast(this.Document.transition), diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 3e1967a18..7618aa7e3 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -14,10 +14,6 @@ transition: 0.7s opacity ease; pointer-events: all; - .presBox-listCont { - position: relative; - } - .presBox-buttons { padding: 10px; width: 100%; @@ -28,4 +24,17 @@ border-radius: 5px; } } + .presBox-backward, .presBox-forward { + width: 25px; + border-radius: 5px; + top:50%; + position: absolute; + display: inline-block; + } + .presBox-backward { + left:5; + } + .presBox-forward { + right:5; + } } \ No newline at end of file diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 2b195855c..44405c413 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -2,7 +2,7 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, reaction } from "mobx"; +import { action, computed, IReactionDisposer, reaction, observable } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { listSpec } from "../../../new_fields/Schema"; @@ -16,6 +16,10 @@ import { CollectionView, CollectionViewType } from "../collections/CollectionVie import { ContextMenu } from "../ContextMenu"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; +import { CollectionCarouselView } from "../collections/CollectionCarouselView"; +import { returnFalse } from "../../../Utils"; +import { ContextMenuProps } from "../ContextMenuItem"; +import { CollectionTimeView } from "../collections/CollectionTimeView"; library.add(faArrowLeft); library.add(faArrowRight); @@ -30,18 +34,26 @@ library.add(faEdit); export class PresBox extends React.Component { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } _childReaction: IReactionDisposer | undefined; + _slideshowReaction: IReactionDisposer | undefined; componentDidMount() { const userDoc = CurrentUserUtils.UserDocument; - let presTemp = Cast(userDoc.presentationTemplate, Doc); - if (presTemp instanceof Promise) { - presTemp.then(presTemp => this.props.Document.childLayout = presTemp); - } - else if (presTemp === undefined) { - presTemp = userDoc.presentationTemplate = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5, isTemplateDoc: true, isTemplateForField: "data" }); - } - else { - this.props.Document.childLayout = presTemp; - } + this._slideshowReaction = reaction(() => this.props.Document._slideshow, + (slideshow) => { + if (!slideshow) { + let presTemp = Cast(userDoc.presentationTemplate, Doc); + if (presTemp instanceof Promise) { + presTemp.then(presTemp => this.props.Document.childLayout = presTemp); + } + else if (presTemp === undefined) { + presTemp = userDoc.presentationTemplate = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5, isTemplateDoc: true, isTemplateForField: "data" }); + } + else { + this.props.Document.childLayout = presTemp; + } + } else { + this.props.Document.childLayout = undefined; + } + }, { fireImmediately: true }); this._childReaction = reaction(() => this.childDocs.slice(), (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); } @@ -52,7 +64,7 @@ export class PresBox extends React.Component { @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } next = async () => { - const current = NumCast(this.props.Document.selectedDoc); + const current = NumCast(this.props.Document._itemIndex); //asking to get document at current index const docAtCurrentNext = await this.getDocAtIndex(current + 1); if (docAtCurrentNext !== undefined) { @@ -69,7 +81,7 @@ export class PresBox extends React.Component { } } back = async () => { - const current = NumCast(this.props.Document.selectedDoc); + const current = NumCast(this.props.Document._itemIndex); //requesting for the doc at current index const docAtCurrent = await this.getDocAtIndex(current); if (docAtCurrent !== undefined) { @@ -222,7 +234,7 @@ export class PresBox extends React.Component { getDocAtIndex = async (index: number) => { const list = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); if (list && index >= 0 && index < list.length) { - this.props.Document.selectedDoc = index; + this.props.Document._itemIndex = index; //awaiting async call to finish to get Doc instance return list[index]; } @@ -250,7 +262,7 @@ export class PresBox extends React.Component { Doc.UnBrushAllDocs(); const list = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); if (list && index >= 0 && index < list.length) { - this.props.Document.selectedDoc = index; + this.props.Document._itemIndex = index; if (!this.props.Document.presStatus) { this.props.Document.presStatus = true; @@ -274,7 +286,7 @@ export class PresBox extends React.Component { } else { this.props.Document.presStatus = true; this.startPresentation(0); - this.gotoDocument(0, NumCast(this.props.Document.selectedDoc)); + this.gotoDocument(0, NumCast(this.props.Document._itemIndex)); } } @@ -293,7 +305,7 @@ export class PresBox extends React.Component { doc.opacity = 1; doc.viewScale = 1; }); - this.props.Document.selectedDoc = 0; + this.props.Document._itemIndex = 0; this.props.Document.presStatus = false; if (this.childDocs.length !== 0) { DocumentManager.Instance.zoomIntoScale(this.childDocs[0], 1); @@ -330,7 +342,12 @@ export class PresBox extends React.Component { })); specificContextMenu = (e: React.MouseEvent): void => { - ContextMenu.Instance.addItem({ description: "Make Current Presentation", event: action(() => Doc.UserDoc().curPresentation = this.props.Document), icon: "asterisk" }); + const funcs: ContextMenuProps[] = []; + funcs.push({ description: "Make Current Presentation", event: action(() => Doc.UserDoc().curPresentation = this.props.Document), icon: "asterisk" }); + funcs.push({ description: "Make slideshow", event: action(() => this.props.Document._slideshow = "slideshow"), icon: "asterisk" }); + funcs.push({ description: "Make timeline", event: action(() => this.props.Document._slideshow = "timeline"), icon: "asterisk" }); + funcs.push({ description: "Make list", event: action(() => this.props.Document._slideshow = "list"), icon: "asterisk" }); + ContextMenu.Instance.addItem({ description: "Presentatoin Funcs...", subitems: funcs, icon: "asterisk" }); } /** @@ -353,19 +370,37 @@ export class PresBox extends React.Component { }); } - selectElement = (doc: Doc) => { const index = DocListCast(this.props.Document[this.props.fieldKey]).indexOf(doc); - index !== -1 && this.gotoDocument(index, NumCast(this.props.Document.selectedDoc)); + index !== -1 && this.gotoDocument(index, NumCast(this.props.Document._itemIndex)); } getTransform = () => { return this.props.ScreenToLocalTransform().translate(0, -50);// listBox padding-left and pres-box-cont minHeight } + panelHeight = () => { + return this.props.PanelHeight() - 20; + } render() { this.initializeScaleViews(this.childDocs, NumCast(this.props.Document._viewType)); - return ( + return (this.props.Document._slideshow ?
+ {this.props.Document.inOverlay ? (null) : +
+ {this.props.Document._slideshow === "slideshow" ? + + : + + } +
} + + +
+ :
-
- {this.props.Document.inOverlay ? (null) : -
- -
- } -
- ); + {this.props.Document.inOverlay ? (null) : +
+ +
} +
); } } \ No newline at end of file diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index ea3acf75c..52773d466 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -54,7 +54,7 @@ export class PresElementBox extends DocExtendableComponent [this.originalLayout.embedOpen, this.originalLayout.collapsedHeight], -- cgit v1.2.3-70-g09d2 From be02a5529f472507512a127cd8de5cde300eff88 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 11 Feb 2020 14:19:56 -0500 Subject: added ability to pass a Layout as a prop. changed presentations to use layout props. fixed creating a template for just an empty collection representing one field. --- src/client/util/DropConverter.ts | 7 +- src/client/views/DocComponent.tsx | 5 +- .../views/collections/CollectionStackingView.tsx | 20 +++-- .../CollectionFreeFormLayoutEngines.tsx | 9 ++- .../views/nodes/ContentFittingDocumentView.tsx | 6 +- src/client/views/nodes/DocumentContentsView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 3 +- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/PresBox.tsx | 28 +------ .../views/presentationview/PresElementBox.tsx | 90 +++++++++++----------- src/new_fields/Doc.ts | 7 +- .../authentication/models/current_user_utils.ts | 5 +- 12 files changed, 94 insertions(+), 91 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index d0f1d86cb..3c7caa60b 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -8,7 +8,7 @@ import { ScriptField, ComputedField } from "../../new_fields/ScriptField"; import { RichTextField } from "../../new_fields/RichTextField"; import { ImageField } from "../../new_fields/URLField"; -export function makeTemplate(doc: Doc): boolean { +export function makeTemplate(doc: Doc, first: boolean = true): boolean { const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; const layout = StrCast(layoutDoc.layout).match(/fieldKey={'[^']*'}/)![0]; const fieldKey = layout.replace("fieldKey={'", "").replace(/'}$/, ""); @@ -18,9 +18,12 @@ export function makeTemplate(doc: Doc): boolean { if (!StrCast(d.title).startsWith("-")) { any = Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)) || any; } else if (d.type === DocumentType.COL || d.data instanceof RichTextField) { - any = makeTemplate(d) || any; + any = makeTemplate(d, false) || any; } }); + if (!docs.length && first) { + any = Doc.MakeMetadataFieldTemplate(doc, Doc.GetProto(layoutDoc)) || any; + } if (layoutDoc[fieldKey] instanceof RichTextField || layoutDoc[fieldKey] instanceof ImageField) { if (!StrCast(layoutDoc.title).startsWith("-")) { any = Doc.MakeMetadataFieldTemplate(layoutDoc, Doc.GetProto(layoutDoc)); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index ce48e1215..0bf944f22 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,4 +1,4 @@ -import { Doc } from '../../new_fields/Doc'; +import { Doc, Opt } from '../../new_fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; import { Cast } from '../../new_fields/Types'; @@ -11,12 +11,13 @@ import { PositionDocument } from '../../new_fields/documentSchemas'; /// DocComponent returns a generic React base class used by views that don't have any data extensions (e.g.,CollectionFreeFormDocumentView, DocumentView, ButtonBox) interface DocComponentProps { Document: Doc; + LayoutDoc?: () => Opt; } export function DocComponent

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

{ //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed get Document(): T { return schemaCtor(this.props.Document); } - @computed get layoutDoc() { return PositionDocument(Doc.Layout(this.props.Document)); } + @computed get layoutDoc() { return PositionDocument(Doc.Layout(this.props.Document, this.props.LayoutDoc?.())); } } return Component; } diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 21c34d047..d21ae32bc 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -55,7 +55,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { this._docXfs.length = 0; return docs.map((d, i) => { const height = () => this.getDocHeight(d); - const width = () => Math.min(d._nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); + const width = () => this.getDocWidth(d); const dref = React.createRef(); const dxf = () => this.getDocTransform(d, dref.current!); this._docXfs.push({ dxf: dxf, width: width, height: height }); @@ -154,11 +154,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get onClickHandler() { return ScriptCast(this.Document.onChildClick); } getDisplayDoc(doc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) { - const layoutDoc = Doc.Layout(doc); + const layoutDoc = Doc.Layout(doc, this.props.childLayoutTemplate?.()); const height = () => this.getDocHeight(doc); return doc) { pinToPres={this.props.pinToPres}> ; } + + getDocWidth(d?: Doc) { + if (!d) return 0; + const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); + const nw = NumCast(layoutDoc._nativeWidth); + return Math.min(nw && !d.ignoreAspect && !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); + let 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); if (!layoutDoc.ignoreAspect && !layoutDoc._fitWidth && nw && nh) { const aspect = nw && nh ? nh / nw : 1; - if (!(d._nativeWidth && !layoutDoc.ignoreAspect && this.props.Document.fillColumn)) wid = Math.min(layoutDoc[WidthSym](), wid); + if (!(!layoutDoc.ignoreAspect && this.props.Document.fillColumn)) wid = Math.min(layoutDoc[WidthSym](), wid); return wid * aspect; } - return layoutDoc._fitWidth ? !layoutDoc._nativeHeight ? this.props.PanelHeight() - 2 * this.yMargin : - Math.min(wid * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth, 1), this.props.PanelHeight() - 2 * this.yMargin) : layoutDoc[HeightSym](); + return layoutDoc._fitWidth ? !nh ? this.props.PanelHeight() - 2 * this.yMargin : + Math.min(wid * NumCast(layoutDoc.scrollHeight, nh) / (nw || 1), this.props.PanelHeight() - 2 * this.yMargin) : layoutDoc[HeightSym](); } columnDividerDown = (e: React.PointerEvent) => { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index b86cbbdbd..050ca8347 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -43,6 +43,9 @@ export interface ViewDefResult { bounds?: ViewDefBounds; } function toLabel(target: FieldResult) { + if (typeof target === "number" || Number(target)) { + return Number(target).toFixed(2).toString(); + } if (target instanceof ObjectField || target instanceof RefField) { return target[ToString](); } @@ -254,10 +257,10 @@ export function computeTimelineLayout( let prevKey = Math.floor(minTime); if (sortedKeys.length && scaling * (sortedKeys[0] - prevKey) > 25) { - groupNames.push({ type: "text", text: prevKey.toString(), x: x, y: 0, height: fontHeight, fontSize, payload: undefined }); + groupNames.push({ type: "text", text: toLabel(prevKey), x: x, y: 0, height: fontHeight, fontSize, payload: undefined }); } if (!sortedKeys.length && curTime !== undefined) { - groupNames.push({ type: "text", text: curTime.toString(), x: (curTime - minTime) * scaling, zIndex: 1000, color: "orange", y: 0, height: fontHeight, fontSize, payload: undefined }); + groupNames.push({ type: "text", text: toLabel(curTime), x: (curTime - minTime) * scaling, zIndex: 1000, color: "orange", y: 0, height: fontHeight, fontSize, payload: undefined }); } const pivotAxisWidth = NumCast(pivotDoc.pivotTimeWidth, panelDim[1] / 2.5); @@ -265,7 +268,7 @@ export function computeTimelineLayout( let zind = 0; sortedKeys.forEach(key => { if (curTime !== undefined && curTime > prevKey && curTime <= key) { - groupNames.push({ type: "text", text: curTime.toString(), x: (curTime - minTime) * scaling, y: 0, zIndex: 1000, color: "orange", height: fontHeight, fontSize, payload: key }); + groupNames.push({ type: "text", text: toLabel(curTime), x: (curTime - minTime) * scaling, y: 0, zIndex: 1000, color: "orange", height: fontHeight, fontSize, payload: key }); } const keyDocs = pivotDateGroups.get(key)!; x += scaling * (key - prevKey); diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index bd1b6166f..671f5b96e 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -2,7 +2,7 @@ import React = require("react"); import { action, computed } from "mobx"; import { observer } from "mobx-react"; import "react-table/react-table.css"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, Opt } from "../../../new_fields/Doc"; import { ComputedField, ScriptField } from "../../../new_fields/ScriptField"; import { NumCast, StrCast } from "../../../new_fields/Types"; import { emptyFunction, returnEmptyString, returnOne } from "../../../Utils"; @@ -18,6 +18,7 @@ import { TraceMobx } from "../../../new_fields/util"; interface ContentFittingDocumentViewProps { Document?: Doc; DataDocument?: Doc; + LayoutDoc?: () => Opt; LibraryPath: Doc[]; childDocs?: Doc[]; renderDepth: number; @@ -42,7 +43,7 @@ interface ContentFittingDocumentViewProps { @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.Document && Doc.Layout(this.props.Document); } + private get layoutDoc() { return this.props.Document && (this.props.LayoutDoc?.() || Doc.Layout(this.props.Document)); } private get nativeWidth() { return NumCast(this.layoutDoc?._nativeWidth, this.props.PanelWidth()); } private get nativeHeight() { return NumCast(this.layoutDoc?._nativeHeight, this.props.PanelHeight()); } @computed get scaling() { @@ -97,6 +98,7 @@ export class ContentFittingDocumentView extends React.Component; Document: Doc; DataDoc?: Doc; + LayoutDoc?: () => Opt; LibraryPath: Doc[]; fitToBox?: boolean; onClick?: ScriptField; @@ -834,6 +834,7 @@ export class DocumentView extends DocComponent(Docu ContainingCollectionDoc={this.props.ContainingCollectionDoc} Document={this.props.Document} DataDoc={this.props.DataDoc} + LayoutDoc={this.props.LayoutDoc} fitToBox={this.props.fitToBox} LibraryPath={this.props.LibraryPath} addDocument={this.props.addDocument} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 7544a5b77..8250f41f3 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -43,6 +43,7 @@ export interface FieldViewProps { setVideoBox?: (player: VideoBox) => void; ContentScaling: () => number; ChromeHeight?: () => number; + childLayoutTemplate?: () => Opt; } @observer diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 85017d3d4..d4a47c159 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -20,6 +20,7 @@ import { ContextMenuProps } from "../ContextMenuItem"; import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; +import { PrefetchProxy } from "../../../new_fields/Proxy"; library.add(faArrowLeft); library.add(faArrowRight); @@ -34,35 +35,14 @@ library.add(faEdit); export class PresBox extends React.Component { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } _childReaction: IReactionDisposer | undefined; - _slideshowReaction: IReactionDisposer | undefined; @observable _isChildActive = false; - componentDidMount() { - const userDoc = CurrentUserUtils.UserDocument; this.props.Document._forceRenderEngine = "timeline"; this.props.Document._replacedChrome = "replaced"; - this._slideshowReaction = reaction(() => this.props.Document._viewType, - (slideshow) => { - if (slideshow === CollectionViewType.Stacking || slideshow === undefined) { - let presTemp = Cast(userDoc.presentationTemplate, Doc); - if (presTemp instanceof Promise) { - presTemp.then(presTemp => this.props.Document.childLayout = presTemp); - } - else if (presTemp === undefined) { - presTemp = userDoc.presentationTemplate = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5, isTemplateDoc: true, isTemplateForField: "data" }); - } - else { - this.props.Document.childLayout = presTemp; - } - } else { - this.props.Document.childLayout = undefined; - } - }, { fireImmediately: true }); this._childReaction = reaction(() => this.childDocs.slice(), (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); } componentWillUnmount() { this._childReaction?.(); - this._slideshowReaction?.(); } @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } @@ -376,7 +356,6 @@ export class PresBox extends React.Component { doc.presBox = this.props.Document; doc.presBoxKey = this.props.fieldKey; doc.collapsedHeight = hgt; - doc._nativeWidth = doc._nativeHeight = undefined; const curScale = NumCast(doc.viewScale, null); if (curScale === undefined) { doc.viewScale = 1; @@ -402,6 +381,8 @@ export class PresBox extends React.Component { this.props.Document._viewType = Number(e.target.selectedOptions[0].value); this.updateMinimize(e, Number(this.props.Document._viewType)); }); + + childLayoutTemplate = () => this.props.Document._viewType === CollectionViewType.Stacking ? Cast(Doc.UserDoc().presentationTemplate, Doc, null) : undefined; render() { const mode = NumCast(this.props.Document._viewType, CollectionViewType.Invalid); this.initializeScaleViews(this.childDocs, mode); @@ -425,8 +406,7 @@ export class PresBox extends React.Component {

{mode !== CollectionViewType.Invalid ? - : (null) } diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 52773d466..888707ee3 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -2,19 +2,18 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons'; import { faArrowDown, faArrowUp, faFile as fileSolid, faFileDownload, faLocationArrow, faSearch } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, reaction, IReactionDisposer } from "mobx"; +import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Doc } 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, StrCast } from "../../../new_fields/Types"; -import { emptyFunction, returnFalse, emptyPath } from "../../../Utils"; -import { DocumentType } from "../../documents/DocumentTypes"; +import { Cast, NumCast } from "../../../new_fields/Types"; +import { emptyFunction, emptyPath, returnFalse } from "../../../Utils"; import { Transform } from "../../util/Transform"; import { CollectionViewType } from '../collections/CollectionView'; +import { DocExtendableComponent } from '../DocComponent'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; -import { DocComponent, DocExtendableComponent } from '../DocComponent'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./PresElementBox.scss"; import React = require("react"); @@ -50,15 +49,16 @@ export class PresElementBox extends DocExtendableComponent [this.originalLayout.embedOpen, this.originalLayout.collapsedHeight], - params => this.originalLayout._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true }); + this._heightDisposer = reaction(() => [this.presElementDoc.embedOpen, this.presElementDoc.collapsedHeight], + params => this.presLayoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true }); } componentWillUnmount() { this._heightDisposer?.(); @@ -71,13 +71,13 @@ export class PresElementBox extends DocExtendableComponent { e.stopPropagation(); - this.originalLayout.hideTillShownButton = !this.originalLayout.hideTillShownButton; - if (!this.originalLayout.hideTillShownButton) { + this.presElementDoc.hideTillShownButton = !this.presElementDoc.hideTillShownButton; + if (!this.presElementDoc.hideTillShownButton) { if (this.indexInPres >= this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 1; } } else { - if (this.presentationDoc.presStatus && this.indexInPres > this.currentIndex && this.targetDoc) { + if (this.presBoxDoc.presStatus && this.indexInPres > this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 0; } } @@ -91,14 +91,14 @@ export class PresElementBox extends DocExtendableComponent { e.stopPropagation(); - this.originalLayout.hideAfterButton = !this.originalLayout.hideAfterButton; - if (!this.originalLayout.hideAfterButton) { + this.presElementDoc.hideAfterButton = !this.presElementDoc.hideAfterButton; + if (!this.presElementDoc.hideAfterButton) { if (this.indexInPres <= this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 1; } } else { - if (this.originalLayout.fadeButton) this.originalLayout.fadeButton = false; - if (this.presentationDoc.presStatus && this.indexInPres < this.currentIndex && this.targetDoc) { + if (this.presElementDoc.fadeButton) this.presElementDoc.fadeButton = false; + if (this.presBoxDoc.presStatus && this.indexInPres < this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 0; } } @@ -112,14 +112,14 @@ export class PresElementBox extends DocExtendableComponent { e.stopPropagation(); - this.originalLayout.fadeButton = !this.originalLayout.fadeButton; - if (!this.originalLayout.fadeButton) { + this.presElementDoc.fadeButton = !this.presElementDoc.fadeButton; + if (!this.presElementDoc.fadeButton) { if (this.indexInPres <= this.currentIndex && this.targetDoc) { this.targetDoc.opacity = 1; } } else { - this.originalLayout.hideAfterButton = false; - if (this.presentationDoc.presStatus && (this.indexInPres < this.currentIndex) && this.targetDoc) { + this.presElementDoc.hideAfterButton = false; + if (this.presBoxDoc.presStatus && (this.indexInPres < this.currentIndex) && this.targetDoc) { this.targetDoc.opacity = 0.5; } } @@ -131,11 +131,11 @@ export class PresElementBox extends DocExtendableComponent { e.stopPropagation(); - this.originalLayout.navButton = !this.originalLayout.navButton; - if (this.originalLayout.navButton) { - this.originalLayout.showButton = false; + this.presElementDoc.navButton = !this.presElementDoc.navButton; + if (this.presElementDoc.navButton) { + this.presElementDoc.showButton = false; if (this.currentIndex === this.indexInPres) { - this.props.focus(this.originalLayout); + this.props.focus(this.presElementDoc); } } } @@ -147,13 +147,13 @@ export class PresElementBox extends DocExtendableComponent { e.stopPropagation(); - this.originalLayout.showButton = !this.originalLayout.showButton; - if (!this.originalLayout.showButton) { - this.originalLayout.viewScale = 1; + this.presElementDoc.showButton = !this.presElementDoc.showButton; + if (!this.presElementDoc.showButton) { + this.presElementDoc.viewScale = 1; } else { - this.originalLayout.navButton = false; + this.presElementDoc.navButton = false; if (this.currentIndex === this.indexInPres) { - this.props.focus(this.originalLayout); + this.props.focus(this.presElementDoc); } } } @@ -162,14 +162,14 @@ export class PresElementBox extends DocExtendableComponent [xCord, yCord]; - embedHeight = () => this.props.PanelHeight() - NumCast(this.originalLayout.collapsedHeight); + embedHeight = () => this.props.PanelHeight() - NumCast(this.presElementDoc.collapsedHeight); embedWidth = () => this.props.PanelWidth() - 20; /** * The function that is responsible for rendering the a preview or not for this * presentation element. */ renderEmbeddedInline = () => { - return !this.originalLayout.embedOpen || !this.targetDoc ? (null) : + return !this.presElementDoc.embedOpen || !this.targetDoc ? (null) :
{ this.props.focus(this.originalLayout); e.stopPropagation(); }}> + onClick={e => { this.props.focus(this.presElementDoc); e.stopPropagation(); }}> {treecontainer ? (null) : <> {`${this.indexInPres + 1}. ${this.targetDoc?.title}`} - +
} - - - - - - - + + + + + + +
{this.renderEmbeddedInline()} diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 1636f4ee7..447dbe3b0 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -701,8 +701,11 @@ export namespace Doc { } // the document containing the view layout information - will be the Document itself unless the Document has - // a layout field. In that case, all layout information comes from there unless overriden by Document - export function Layout(doc: Doc): Doc { return doc[LayoutSym] || doc; } + // a layout field or 'layout' is given. + export function Layout(doc: Doc, layout?: Doc): Doc { + const overrideLayout = layout && Cast(doc["data-layout[" + layout[Id] + "]"], Doc, null); + return overrideLayout || doc[LayoutSym] || doc; + } export function SetLayout(doc: Doc, layout: Doc | string) { doc[StrCast(doc.layoutKey, "layout")] = layout; } export function LayoutField(doc: Doc) { return doc[StrCast(doc.layoutKey, "layout")]; } export function LayoutFieldKey(doc: Doc): string { return StrCast(Doc.Layout(doc).layout).split("'")[1]; } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 0185017ec..ce4f94d83 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -48,7 +48,7 @@ export class CurrentUserUtils { // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static setupCreatorButtons(doc: Doc, buttons?: string[]) { const notes = CurrentUserUtils.setupNoteTypes(doc); - const emptyPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, _chromeStatus: "replaced", showTitle: "title", boxShadow: "0 0" }); + const emptyPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, _LODdisable: true, _chromeStatus: "replaced", showTitle: "title", boxShadow: "0 0" }); const emptyCollection = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, _LODdisable: true, _width: 150, _height: 100, title: "freeform" }); doc.noteTypes = Docs.Create.TreeDocument(notes, { title: "Note Types", _height: 75 }); doc.activePen = doc; @@ -270,7 +270,8 @@ export class CurrentUserUtils { // the initial presentation Doc to use static setupDefaultPresentation(doc: Doc) { - doc.curPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, _chromeStatus: "replaced", showTitle: "title", boxShadow: "0 0" }); + doc.presentationTemplate = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data" })); + doc.curPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, _LODdisable: true, _chromeStatus: "replaced", showTitle: "title", boxShadow: "0 0" }); } static setupMobileUploads(doc: Doc) { -- cgit v1.2.3-70-g09d2 From d53ae2d90e7d7de8135ff19e18535cccd7a90ed0 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 19 Feb 2020 00:45:23 -0500 Subject: getting rid of data docs from many places --- src/client/documents/Documents.ts | 2 +- src/client/util/DictationManager.ts | 4 +- src/client/util/DocumentManager.ts | 6 +-- src/client/util/RichTextSchema.tsx | 2 +- src/client/views/DocComponent.tsx | 4 +- src/client/views/DocumentButtonBar.tsx | 8 +-- src/client/views/GlobalKeyHandler.ts | 2 +- src/client/views/MainView.tsx | 6 +-- src/client/views/MainViewNotifs.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 60 +++++++++------------- .../views/collections/CollectionSchemaCells.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 6 +-- .../views/collections/CollectionTreeView.tsx | 12 ++--- src/client/views/collections/CollectionView.tsx | 4 +- .../views/collections/ParentDocumentSelector.tsx | 4 +- src/client/views/linking/LinkFollowBox.tsx | 16 +++--- src/client/views/linking/LinkMenu.tsx | 2 +- src/client/views/linking/LinkMenuGroup.tsx | 2 +- src/client/views/linking/LinkMenuItem.tsx | 2 +- .../views/nodes/ContentFittingDocumentView.tsx | 2 +- src/client/views/nodes/DocuLinkBox.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 22 ++++---- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/FontIconBox.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/FormattedTextBoxComment.tsx | 4 +- src/client/views/nodes/KeyValuePair.tsx | 4 +- src/client/views/nodes/PresBox.tsx | 4 +- src/client/views/nodes/VideoBox.tsx | 2 +- src/client/views/pdf/Annotation.tsx | 6 +-- src/client/views/pdf/PDFViewer.tsx | 2 +- .../views/presentationview/PresElementBox.tsx | 3 +- src/client/views/search/SearchItem.tsx | 6 +-- src/new_fields/Doc.ts | 4 +- 36 files changed, 105 insertions(+), 112 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 669aa97b5..650538e93 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -654,7 +654,7 @@ export namespace Docs { { type: type, content: [ - ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth, config.path)) + ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, config.initialWidth, config.path)) ] } ] diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 3394cb93d..569c1ef6d 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -326,7 +326,7 @@ export namespace DictationManager { ["open fields", { action: (target: DocumentView) => { const kvp = Docs.Create.KVPDocument(target.props.Document, { _width: 300, _height: 300 }); - target.props.addDocTab(kvp, target.props.DataDoc, "onRight"); + target.props.addDocTab(kvp, "onRight"); } }], @@ -340,7 +340,7 @@ export namespace DictationManager { const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`; proto.data = new RichTextField(proseMirrorState); proto.backgroundColor = "#eeffff"; - target.props.addDocTab(newBox, proto, "onRight"); + target.props.addDocTab(newBox, "onRight"); } }] diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index bfda8e75b..c639f07f5 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -148,7 +148,7 @@ export class DocumentManager { const targetDocContext = (annotatedDoc ? annotatedDoc : contextDoc); if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default - (dockFunc || CollectionDockingView.AddRightSplit)(Doc.BrushDoc(Doc.MakeAlias(targetDoc)), undefined); + (dockFunc || CollectionDockingView.AddRightSplit)(Doc.BrushDoc(Doc.MakeAlias(targetDoc))); highlight(); } else { const targetDocContextView = DocumentManager.Instance.getFirstDocumentView(targetDocContext); @@ -164,12 +164,12 @@ export class DocumentManager { retryDocView.props.focus(targetDoc, willZoom); // focus on the target if it now exists in the context } else { if (closeContextIfNotFound && targetDocContextView.props.removeDocument) targetDocContextView.props.removeDocument(targetDocContextView.props.Document); - targetDoc.layout && (dockFunc || CollectionDockingView.AddRightSplit)(Doc.BrushDoc(Doc.MakeAlias(targetDoc)), undefined); // otherwise create a new view of the target + targetDoc.layout && (dockFunc || CollectionDockingView.AddRightSplit)(Doc.BrushDoc(Doc.MakeAlias(targetDoc))); // otherwise create a new view of the target } highlight(); }, 0); } else { // there's no context view so we need to create one first and try again - (dockFunc || CollectionDockingView.AddRightSplit)(targetDocContext, undefined); + (dockFunc || CollectionDockingView.AddRightSplit)(targetDocContext); setTimeout(() => { const finalDocView = DocumentManager.Instance.getFirstDocumentView(targetDoc); const finalDocContextView = DocumentManager.Instance.getFirstDocumentView(targetDocContext); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 23b0a56a8..cfbae5dca 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -613,7 +613,7 @@ export class ImageResizeView { DocServer.GetRefField(node.attrs.docid).then(async linkDoc => (linkDoc instanceof Doc) && DocumentManager.Instance.FollowLink(linkDoc, view.state.schema.Document, - document => addDocTab(document, undefined, node.attrs.location ? node.attrs.location : "inTab"), false)); + document => addDocTab(document, node.attrs.location ? node.attrs.location : "inTab"), false)); } }; this._handle.onpointerdown = function (e: any) { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 0bf944f22..61b1f9e0f 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,4 +1,4 @@ -import { Doc, Opt } from '../../new_fields/Doc'; +import { Doc, Opt, DataSym } from '../../new_fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; import { Cast } from '../../new_fields/Types'; @@ -58,7 +58,7 @@ export function DocAnnotatableComponent

(schema //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed get Document(): T { return schemaCtor(this.props.Document); } @computed get layoutDoc() { return Doc.Layout(this.props.Document); } - @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Cast(this.props.Document.resolvedDataDoc, Doc, null) || Doc.GetProto(this.props.Document)) as Doc; } + @computed get dataDoc() { return this.props.Document[DataSym]; } _annotationKey: string = "annotations"; public set annotationKey(val: string) { this._annotationKey = val; } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index b530d8a42..c8ad78f47 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -251,10 +251,10 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView | @computed get contextButton() { - return !this.view0 ? (null) : v).map(v => v as DocumentView)} Document={this.view0.props.Document} addDocTab={(doc, data, where) => { - where === "onRight" ? CollectionDockingView.AddRightSplit(doc, data) : - this.props.stack ? CollectionDockingView.Instance.AddTab(this.props.stack, doc, data) : - this.view0?.props.addDocTab(doc, data, "onRight"); + return !this.view0 ? (null) : v).map(v => v as DocumentView)} Document={this.view0.props.Document} addDocTab={(doc, where) => { + where === "onRight" ? CollectionDockingView.AddRightSplit(doc) : + this.props.stack ? CollectionDockingView.Instance.AddTab(this.props.stack, doc) : + this.view0?.props.addDocTab(doc, "onRight"); return true; }} />; } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 979687ffb..d0900251d 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -156,7 +156,7 @@ export default class KeyManager { return { stopPropagation: false, preventDefault: false }; } } - MainView.Instance.mainFreeform && CollectionDockingView.AddRightSplit(MainView.Instance.mainFreeform, undefined); + MainView.Instance.mainFreeform && CollectionDockingView.AddRightSplit(MainView.Instance.mainFreeform); break; case "arrowleft": if (document.activeElement) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7948da3c5..1849ec250 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -185,7 +185,7 @@ export class MainView extends React.Component { reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized, initialized => initialized && received && DocServer.GetRefField(received).then(docField => { if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) { - CollectionDockingView.AddRightSplit(docField, undefined); + CollectionDockingView.AddRightSplit(docField); } }), ); @@ -379,10 +379,10 @@ export class MainView extends React.Component { document.removeEventListener("pointerup", this.onPointerUp); } flyoutWidthFunc = () => this.flyoutWidth; - addDocTabFunc = (doc: Doc, data: Opt, where: string, libraryPath?: Doc[]): boolean => { + addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => { return where === "close" ? CollectionDockingView.CloseRightSplit(doc) : doc.dockingConfig ? this.openWorkspace(doc) : - CollectionDockingView.AddRightSplit(doc, undefined, libraryPath); + CollectionDockingView.AddRightSplit(doc, libraryPath); } mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1); diff --git a/src/client/views/MainViewNotifs.tsx b/src/client/views/MainViewNotifs.tsx index 09fa1cb0c..82e07c449 100644 --- a/src/client/views/MainViewNotifs.tsx +++ b/src/client/views/MainViewNotifs.tsx @@ -15,7 +15,7 @@ export class MainViewNotifs extends React.Component { @observable static NotifsCol: Opt; openNotifsCol = () => { if (MainViewNotifs.NotifsCol) { - CollectionDockingView.AddRightSplit(MainViewNotifs.NotifsCol, undefined); + CollectionDockingView.AddRightSplit(MainViewNotifs.NotifsCol); } } render() { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 26b65c898..6e1d522fc 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -8,7 +8,7 @@ import * as ReactDOM from 'react-dom'; import Measure from "react-measure"; import * as GoldenLayout from "../../../client/goldenLayout"; import { DateField } from '../../../new_fields/DateField'; -import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc"; +import { Doc, DocListCast, Field, Opt, DataSym } from "../../../new_fields/Doc"; import { Id } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; import { FieldId } from "../../../new_fields/RefField"; @@ -38,7 +38,7 @@ const _global = (window /* browser */ || global /* node */) as any; export class CollectionDockingView extends React.Component { @observable public static Instances: CollectionDockingView[] = []; @computed public static get Instance() { return CollectionDockingView.Instances[0]; } - public static makeDocumentConfig(document: Doc, dataDoc: Doc | undefined, width?: number, libraryPath?: Doc[]) { + public static makeDocumentConfig(document: Doc, width?: number, libraryPath?: Doc[]) { return { type: 'react-component', component: 'DocumentFrameRenderer', @@ -46,8 +46,7 @@ export class CollectionDockingView extends React.Component d[Id]) : [] + libraryPath: libraryPath?.map(d => d[Id]) //collectionDockingView: CollectionDockingView.Instance } }; @@ -76,12 +75,12 @@ export class CollectionDockingView extends React.Component { - CollectionDockingView.makeDocumentConfig(doc, undefined); + CollectionDockingView.makeDocumentConfig(doc); }) }; } @@ -97,10 +96,9 @@ export class CollectionDockingView extends React.Component { if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" && DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)?.Document.isDisplayPanel) { - const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, dataDoc, undefined, libraryPath); + const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); child.addChild(newItemStackConfig, undefined); !addToSplit && child.contentItems[0].remove(); instance.layoutChanged(document); @@ -188,7 +186,7 @@ export class CollectionDockingView extends React.Component tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { if (DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)?.Document.isDisplayPanel) { - const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, dataDoc, undefined, libraryPath); + const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); child.addChild(newItemStackConfig, undefined); !addToSplit && child.contentItems[j].remove(); instance.layoutChanged(document); @@ -210,12 +208,12 @@ export class CollectionDockingView extends React.Component { + public AddTab = (stack: any, document: Doc, libraryPath?: Doc[]) => { Doc.GetProto(document).lastOpened = new DateField; - const docContentConfig = CollectionDockingView.makeDocumentConfig(document, dataDocument, undefined, libraryPath); + const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); if (stack === undefined) { let stack: any = this._goldenLayout.root; while (!stack.isStack) { @@ -427,7 +425,6 @@ export class CollectionDockingView extends React.Component`; tab.titleElement[0].onclick = (e: any) => tab.titleElement[0].focus(); @@ -507,7 +504,7 @@ export class CollectionDockingView extends React.Component { if (e.target === stack.header.element[0] && e.button === 1) { - this.AddTab(stack, Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: "Untitled Collection" }), undefined); + this.AddTab(stack, Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: "Untitled Collection" })); } }); @@ -580,7 +577,6 @@ export class CollectionDockingView extends React.Component string | undefined; @@ -593,7 +589,6 @@ export class DockedFrameRenderer extends React.Component { @observable private _panelWidth = 0; @observable private _panelHeight = 0; @observable private _document: Opt; - @observable private _dataDoc: Opt; @observable private _isActive: boolean = false; get _stack(): any { @@ -601,12 +596,7 @@ export class DockedFrameRenderer extends React.Component { } constructor(props: any) { super(props); - DocServer.GetRefField(this.props.documentId).then(action((f: Opt) => { - this._document = f as Doc; - if (this.props.dataDocumentId && this.props.documentId !== this.props.dataDocumentId) { - DocServer.GetRefField(this.props.dataDocumentId).then(action((f: Opt) => this._dataDoc = f as Doc)); - } - })); + DocServer.GetRefField(this.props.documentId).then(action((f: Opt) => this._document = f as Doc)); this.props.libraryPath && this.setupLibraryPath(); } @@ -630,7 +620,7 @@ export class DockedFrameRenderer extends React.Component { pinDoc.presentationTargetDoc = doc; Doc.AddDocToList(curPres, "data", pinDoc); if (!DocumentManager.Instance.getDocumentView(curPres)) { - CollectionDockingView.AddRightSplit(curPres, undefined); + CollectionDockingView.AddRightSplit(curPres); } } } @@ -708,16 +698,16 @@ export class DockedFrameRenderer extends React.Component { get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; } get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this.panelWidth() * 100}%` : undefined; } - addDocTab = (doc: Doc, dataDoc: Opt, location: string, libraryPath?: Doc[]) => { + addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => { SelectionManager.DeselectAll(); if (doc.dockingConfig) { return MainView.Instance.openWorkspace(doc); } else if (location === "onRight") { - return CollectionDockingView.AddRightSplit(doc, dataDoc, libraryPath); + return CollectionDockingView.AddRightSplit(doc, libraryPath); } else if (location === "close") { return CollectionDockingView.CloseRightSplit(doc); } else { - return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc, libraryPath); + return CollectionDockingView.Instance.AddTab(this._stack, doc, libraryPath); } } @@ -725,7 +715,7 @@ export class DockedFrameRenderer extends React.Component { TraceMobx(); if (!this._document) return (null); const document = this._document; - const resolvedDataDoc = document.layout instanceof Doc ? document : this._dataDoc; + const resolvedDataDoc = this._document[DataSym] !== this._document && this._document[DataSym];// document.layout instanceof Doc ? document : this._dataDoc; return {

); } } -Scripting.addGlobal(function openOnRight(doc: any) { CollectionDockingView.AddRightSplit(doc, undefined); }); -Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.UseRightSplit(doc, undefined, undefined, shiftKey); }); +Scripting.addGlobal(function openOnRight(doc: any) { CollectionDockingView.AddRightSplit(doc); }); +Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.UseRightSplit(doc, undefined, shiftKey); }); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index a3b1b5ec0..851fded71 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -35,7 +35,7 @@ export interface CellProps { Document: Doc; fieldKey: string; renderDepth: number; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index c422c38f1..7dee7f18f 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -224,7 +224,7 @@ export interface SchemaTableProps { ScreenToLocalTransform: () => Transform; active: (outsideReaction: boolean) => boolean; onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; isSelected: (outsideReaction?: boolean) => boolean; isFocused: (document: Doc) => boolean; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index ad9dc8f7c..0d5d3e449 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -4,7 +4,7 @@ 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 } from "../../../new_fields/Doc"; +import { Doc, HeightSym, WidthSym, DataSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; @@ -62,7 +62,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); const style = this.isStackingView ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; return
- {this.getDisplayDoc(d, Cast(d.resolvedDataDoc, Doc, null) || this.props.DataDoc, dxf, width)} + {this.getDisplayDoc(d, this.props.DataDoc, dxf, width)}
; }); } @@ -158,7 +158,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const height = () => this.getDocHeight(doc); return boolean; moveDocument: DragManager.MoveFunction; dropAction: "alias" | "copy" | undefined; - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; + addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; panelWidth: () => number; panelHeight: () => number; @@ -128,7 +128,7 @@ class TreeView extends React.Component { } @undoBatch delete = () => this.props.deleteDoc(this.props.document); - @undoBatch openRight = () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath); + @undoBatch openRight = () => this.props.addDocTab(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) => { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); @@ -201,8 +201,8 @@ class TreeView extends React.Component { ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.GetProto(CurrentUserUtils.UserDocument.recentlyClosed as Doc).data = new List(), icon: "plus" }); } else if (this.props.document !== CurrentUserUtils.UserDocument.workspaces) { ContextMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.document), icon: "tv" }); - ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "inTab", this.props.libraryPath), icon: "folder" }); - ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath), icon: "caret-square-right" }); + ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, "inTab", this.props.libraryPath), icon: "folder" }); + ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath), icon: "caret-square-right" }); if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) { ContextMenu.Instance.addItem({ description: "Focus", event: () => (view => view && view.props.focus(this.props.document, true))(DocumentManager.Instance.getFirstDocumentView(this.props.document)), icon: "camera" }); } @@ -212,7 +212,7 @@ class TreeView extends React.Component { ContextMenu.Instance.addItem({ description: "Create New Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" }); } ContextMenu.Instance.addItem({ description: "Toggle Theme Colors", event: () => this.props.document.darkScheme = !this.props.document.darkScheme, icon: "minus" }); - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { const kvp = Docs.Create.KVPDocument(this.props.document, { _width: 300, _height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { const kvp = Docs.Create.KVPDocument(this.props.document, { _width: 300, _height: 300 }); this.props.addDocTab(kvp, "onRight"); }, icon: "layer-group" }); ContextMenu.Instance.addItem({ description: "Publish", event: () => DocUtils.Publish(this.props.document, StrCast(this.props.document.title), () => { }, () => { }), icon: "file" }); ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15); e.stopPropagation(); @@ -457,7 +457,7 @@ class TreeView extends React.Component { remove: ((doc: Doc) => boolean), move: DragManager.MoveFunction, dropAction: dropActionType, - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean, + addDocTab: (doc: Doc, where: string) => boolean, pinToPres: (document: Doc) => void, backgroundColor: undefined | ((document: Doc) => string | undefined), screenToLocalXf: () => Transform, diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 79fd7d792..95f9fa62f 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -229,10 +229,10 @@ export class CollectionView extends Touchable { const layoutItems = existing && "subitems" in existing ? existing.subitems : []; layoutItems.push({ description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }); if (this.props.Document.childLayout instanceof Doc) { - layoutItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, undefined, "onRight"), icon: "project-diagram" }); + layoutItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" }); } if (this.props.Document.childDetailed instanceof Doc) { - layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailed as Doc, undefined, "onRight"), icon: "project-diagram" }); + layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailed as Doc, "onRight"), icon: "project-diagram" }); } !existing && ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "hand-point-right" }); diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 027ac5a0e..43ba5c614 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -24,7 +24,7 @@ type SelectorProps = { Document: Doc, Views: DocumentView[], Stack?: any, - addDocTab(doc: Doc, dataDoc: Doc | undefined, location: string): void + addDocTab(doc: Doc, location: string): void }; @observer @@ -60,7 +60,7 @@ export class SelectorContextMenu extends React.Component { col._panX = newPanX; col._panY = newPanY; } - this.props.addDocTab(col, undefined, "inTab"); // bcz: dataDoc? + this.props.addDocTab(col, "inTab"); // bcz: dataDoc? }; } diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 325c92413..b47464517 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -183,9 +183,9 @@ export class LinkFollowBox extends React.Component { } - static _addDocTab: (undefined | ((doc: Doc, dataDoc: Opt, where: string) => boolean)); + static _addDocTab: (undefined | ((doc: Doc, where: string) => boolean)); - static setAddDocTab = (addFunc: (doc: Doc, dataDoc: Opt, where: string) => boolean) => { + static setAddDocTab = (addFunc: (doc: Doc, where: string) => boolean) => { LinkFollowBox._addDocTab = addFunc; } @@ -199,7 +199,7 @@ export class LinkFollowBox extends React.Component { options.context._panX = newPanX; options.context._panY = newPanY; } - (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, undefined, "onRight"); + (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, "onRight"); if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom }); @@ -212,7 +212,7 @@ export class LinkFollowBox extends React.Component { openLinkRight = () => { if (LinkFollowBox.destinationDoc) { const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); - (LinkFollowBox._addDocTab || this.props.addDocTab)(alias, undefined, "onRight"); + (LinkFollowBox._addDocTab || this.props.addDocTab)(alias, "onRight"); this.highlightDoc(); SelectionManager.DeselectAll(); } @@ -222,8 +222,8 @@ export class LinkFollowBox extends React.Component { @undoBatch jumpToLink = async (options: { shouldZoom: boolean }) => { if (LinkFollowBox.sourceDoc && LinkFollowBox.linkDoc) { - const focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; - //let focus = (doc: Doc, maxLocation: string) => this.props.focus(docthis.props.focus(LinkFollowBox.destinationDoc, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation)); + const focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, "inTab"); SelectionManager.DeselectAll(); }; + //let focus = (doc: Doc, maxLocation: string) => this.props.focus(docthis.props.focus(LinkFollowBox.destinationDoc, true, 1, () => this.props.addDocTab(doc, maxLocation)); DocumentManager.Instance.FollowLink(LinkFollowBox.linkDoc, LinkFollowBox.sourceDoc, focus, options && options.shouldZoom, false, undefined); } @@ -234,7 +234,7 @@ export class LinkFollowBox extends React.Component { if (LinkFollowBox.destinationDoc) { const fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc); // this.prosp.addDocTab is empty -- use the link source's addDocTab - (LinkFollowBox._addDocTab || this.props.addDocTab)(fullScreenAlias, undefined, "inTab"); + (LinkFollowBox._addDocTab || this.props.addDocTab)(fullScreenAlias, "inTab"); this.highlightDoc(); SelectionManager.DeselectAll(); @@ -251,7 +251,7 @@ export class LinkFollowBox extends React.Component { options.context._panX = newPanX; options.context._panY = newPanY; } - (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, undefined, "inTab"); + (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, "inTab"); if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom }); this.highlightDoc(); diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 1a40f0c55..a8aa01306 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -16,7 +16,7 @@ library.add(faTrash); interface Props { docView: DocumentView; changeFlyout: () => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; } @observer diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 0c38ff45c..78c77e106 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -17,7 +17,7 @@ interface LinkMenuGroupProps { group: Doc[]; groupType: string; showEditor: (linkDoc: Doc) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; docView: DocumentView; } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index b7d27ee30..54f5636e4 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -20,7 +20,7 @@ interface LinkMenuItemProps { sourceDoc: Doc; destinationDoc: Doc; showEditor: (linkDoc: Doc) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; } @observer diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 73fe4fb5d..36233a7e6 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -34,7 +34,7 @@ interface ContentFittingDocumentViewProps { removeDocument?: (document: Doc) => boolean; active: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; dontRegisterView?: boolean; } diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx index 156b16ec8..a0b5cd8ec 100644 --- a/src/client/views/nodes/DocuLinkBox.tsx +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -61,7 +61,7 @@ export class DocuLinkBox extends DocComponent(Doc onClick = (e: React.MouseEvent) => { if (!this.props.Document.onClick) { if (Math.abs(e.clientX - this._downx) < 3 && Math.abs(e.clientY - this._downy) < 3 && (e.button !== 2 && !e.ctrlKey && this.props.Document.isButton)) { - DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, undefined, "inTab"), false); + DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, "inTab"), false); } e.stopPropagation(); } diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 11a33b70a..c0f603171 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -82,7 +82,7 @@ export class DocumentContentsView extends React.Component boolean; whenActiveChanged: (isActive: boolean) => void; bringToFront: (doc: Doc, sendToBack?: boolean) => void; - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; + addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; zoomToScale: (scale: number) => void; backgroundHalo?: () => boolean; @@ -152,9 +152,9 @@ export class DocumentView extends DocComponent(Docu // RadialMenu.Instance.openMenu(); - // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group", selected: -1 }); + // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight"), icon: "layer-group", selected: -1 }); // RadialMenu.Instance.addItem({ description: "Delete this document", event: () => this.props.ContainingCollectionView?.removeDocument(this.props.Document), icon: "trash", selected: -1 }); - // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, undefined, "onRight"), icon: "folder", selected: -1 }); + // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "folder", selected: -1 }); // RadialMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin", selected: -1 }); // RadialMenu.Instance.displayMenu(pt.pageX - 15, pt.pageY - 15); @@ -253,7 +253,7 @@ export class DocumentView extends DocComponent(Docu if (StrCast(fullScreenAlias.layoutKey) !== "layout_fullScreen" && fullScreenAlias.layout_fullScreen) { fullScreenAlias.layoutKey = "layout_fullScreen"; } - UndoManager.RunInBatch(() => this.props.addDocTab(fullScreenAlias, undefined, "inTab"), "double tap"); + UndoManager.RunInBatch(() => this.props.addDocTab(fullScreenAlias, "inTab"), "double tap"); SelectionManager.DeselectAll(); Doc.UnBrushDoc(this.props.Document); } else if (this.onClickHandler && this.onClickHandler.script) { @@ -277,7 +277,7 @@ export class DocumentView extends DocComponent(Docu if (linkDocs.length) { DocumentManager.Instance.FollowLink(undefined, this.props.Document, // open up target if it's not already in view ... by zooming into the button document first and setting flag to reset zoom afterwards - (doc: Doc, maxLocation: string) => this.props.focus(this.props.Document, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation)), + (doc: Doc, maxLocation: string) => this.props.focus(this.props.Document, true, 1, () => this.props.addDocTab(doc, maxLocation)), ctrlKey, altKey, this.props.ContainingCollectionDoc); } } @@ -644,12 +644,12 @@ export class DocumentView extends DocComponent(Docu const open = ContextMenu.Instance.findByDescription("Open..."); const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; openItems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this, this.props.LibraryPath), icon: "desktop" }); - openItems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab", this.props.LibraryPath), icon: "folder" }); - openItems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight", this.props.LibraryPath), icon: "caret-square-right" }); - openItems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "inTab"), icon: "folder" }); - openItems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "onRight"), icon: "caret-square-right" }); - openItems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), undefined, "onRight"), icon: "layer-group" }); - templateDoc && openItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, undefined, "onRight"), icon: "eye" }); + openItems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, "inTab", this.props.LibraryPath), icon: "folder" }); + openItems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, "onRight", this.props.LibraryPath), icon: "caret-square-right" }); + openItems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), "inTab"), icon: "folder" }); + openItems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), "onRight"), icon: "caret-square-right" }); + openItems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); + templateDoc && openItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" }); openItems.push({ description: "Open Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); !open && cm.addItem({ description: "Open...", subitems: openItems, icon: "external-link-alt" }); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 00f00dd52..f5c85e143 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -29,7 +29,7 @@ export interface FieldViewProps { select: (isCtrlPressed: boolean) => void; renderDepth: number; addDocument?: (document: Doc) => boolean; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => 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; diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index a191ac4f4..d4da21239 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -36,7 +36,7 @@ export class FontIconBox extends DocComponent( showTemplate = (): void => { const dragFactory = Cast(this.props.Document.dragFactory, Doc, null); - dragFactory && this.props.addDocTab(dragFactory, undefined, "onRight"); + dragFactory && this.props.addDocTab(dragFactory, "onRight"); } specificContextMenu = (): void => { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index fd288f720..842ccdd7b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -916,7 +916,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & // if (linkClicked) { // DocServer.GetRefField(linkClicked).then(async linkDoc => { // (linkDoc instanceof Doc) && - // DocumentManager.Instance.FollowLink(linkDoc, this.props.Document, document => this.props.addDocTab(document, undefined, location ? location : "inTab"), false); + // DocumentManager.Instance.FollowLink(linkDoc, this.props.Document, document => this.props.addDocTab(document, location ? location : "inTab"), false); // }); // } // } else { diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index fda3e3285..1174110e7 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -84,9 +84,9 @@ export class FormattedTextBoxComment { const textBox = FormattedTextBoxComment.textBox; if (FormattedTextBoxComment.linkDoc && !keep && textBox) { DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, - (doc: Doc, maxLocation: string) => textBox.props.addDocTab(doc, undefined, e.ctrlKey ? "inTab" : "onRight")); + (doc: Doc, maxLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "inTab" : "onRight")); } else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) { - textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400 }), undefined, "onRight"); + textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400 }), "onRight"); } keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation( FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index e6b512adf..93bda6d02 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -22,7 +22,7 @@ export interface KeyValuePairProps { keyWidth: number; PanelHeight: () => number; PanelWidth: () => number; - addDocTab: (doc: Doc, data: Opt, where: string) => boolean; + addDocTab: (doc: Doc, where: string) => boolean; } @observer export class KeyValuePair extends React.Component { @@ -46,7 +46,7 @@ export class KeyValuePair extends React.Component { if (value instanceof Doc) { e.stopPropagation(); e.preventDefault(); - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { _width: 300, _height: 300 }), undefined, "onRight"), icon: "layer-group" }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); ContextMenu.Instance.displayMenu(e.clientX, e.clientY); } } diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index d4a47c159..8d20bbe59 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -327,12 +327,12 @@ export class PresBox extends React.Component { if (toggle) { if (this.props.Document.inOverlay) { Doc.RemoveDocFromList((CurrentUserUtils.UserDocument.overlays as Doc), this.props.fieldKey, this.props.Document); - CollectionDockingView.AddRightSplit(this.props.Document, this.props.DataDoc); + CollectionDockingView.AddRightSplit(this.props.Document); this.props.Document.inOverlay = false; } else { this.props.Document.x = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0)[0];// 500;//e.clientX + 25; this.props.Document.y = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0)[1];////e.clientY - 25; - this.props.addDocTab && this.props.addDocTab(this.props.Document, this.props.DataDoc, "close"); + this.props.addDocTab?.(this.props.Document, "close"); Doc.AddDocToList((CurrentUserUtils.UserDocument.overlays as Doc), this.props.fieldKey, this.props.Document); } } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 6695e04c3..69c6f2617 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -90,7 +90,7 @@ export class VideoBox extends DocAnnotatableComponent, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; focus: (doc: Doc) => void; dataDoc: Doc; @@ -30,7 +30,7 @@ interface IRegionAnnotationProps { y: number; width: number; height: number; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; document: Doc; dataDoc: Doc; @@ -98,7 +98,7 @@ class RegionAnnotation extends React.Component { const annoGroup = await Cast(this.props.document.group, Doc); if (annoGroup) { DocumentManager.Instance.FollowLink(undefined, annoGroup, - (doc: Doc, maxLocation: string) => this.props.addDocTab(doc, undefined, e.ctrlKey ? "inTab" : "onRight"), + (doc: Doc, maxLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : "onRight"), false, false, undefined); e.stopPropagation(); } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index a9b8c6bbe..198aeb856 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -65,7 +65,7 @@ interface IViewerProps { loaded: (nw: number, nh: number, np: number) => void; active: (outsideReaction?: boolean) => boolean; isChildActive: (outsideReaction?: boolean) => boolean; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; addDocument?: (doc: Doc) => boolean; setPdfViewer: (view: PDFViewer) => void; diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 888707ee3..8d62c34c5 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -4,7 +4,7 @@ import { faArrowDown, faArrowUp, faFile as fileSolid, faFileDownload, faLocation import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DataSym } from "../../../new_fields/Doc"; import { documentSchema } from '../../../new_fields/documentSchemas'; import { Id } from "../../../new_fields/FieldSymbols"; import { createSchema, makeInterface } from '../../../new_fields/Schema'; @@ -173,6 +173,7 @@ export class PresElementBox extends DocExtendableComponent { col._panX = newPanX; col._panY = newPanY; } - CollectionDockingView.AddRightSplit(col, undefined); + CollectionDockingView.AddRightSplit(col); }; } render() { @@ -108,7 +108,7 @@ export class LinkContextMenu extends React.Component { unHighlightDoc = (doc: Doc) => () => Doc.UnBrushDoc(doc); - getOnClick = (col: Doc) => () => CollectionDockingView.AddRightSplit(col, undefined); + getOnClick = (col: Doc) => () => CollectionDockingView.AddRightSplit(col); render() { return ( @@ -272,7 +272,7 @@ export class SearchItem extends React.Component { @computed get contextButton() { - return CollectionDockingView.AddRightSplit(doc, data)} />; + return CollectionDockingView.AddRightSplit(doc)} />; } render() { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 43bbea623..1f2dd1c8f 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -17,6 +17,7 @@ import { listSpec } from "./Schema"; import { ComputedField } from "./ScriptField"; import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; +import { DatasetAbout } from "../client/northstar/model/idea/idea"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -495,7 +496,8 @@ export namespace Doc { // if the childDoc is a template for a field, then this will return the expanded layout with its data doc. // otherwise, it just returns the childDoc export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt, childDoc: Doc) { - const resolvedDataDoc = containerDataDoc === containerDoc || !containerDataDoc || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc; + const existingResolvedDataDoc = childDoc[DataSym] !== Doc.GetProto(childDoc)[DataSym] && childDoc[DataSym]; + const resolvedDataDoc = existingResolvedDataDoc || (containerDataDoc === containerDoc || !containerDataDoc || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc); return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc }; } export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) { -- cgit v1.2.3-70-g09d2 From 0b85eecdb974a7446be855f7b2fdef8978b65733 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 12 Mar 2020 20:29:06 -0400 Subject: cleaned up presentationBox code and buttons in view chromes. --- .../views/collections/CollectionViewChromes.tsx | 23 +-- src/client/views/nodes/PresBox.scss | 7 + src/client/views/nodes/PresBox.tsx | 154 +++++++-------------- .../views/presentationview/PresElementBox.tsx | 19 ++- src/new_fields/Doc.ts | 6 +- 5 files changed, 85 insertions(+), 124 deletions(-) (limited to 'src/client/views/presentationview') diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 57a73000d..689d3674f 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -38,25 +38,30 @@ const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); export class CollectionViewBaseChrome extends React.Component { //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\) + get target() { return this.props.CollectionView.props.Document; } _templateCommand = { - title: "=> item view", script: "setChildLayout(this.target, this.source?.[0])", params: ["target", "source"], + params: ["target", "source"], title: "=> item view", + script: "setChildLayout(this.target, this.source?.[0])", + immediate: (source: Doc[]) => Doc.setChildLayout(this.target, source?.[0]), initialize: emptyFunction, - immediate: (draggedDocs: Doc[]) => Doc.setChildLayout(this.props.CollectionView.props.Document, draggedDocs.length ? draggedDocs[0] : undefined) }; _narrativeCommand = { - title: "=> click item view", script: "setChildDetailedLayout(this.target, this.source?.[0])", params: ["target", "source"], + params: ["target", "source"], title: "=> click item view", + script: "setChildDetailedLayout(this.target, this.source?.[0])", + immediate: (source: Doc[]) => Doc.setChildDetailedLayout(this.target, source?.[0]), initialize: emptyFunction, - immediate: (draggedDocs: Doc[]) => Doc.setChildDetailedLayout(this.props.CollectionView.props.Document, draggedDocs.length ? draggedDocs[0] : undefined) }; _contentCommand = { - title: "=> content", script: "getProto(this.target).data = aliasDocs(this.source);", params: ["target", "source"], + params: ["target", "source"], title: "=> content", + script: "getProto(this.target).data = aliasDocs(this.source);", + immediate: (source: Doc[]) => Doc.GetProto(this.target).data = Doc.aliasDocs(source), initialize: emptyFunction, - immediate: (draggedDocs: Doc[]) => Doc.GetProto(this.props.CollectionView.props.Document).data = new List(draggedDocs.map((d: any) => Doc.MakeAlias(d))) }; _viewCommand = { - title: "=> saved view", script: "this.target._panX = this.restoredPanX; this.target._panY = this.restoredPanY; this.target.scale = this.restoredScale;", params: ["target"], - initialize: (button: Doc) => { button.restoredPanX = this.props.CollectionView.props.Document._panX; button.restoredPanY = this.props.CollectionView.props.Document._panY; button.restoredScale = this.props.CollectionView.props.Document.scale; }, - immediate: (draggedDocs: Doc[]) => { this.props.CollectionView.props.Document._panX = 0; this.props.CollectionView.props.Document._panY = 0; this.props.CollectionView.props.Document.scale = 1; }, + params: ["target"], title: "=> saved view", + script: "this.target._panX = this.restoredPanX; this.target._panY = this.restoredPanY; this.target.scale = this.restoredScale;", + immediate: (source: Doc[]) => { this.target._panX = 0; this.target._panY = 0; this.target.scale = 1; }, + initialize: (button: Doc) => { button.restoredPanX = this.target._panX; button.restoredPanY = this.target._panY; button.restoredScale = this.target.scale; }, }; _freeform_commands = [this._contentCommand, this._templateCommand, this._narrativeCommand, this._viewCommand]; _stacking_commands = [this._contentCommand, this._templateCommand]; diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 6a20751cc..ba8389fda 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -25,6 +25,13 @@ width: 20%; border-radius: 5px; } + .collectionViewBaseChrome-viewPicker { + min-width: 50; + width: 5%; + height: 25; + position: relative; + display: inline-block; + } } .presBox-backward, .presBox-forward { width: 25px; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 4c5535548..c62cd5952 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -4,7 +4,7 @@ import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faH import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { InkTool } from "../../../new_fields/InkField"; import { listSpec } from "../../../new_fields/Schema"; import { BoolCast, Cast, FieldValue, NumCast } from "../../../new_fields/Types"; @@ -14,8 +14,6 @@ import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionView, CollectionViewType } from "../collections/CollectionView"; -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; @@ -45,63 +43,45 @@ export class PresBox extends React.Component { } @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } + @computed get currentIndex() { return NumCast(this.props.Document._itemIndex); } - next = async () => { - runInAction(() => Doc.UserDoc().curPresentation = this.props.Document); - const current = NumCast(this.props.Document._itemIndex); - //asking to get document at current index - const docAtCurrentNext = await this.getDocAtIndex(current + 1); - if (docAtCurrentNext !== undefined) { - const presDocs = DocListCast(this.props.Document[this.props.fieldKey]); - let nextSelected = current + 1; - - for (; nextSelected < presDocs.length - 1; nextSelected++) { - if (!presDocs[nextSelected + 1].groupButton) { + updateCurrentPresentation = action(() => Doc.UserDoc().curPresentation = this.props.Document); + + next = () => { + this.updateCurrentPresentation(); + if (this.childDocs[this.currentIndex + 1] !== undefined) { + let nextSelected = this.currentIndex + 1; + + for (; nextSelected < this.childDocs.length - 1; nextSelected++) { + if (!this.childDocs[nextSelected + 1].groupButton) { break; } } - this.gotoDocument(nextSelected, current); + this.gotoDocument(nextSelected, this.currentIndex); } } - back = async () => { - action(() => Doc.UserDoc().curPresentation = this.props.Document); - const current = NumCast(this.props.Document._itemIndex); - //requesting for the doc at current index - const docAtCurrent = await this.getDocAtIndex(current); - if (docAtCurrent !== undefined) { - - //asking for its presentation id. - let prevSelected = current; - let zoomOut: boolean = false; - - const presDocs = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - const currentsArray: Doc[] = []; - for (; presDocs && prevSelected > 0 && presDocs[prevSelected].groupButton; prevSelected--) { - currentsArray.push(presDocs[prevSelected]); + back = () => { + this.updateCurrentPresentation(); + const docAtCurrent = this.childDocs[this.currentIndex]; + if (docAtCurrent) { + //check if any of the group members had used zooming in including the current document + //If so making sure to zoom out, which goes back to state before zooming action + let prevSelected = this.currentIndex; + let didZoom = docAtCurrent.zoomButton; + for (; !didZoom && prevSelected > 0 && this.childDocs[prevSelected].groupButton; prevSelected--) { + didZoom = this.childDocs[prevSelected].zoomButton; } prevSelected = Math.max(0, prevSelected - 1); - //checking if any of the group members had used zooming in - currentsArray.forEach((doc: Doc) => { - if (doc.showButton) { - zoomOut = true; - return; - } - }); - - // if a group set that flag to zero or a single element - //If so making sure to zoom out, which goes back to state before zooming action - if (current > 0) { - if (zoomOut || docAtCurrent.showButton) { - const prevScale = NumCast(this.childDocs[prevSelected].viewScale, null); - const curScale = DocumentManager.Instance.getScaleOfDocView(this.childDocs[current]); - if (prevScale !== undefined && prevScale !== curScale) { - DocumentManager.Instance.zoomIntoScale(docAtCurrent, prevScale); - } + if (this.currentIndex > 0 && didZoom) { + const prevScale = NumCast(this.childDocs[prevSelected].viewScale); + const curScale = DocumentManager.Instance.getScaleOfDocView(docAtCurrent); + if (prevScale && prevScale !== curScale) { + DocumentManager.Instance.zoomIntoScale(docAtCurrent, prevScale); } } - this.gotoDocument(prevSelected, current); + this.gotoDocument(prevSelected, this.currentIndex); } } @@ -115,7 +95,7 @@ export class PresBox extends React.Component { * Hide Until Presented, Hide After Presented, Fade After Presented */ showAfterPresented = (index: number) => { - action(() => Doc.UserDoc().curPresentation = this.props.Document); + this.updateCurrentPresentation(); this.childDocs.forEach((doc, ind) => { //the order of cases is aligned based on priority if (doc.hideTillShownButton && ind <= index) { @@ -136,7 +116,7 @@ export class PresBox extends React.Component { * Hide Until Presented, Hide After Presented, Fade After Presented */ hideIfNotPresented = (index: number) => { - action(() => Doc.UserDoc().curPresentation = this.props.Document); + this.updateCurrentPresentation(); this.childDocs.forEach((key, ind) => { //the order of cases is aligned based on priority @@ -158,7 +138,7 @@ export class PresBox extends React.Component { * te option open, navigates to that element. */ navigateToElement = async (curDoc: Doc, fromDocIndex: number) => { - action(() => Doc.UserDoc().curPresentation = this.props.Document); + this.updateCurrentPresentation(); const fromDoc = this.childDocs[fromDocIndex].presentationTargetDoc as Doc; let docToJump = curDoc; let willZoom = false; @@ -178,7 +158,7 @@ export class PresBox extends React.Component { docToJump = doc; willZoom = false; } - if (doc.showButton) { + if (doc.zoomButton) { docToJump = doc; willZoom = true; } @@ -192,7 +172,7 @@ export class PresBox extends React.Component { const target = await Cast(curDoc.presentationTargetDoc, Doc); if (curDoc.navButton && target) { DocumentManager.Instance.jumpToDocument(target, false, undefined, srcContext); - } else if (curDoc.showButton && target) { + } else if (curDoc.zoomButton && target) { const curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); //awaiting jump so that new scale can be found, since jumping is async await DocumentManager.Instance.jumpToDocument(target, true, undefined, srcContext); @@ -220,19 +200,6 @@ export class PresBox extends React.Component { } - /** - * Async function that supposedly return the doc that is located at given index. - */ - getDocAtIndex = async (index: number) => { - const list = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); - if (list && index >= 0 && index < list.length) { - this.props.Document._itemIndex = index; - //awaiting async call to finish to get Doc instance - return list[index]; - } - return undefined; - } - @undoBatch public removeDocument = (doc: Doc) => { @@ -249,11 +216,10 @@ export class PresBox extends React.Component { //The function that is called when a document is clicked or reached through next or back. //it'll also execute the necessary actions if presentation is playing. - public gotoDocument = async (index: number, fromDoc: number) => { - action(() => Doc.UserDoc().curPresentation = this.props.Document); + public gotoDocument = (index: number, fromDoc: number) => { + this.updateCurrentPresentation(); Doc.UnBrushAllDocs(); - const list = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); - if (list && index >= 0 && index < list.length) { + if (index >= 0 && index < this.childDocs.length) { this.props.Document._itemIndex = index; if (!this.props.Document.presStatus) { @@ -261,24 +227,21 @@ export class PresBox extends React.Component { this.startPresentation(index); } - const doc = await list[index]; - if (this.props.Document.presStatus) { - this.navigateToElement(doc, fromDoc); - this.hideIfNotPresented(index); - this.showAfterPresented(index); - } + this.navigateToElement(this.childDocs[index], fromDoc); + this.hideIfNotPresented(index); + this.showAfterPresented(index); } } //The function that starts or resets presentaton functionally, depending on status flag. startOrResetPres = () => { - action(() => Doc.UserDoc().curPresentation = this.props.Document); + this.updateCurrentPresentation(); if (this.props.Document.presStatus) { this.resetPresentation(); } else { this.props.Document.presStatus = true; this.startPresentation(0); - this.gotoDocument(0, NumCast(this.props.Document._itemIndex)); + this.gotoDocument(0, this.currentIndex); } } @@ -292,22 +255,17 @@ export class PresBox extends React.Component { //The function that resets the presentation by removing every action done by it. It also //stops the presentaton. resetPresentation = () => { - action(() => Doc.UserDoc().curPresentation = this.props.Document); - this.childDocs.forEach((doc: Doc) => { - doc.opacity = 1; - doc.viewScale = 1; - }); + this.updateCurrentPresentation(); + this.childDocs.forEach(doc => doc.opacity = doc.viewScale = 1); this.props.Document._itemIndex = 0; this.props.Document.presStatus = false; - if (this.childDocs.length !== 0) { - DocumentManager.Instance.zoomIntoScale(this.childDocs[0], 1); - } + this.childDocs.length && DocumentManager.Instance.zoomIntoScale(this.childDocs[0], 1); } //The function that starts the presentation, also checking if actions should be applied //directly at start. startPresentation = (startIndex: number) => { - action(() => Doc.UserDoc().curPresentation = this.props.Document); + this.updateCurrentPresentation(); this.childDocs.map(doc => { if (doc.hideTillShownButton && this.childDocs.indexOf(doc) > startIndex) { doc.opacity = 0; @@ -337,14 +295,6 @@ export class PresBox extends React.Component { } })); - specificContextMenu = (e: React.MouseEvent): void => { - const funcs: ContextMenuProps[] = []; - funcs.push({ description: "Show as Slideshow", event: action(() => this.props.Document._viewType = CollectionViewType.Carousel), icon: "asterisk" }); - funcs.push({ description: "Show as Timeline", event: action(() => this.props.Document._viewType = CollectionViewType.Time), icon: "asterisk" }); - funcs.push({ description: "Show as List", event: action(() => { this.props.Document._viewType = CollectionViewType.Stacking; this.props.Document._pivotField = undefined; }), icon: "asterisk" }); - ContextMenu.Instance.addItem({ description: "Presentation Funcs...", subitems: funcs, icon: "asterisk" }); - } - /** * Initially every document starts with a viewScale 1, which means * that they will be displayed in a canvas with scale 1. @@ -353,18 +303,15 @@ export class PresBox extends React.Component { const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 46; docList.forEach((doc: Doc) => { doc.presBox = this.props.Document; - doc.presBoxKey = this.props.fieldKey; doc.collapsedHeight = hgt; - const curScale = NumCast(doc.viewScale, null); - if (curScale === undefined) { + if (!NumCast(doc.viewScale)) { doc.viewScale = 1; } }); } selectElement = (doc: Doc) => { - const index = DocListCast(this.props.Document[this.props.fieldKey]).indexOf(doc); - index !== -1 && this.gotoDocument(index, NumCast(this.props.Document._itemIndex)); + this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.props.Document._itemIndex)); } getTransform = () => { @@ -378,7 +325,7 @@ export class PresBox extends React.Component { viewChanged = action((e: React.ChangeEvent) => { //@ts-ignore this.props.Document._viewType = Number(e.target.selectedOptions[0].value); - this.props.Document._viewType === CollectionViewType.Stacking && (this.props.Document._pivotField = undefined); + this.props.Document._viewType === CollectionViewType.Stacking && (this.props.Document._pivotField = undefined); // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here this.updateMinimize(e, Number(this.props.Document._viewType)); }); @@ -386,10 +333,9 @@ export class PresBox extends React.Component { render() { const mode = NumCast(this.props.Document._viewType, CollectionViewType.Invalid); this.initializeScaleViews(this.childDocs, mode); - return
+ return
-