From bbdd26d89a231922cebd1560761ffffba97b9a40 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Thu, 12 Sep 2019 15:53:27 -0400 Subject: updated to master, will check self healing links now --- src/client/views/linking/LinkFollowBox.tsx | 20 +++++++++- src/client/views/linking/LinkMenuItem.tsx | 64 ++---------------------------- 2 files changed, 23 insertions(+), 61 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index d5ed01f53..603515d2a 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -18,6 +18,7 @@ import { DocServer } from "../../DocServer"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faTimes } from '@fortawesome/free-solid-svg-icons'; import { docs_v1 } from "googleapis"; +import { Utils } from "../../../Utils"; enum FollowModes { OPENTAB = "Open in Tab", @@ -245,15 +246,32 @@ export class LinkFollowBox extends React.Component { let proto = Doc.GetProto(LinkFollowBox.linkDoc); let targetContext = await Cast(proto.targetContext, Doc); let sourceContext = await Cast(proto.sourceContext, Doc); + let guid = StrCast(LinkFollowBox.linkDoc.guid); const shouldZoom = options ? options.shouldZoom : false; let dockingFunc = (document: Doc) => { this._addDocTab && this._addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; - if (LinkFollowBox.destinationDoc === LinkFollowBox.linkDoc.anchor2 && targetContext) { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext); } else if (LinkFollowBox.destinationDoc === LinkFollowBox.linkDoc.anchor1 && sourceContext) { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!)); + if (LinkFollowBox.sourceDoc) { + if (guid) { + console.log("guid"); + console.log('wegotthis', StrCast(LinkFollowBox.sourceDoc[Id])); // need to find if jumptodoc is the doc to follow, take id + jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); + LinkFollowBox.destinationDoc.guid = guid; + // process to follow: if guid, then we want to find the linkhref and use that to figure out whether we can find the links that correspond to the guid. + } else { + console.log("no guid"); // retroactively fixing old in-text links by adding guid + jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); + let newguid = Utils.GenerateGuid(); + LinkFollowBox.linkDoc.guid = newguid; + jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); + LinkFollowBox.destinationDoc.guid = newguid; + // if we find a link that doesnt match a guid but matches the OG link ref that correspond to the original anchor, then we move forward + } + } } else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, undefined, undefined, diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 0e951fc38..5631727ca 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -3,8 +3,8 @@ import { faArrowRight, faChevronDown, faChevronUp, faEdit, faEye, faTimes } from import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, observable } from 'mobx'; import { observer } from "mobx-react"; -import { Doc } from '../../../new_fields/Doc'; -import { Cast, StrCast } from '../../../new_fields/Types'; +import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; +import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; import { DragLinkAsDocument } from '../../util/DragManager'; import { LinkManager } from '../../util/LinkManager'; import { ContextMenu } from '../ContextMenu'; @@ -12,18 +12,12 @@ import { MainView } from '../MainView'; import { LinkFollowBox } from './LinkFollowBox'; import './LinkMenu.scss'; import React = require("react"); -<<<<<<< HEAD:src/client/views/nodes/LinkMenuItem.tsx -import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; -import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; -import { observable, action } from 'mobx'; -import { LinkManager } from '../../util/LinkManager'; -import { DragLinkAsDocument } from '../../util/DragManager'; import { CollectionDockingView } from '../collections/CollectionDockingView'; import { SelectionManager } from '../../util/SelectionManager'; import { Utils } from '../../../Utils'; import { Id } from '../../../new_fields/FieldSymbols'; -======= ->>>>>>> ec62b213439ab49134fa2dbbdf38a6d1ef5737cd:src/client/views/linking/LinkMenuItem.tsx +import { DocumentManager } from '../../util/DocumentManager'; +import { undoBatch } from '../../util/UndoManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -40,58 +34,8 @@ interface LinkMenuItemProps { export class LinkMenuItem extends React.Component { private _drag = React.createRef(); @observable private _showMore: boolean = false; -<<<<<<< HEAD:src/client/views/nodes/LinkMenuItem.tsx @action toggleShowMore() { this._showMore = !this._showMore; } - @undoBatch - onFollowLink = async (e: React.PointerEvent): Promise => { - e.stopPropagation(); - e.persist(); - let jumpToDoc = this.props.destinationDoc; - let pdfDoc = FieldValue(Cast(this.props.destinationDoc, Doc)); - if (pdfDoc) { - jumpToDoc = pdfDoc; - } - let proto = Doc.GetProto(this.props.linkDoc); - let targetContext = await Cast(proto.targetContext, Doc); - let sourceContext = await Cast(proto.sourceContext, Doc); - let guid = StrCast(this.props.linkDoc.guid); - let self = this; - - let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; - if (e.ctrlKey) { - dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined); - } - - if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, async document => dockingFunc(document), undefined, targetContext); - } - else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!)); - if (guid) { - console.log('wegotthis', StrCast(self.props.linkDoc.anchor2), jumpToDoc[Id]); - jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(this.props.linkDoc.anchor2)); - jumpToDoc.guid = guid; - } else { // retroactively fixing old in-text links by adding guid - console.log('wegotthis', self.props.linkDoc.anchor2, jumpToDoc[Id]); - jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(this.props.linkDoc.anchor2)); - let newguid = Utils.GenerateGuid(); - this.props.linkDoc.guid = newguid; - jumpToDoc.guid = newguid; - } - } - else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page))); - } - else { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, dockingFunc); - } -======= - @action toggleShowMore() { - this._showMore = !this._showMore; ->>>>>>> ec62b213439ab49134fa2dbbdf38a6d1ef5737cd:src/client/views/linking/LinkMenuItem.tsx - } - onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); this.props.showEditor(this.props.linkDoc); -- cgit v1.2.3-70-g09d2 From d6a31b7c55f91336b94dce59096da1bb2dc01d88 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Thu, 12 Sep 2019 16:03:18 -0400 Subject: will check guid statuses --- src/client/views/linking/LinkFollowBox.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 603515d2a..2ae5fcda0 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -255,15 +255,16 @@ export class LinkFollowBox extends React.Component { } else if (LinkFollowBox.destinationDoc === LinkFollowBox.linkDoc.anchor1 && sourceContext) { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!)); - if (LinkFollowBox.sourceDoc) { + if (LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc) { if (guid) { console.log("guid"); - console.log('wegotthis', StrCast(LinkFollowBox.sourceDoc[Id])); // need to find if jumptodoc is the doc to follow, take id + console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id])); // need to find if jumptodoc is the doc to follow, take id jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); LinkFollowBox.destinationDoc.guid = guid; // process to follow: if guid, then we want to find the linkhref and use that to figure out whether we can find the links that correspond to the guid. } else { console.log("no guid"); // retroactively fixing old in-text links by adding guid + console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id])); jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); let newguid = Utils.GenerateGuid(); LinkFollowBox.linkDoc.guid = newguid; -- cgit v1.2.3-70-g09d2 From 5f9aad860613575510400e07889f5dc3dda95de5 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Thu, 12 Sep 2019 16:04:26 -0400 Subject: will check guid statuses --- src/client/views/linking/LinkFollowBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 2ae5fcda0..009c3ac55 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -264,7 +264,7 @@ export class LinkFollowBox extends React.Component { // process to follow: if guid, then we want to find the linkhref and use that to figure out whether we can find the links that correspond to the guid. } else { console.log("no guid"); // retroactively fixing old in-text links by adding guid - console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id])); + console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id]), 'as well as the linkdoc id', LinkFollowBox.linkDoc[Id]); jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); let newguid = Utils.GenerateGuid(); LinkFollowBox.linkDoc.guid = newguid; -- cgit v1.2.3-70-g09d2 From 8c0643bab365b58af25101345b209bacc49a955b Mon Sep 17 00:00:00 2001 From: kimdahey Date: Thu, 12 Sep 2019 16:19:09 -0400 Subject: self healing links established (?!) --- src/client/views/linking/LinkFollowBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 009c3ac55..0a3c8a320 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -268,7 +268,7 @@ export class LinkFollowBox extends React.Component { jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); let newguid = Utils.GenerateGuid(); LinkFollowBox.linkDoc.guid = newguid; - jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); + jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.linkDoc[Id])); LinkFollowBox.destinationDoc.guid = newguid; // if we find a link that doesnt match a guid but matches the OG link ref that correspond to the original anchor, then we move forward } -- cgit v1.2.3-70-g09d2 From 827cee4d7ac4f1e761b141097d20671e7873bea8 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 15 Sep 2019 01:14:21 -0400 Subject: changed moveDocument to move the draggedDoc -- its up to the caller to add the droppedDoc if it wants to. cleaned up some old code related to passing dataDoc along with doc's to drag and other functinos --- src/client/util/DragManager.ts | 16 ++++----- src/client/views/DocumentDecorations.tsx | 20 +++++------ src/client/views/MainOverlayTextBox.tsx | 2 +- src/client/views/TemplateMenu.tsx | 2 +- .../views/collections/CollectionBaseView.tsx | 13 ++++--- .../views/collections/CollectionDockingView.tsx | 14 +++----- .../views/collections/CollectionSchemaCells.tsx | 3 +- .../views/collections/CollectionSchemaView.tsx | 2 +- .../CollectionStackingViewFieldColumn.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 8 +++-- src/client/views/collections/CollectionView.tsx | 3 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 40 +++++++--------------- src/client/views/linking/LinkMenuGroup.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 35 ++++++------------- src/client/views/nodes/DragBox.tsx | 2 +- src/client/views/pdf/Page.tsx | 2 +- src/client/views/search/SearchItem.tsx | 2 +- 18 files changed, 67 insertions(+), 103 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 4c9c9c17c..252accefa 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -32,7 +32,7 @@ export function SetupDrag( document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); let doc = await docFunc(); - var dragData = new DragManager.DocumentDragData([doc], [undefined]); + var dragData = new DragManager.DocumentDragData([doc]); dragData.dropAction = dropAction; dragData.moveDocument = moveFunc; dragData.options = options; @@ -76,7 +76,7 @@ export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: num if (draggeddoc) { let moddrag = await Cast(draggeddoc.annotationOn, Doc); let dragdocs = moddrag ? [moddrag] : [draggeddoc]; - let dragData = new DragManager.DocumentDragData(dragdocs, dragdocs); + let dragData = new DragManager.DocumentDragData(dragdocs); dragData.moveDocument = moveLinkedDocument; DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { handlers: { @@ -107,7 +107,7 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n if (doc) moddrag.push(doc); } let dragdocs = moddrag.length ? moddrag : draggedDocs; - let dragData = new DragManager.DocumentDragData(dragdocs, dragdocs); + let dragData = new DragManager.DocumentDragData(dragdocs); dragData.moveDocument = moveLinkedDocument; DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { handlers: { @@ -201,15 +201,13 @@ export namespace DragManager { export type MoveFunction = (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; export class DocumentDragData { - constructor(dragDoc: Doc[], dragDataDocs: (Doc | undefined)[]) { + constructor(dragDoc: Doc[]) { this.draggedDocuments = dragDoc; - this.draggedDataDocs = dragDataDocs; this.droppedDocuments = dragDoc; this.xOffset = 0; this.yOffset = 0; } draggedDocuments: Doc[]; - draggedDataDocs: (Doc | undefined)[]; droppedDocuments: Doc[]; xOffset: number; yOffset: number; @@ -253,7 +251,7 @@ export namespace DragManager { } export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], initialize?: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) { - let dragData = new DragManager.DocumentDragData([], [undefined]); + let dragData = new DragManager.DocumentDragData([]); runInAction(() => StartDragFunctions.map(func => func())); StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag : (dropData: { [id: string]: any }) => { @@ -363,8 +361,6 @@ export namespace DragManager { const docs: Doc[] = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnnotationDragData ? [dragData.dragDocument] : []; - const datadocs: (Doc | undefined)[] = - dragData instanceof DocumentDragData ? dragData.draggedDataDocs : dragData instanceof AnnotationDragData ? [dragData.dragDocument] : []; let dragElements = eles.map(ele => { const w = ele.offsetWidth, h = ele.offsetHeight; @@ -449,7 +445,7 @@ export namespace DragManager { pageY: e.pageY, preventDefault: emptyFunction, button: 0 - }, docs, datadocs); + }, docs); } //TODO: Why can't we use e.movementX and e.movementY? let moveX = e.pageX - lastX; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index ac103b2ea..ac1f51688 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -253,7 +253,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let dragDocView = SelectionManager.SelectedDocuments()[0]; const [left, top] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).inverse().transformPoint(0, 0); const [xoff, yoff] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).transformDirection(e.x - left, e.y - top); - let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document), SelectionManager.SelectedDocuments().map(dv => dv.props.DataDoc ? dv.props.DataDoc : dv.props.Document)); + let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document)); dragData.xOffset = xoff; dragData.yOffset = yoff; dragData.moveDocument = SelectionManager.SelectedDocuments()[0].props.moveDocument; @@ -358,15 +358,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (this._iconDoc && selectedDocs.length === 1 && this._removeIcon) { selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc); } - if (!this._removeIcon) { - if (selectedDocs.length === 1) { - this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].toggleMinimized()); - } else if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && - Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { - let docViews = SelectionManager.ViewsSortedVertically(); - let topDocView = docViews[0]; - topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); - } + if (!this._removeIcon && selectedDocs.length === 1) { // if you click on the top-left button when just 1 doc is selected, then collapse it. not sure why we don't do it for multiple selections + this.getIconDoc(selectedDocs[0]).then(async icon => { + let minimizedDoc = await Cast(selectedDocs[0].props.Document.minimizedDoc, Doc); + if (minimizedDoc) { + let scrpt = selectedDocs[0].props.ScreenToLocalTransform().scale(selectedDocs[0].props.ContentScaling()).inverse().transformPoint( + NumCast(minimizedDoc.x) - NumCast(selectedDocs[0].Document.x), NumCast(minimizedDoc.y) - NumCast(selectedDocs[0].Document.y)); + selectedDocs[0].collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs)); + } + }); } this._removeIcon = false; } diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 71fb2707d..cd8423a12 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -102,7 +102,7 @@ export class MainOverlayTextBox extends React.Component if ((e.movementX > 1 || e.movementY > 1) && FormattedTextBox.InputBoxOverlay) { document.removeEventListener("pointermove", this.textBoxMove); document.removeEventListener('pointerup', this.textBoxUp); - let dragData = new DragManager.DocumentDragData([FormattedTextBox.InputBoxOverlay.props.Document], [FormattedTextBox.InputBoxOverlay.props.DataDoc]); + let dragData = new DragManager.DocumentDragData([FormattedTextBox.InputBoxOverlay.props.Document]); const [left, top] = this._textXf().inverse().transformPoint(0, 0); dragData.xOffset = e.clientX - left; dragData.yOffset = e.clientY - top; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index af3fcaa24..d57a72dad 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -67,7 +67,7 @@ export class TemplateMenu extends React.Component { setTimeout(() => { let newDocView = DocumentManager.Instance.getDocumentView(topDoc); if (newDocView) { - let de = new DragManager.DocumentDragData([topDoc], [undefined]); + let de = new DragManager.DocumentDragData([topDoc]); de.moveDocument = topDocView.props.moveDocument; let xf = newDocView.ContentDiv!.getBoundingClientRect(); DragManager.StartDocumentDrag([newDocView.ContentDiv!], de, ex, ey, { diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index b7036b3ff..a54718e9e 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -141,17 +141,16 @@ export class CollectionBaseView extends React.Component { return false; } + // this is called with the document that was dragged and the collection to move it into. + // if the target collection is the same as this collection, then the move will be allowed. + // otherwise, the document being moved must be able to be removed from its container before + // moving it into the target. @action.bound moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean { - let self = this; - let targetDataDoc = this.props.Document; - if (Doc.AreProtosEqual(targetDataDoc, targetCollection)) { + if (Doc.AreProtosEqual(this.props.Document, targetCollection)) { return true; } - if (this.removeDocument(doc)) { - return addDocument(doc); - } - return false; + return this.removeDocument(doc) ? addDocument(doc) : false; } render() { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 166fa0811..bf55dba31 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -66,15 +66,15 @@ export class CollectionDockingView extends React.Component { - CollectionDockingView.makeDocumentConfig(doc, dragDataDocs[i]); + CollectionDockingView.makeDocumentConfig(doc, undefined); }) }; } @@ -84,12 +84,6 @@ export class CollectionDockingView extends React.Component - // this.AddRightSplit(dragDoc, dragDataDocs[i], true).contentItems[0].tab._dragListener. - // onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 })); } @action @@ -412,7 +406,7 @@ export class CollectionDockingView extends React.Component { e.preventDefault(); e.stopPropagation(); - DragManager.StartDocumentDrag([dragSpan], new DragManager.DocumentDragData([doc], [dataDoc]), e.clientX, e.clientY, { + DragManager.StartDocumentDrag([dragSpan], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY, { handlers: { dragComplete: emptyFunction }, hideSource: false }); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 17a3f4f7c..3452e8702 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -172,7 +172,8 @@ export class CollectionSchemaCell extends React.Component { let onItemDown = (e: React.PointerEvent) => { if (fieldIsDoc) { SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, - this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); + this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, + this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); } }; let onPointerEnter = (e: React.PointerEvent): void => { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 1a84f94c8..25d3bd128 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -14,7 +14,7 @@ import { listSpec } from "../../../new_fields/Schema"; import { Docs, DocumentOptions } from "../../documents/Documents"; import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { Gateway } from "../../northstar/manager/Gateway"; -import { SetupDrag, DragManager } from "../../util/DragManager"; +import { DragManager } from "../../util/DragManager"; import { CompileScript, ts, Transformer } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; import { COLLECTION_BORDER_WIDTH } from '../../views/globalCssVariables.scss'; diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 185bec7a2..34f2652ff 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -183,7 +183,7 @@ export class CollectionStackingViewFieldColumn extends React.Component(schemaCtor: (doc: Doc) => T) { if (de.data.dropAction || de.data.userDropAction) { added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } else if (de.data.moveDocument) { - let movedDocs = de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments; - added = movedDocs.reduce((added: boolean, d) => - de.data.moveDocument(d, this.props.Document, this.props.addDocument) || added, false); + let movedDocs = de.data.draggedDocuments;// de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments; + // note that it's possible the drag function might create a drop document that's not the same as the + // original dragged document. So we explicitly call addDocument() with a droppedDocument and + added = movedDocs.reduce((added: boolean, d, i) => + de.data.moveDocument(d, this.props.Document, (doc: Doc) => this.props.addDocument(de.data.droppedDocuments[i])) || added, false); } else { added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index bce4eb427..548f663ec 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -95,8 +95,9 @@ export class CollectionView extends React.Component { } subItems.push({ description: "Schema", event: () => this.props.Document.viewType = CollectionViewType.Schema, icon: "th-list" }); subItems.push({ description: "Treeview", event: () => this.props.Document.viewType = CollectionViewType.Tree, icon: "tree" }); + subItems.push({ description: "Stacking", event: () => this.props.Document.viewType = CollectionViewType.Stacking, icon: "ellipsis-v" }); subItems.push({ - description: "Stacking", event: () => { + description: "Stacking (AutoHeight)", event: () => { this.props.Document.viewType = CollectionViewType.Stacking; this.props.Document.autoHeight = true }, icon: "ellipsis-v" diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ad91eb007..f2ca645a7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -381,7 +381,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { SelectionManager.DeselectAll(); prevSelected.map(dv => SelectionManager.SelectDoc(dv, true)); - let de = new DragManager.DocumentDragData(eles, eles.map(d => undefined)); + let de = new DragManager.DocumentDragData(eles); de.moveDocument = this.props.moveDocument; const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0); const [xoff, yoff] = this.getTransform().transformDirection(e.x - left, e.y - top); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index cc5e887b2..5cab6f8e0 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -315,7 +315,7 @@ export class MarqueeView extends React.Component dataExtensionField.ink = inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined; this.marqueeInkDelete(inkData); - if (e.key === "s") { + if (e.key === "s" || e.key === "S") { selected.map(d => { this.props.removeDocument(d); d.x = NumCast(d.x) - bounds.left - bounds.width / 2; @@ -324,35 +324,19 @@ export class MarqueeView extends React.Component return d; }); newCollection.chromeStatus = "disabled"; - let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); - newCollection.proto!.summaryDoc = summary; - selected = [newCollection]; - newCollection.x = bounds.left + bounds.width; - summary.proto!.subBulletDocs = new List(selected); - let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" }); - container.viewType = CollectionViewType.Stacking; - container.autoHeight = true; - this.props.addLiveTextDocument(container); - // }); - } else if (e.key === "S") { - selected.map(d => { - this.props.removeDocument(d); - d.x = NumCast(d.x) - bounds.left - bounds.width / 2; - d.y = NumCast(d.y) - bounds.top - bounds.height / 2; - d.page = -1; - return d; - }); - newCollection.chromeStatus = "disabled"; - let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); + let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, autoHeight: true, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); + summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" newCollection.proto!.summaryDoc = summary; - selected = [newCollection]; newCollection.x = bounds.left + bounds.width; - //this.props.addDocument(newCollection, false); - summary.proto!.summarizedDocs = new List(selected); - summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" - summary.autoHeight = true; - - this.props.addLiveTextDocument(summary); + if (e.key === "s") { // summary is wrapped in an expand/collapse container that also contains the summarized documents in a free form view. + let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" }); + container.viewType = CollectionViewType.Stacking; + container.autoHeight = true; + this.props.addLiveTextDocument(container); + } else if (e.key === "S") { // the summary stands alone, but is linked to a collection of the summarized documents - set the OnCLick behavior to link follow to access them + summary.proto!.summarizedDocs = new List([newCollection]); + this.props.addLiveTextDocument(summary); + } } else { this.props.addDocument(newCollection, false); diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index b6a24b0c8..d711ac284 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -57,7 +57,7 @@ export class LinkMenuGroup extends React.Component { let opp = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); if (opp) return opp; }) as Doc[]; - let dragData = new DragManager.DocumentDragData(draggedDocs, draggedDocs.map(d => undefined)); + let dragData = new DragManager.DocumentDragData(draggedDocs); DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, { handlers: { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e95f484a4..17bf02448 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -138,7 +138,6 @@ export class DocumentView extends DocComponent(Docu private _downY: number = 0; private _lastTap: number = 0; private _doubleTap = false; - private _hitExpander = false; private _hitTemplateDrag = false; private _mainCont = React.createRef(); private _dropDisposer?: DragManager.DragDropDisposer; @@ -221,20 +220,19 @@ export class DocumentView extends DocComponent(Docu } get dataDoc() { - if (this.props.DataDoc === undefined && (this.props.Document.layout instanceof Doc || this.props.Document instanceof Promise)) { - // if there is no dataDoc (ie, we're not rendering a temlplate layout), but this document - // has a template layout document, then we will render the template layout but use - // this document as the data document for the layout. - return this.props.Document; - } + // bcz: don't think we need this, but left it in in case strange behavior pops up. DocumentContentsView has this functionality + // if (this.props.DataDoc === undefined && (this.props.Document.layout instanceof Doc || this.props.Document instanceof Promise)) { + // // if there is no dataDoc (ie, we're not rendering a temlplate layout), but this document + // // has a template layout document, then we will render the template layout but use + // // this document as the data document for the layout. + // return this.props.Document; + // } return this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined; } - startDragging(x: number, y: number, dropAction: dropActionType, dragSubBullets: boolean, applyAsTemplate?: boolean) { + startDragging(x: number, y: number, dropAction: dropActionType, applyAsTemplate?: boolean) { if (this._mainCont.current) { - let allConnected = [this.props.Document, ...(dragSubBullets ? DocListCast(this.props.Document.subBulletDocs) : [])]; - let alldataConnected = [this.dataDoc, ...(dragSubBullets ? DocListCast(this.props.Document.subBulletDocs) : [])]; const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0); - let dragData = new DragManager.DocumentDragData(allConnected, alldataConnected); + let dragData = new DragManager.DocumentDragData([this.props.Document]); const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); dragData.dropAction = dropAction; dragData.xOffset = xoff; @@ -249,14 +247,6 @@ export class DocumentView extends DocComponent(Docu }); } } - toggleMinimized = async () => { - let minimizedDoc = await Cast(this.props.Document.minimizedDoc, Doc); - if (minimizedDoc) { - let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint( - NumCast(minimizedDoc.x) - NumCast(this.Document.x), NumCast(minimizedDoc.y) - NumCast(this.Document.y)); - this.collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs)); - } - } static _undoBatch?: UndoManager.Batch = undefined; @action @@ -315,15 +305,13 @@ export class DocumentView extends DocComponent(Docu SelectionManager.SelectDoc(this, e.ctrlKey); let isExpander = (e.target as any).id === "isExpander"; if (BoolCast(this.props.Document.isButton) || this.props.Document.type === DocumentType.BUTTON || isExpander) { - let subBulletDocs = await DocListCastAsync(this.props.Document.subBulletDocs); let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs); let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs); let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document); let expandedDocs: Doc[] = []; - expandedDocs = subBulletDocs ? [...subBulletDocs, ...expandedDocs] : expandedDocs; expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs; expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs; - // let expandedDocs = [...(subBulletDocs ? subBulletDocs : []), ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),]; + // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),]; if (expandedDocs.length) { // bcz: need a better way to associate behaviors with click events on widget-documents SelectionManager.DeselectAll(); let maxLocation = StrCast(this.props.Document.maximizeLocation, "inPlace"); @@ -394,7 +382,6 @@ export class DocumentView extends DocComponent(Docu if (e.nativeEvent.cancelBubble) return; this._downX = e.clientX; this._downY = e.clientY; - this._hitExpander = DocListCast(this.props.Document.subBulletDocs).length > 0; this._hitTemplateDrag = false; for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) { if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") { @@ -416,7 +403,7 @@ export class DocumentView extends DocComponent(Docu if (!e.altKey && !this.topMost && e.buttons === 1 && !BoolCast(this.props.Document.lockedPosition)) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitExpander, this._hitTemplateDrag); + this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); } } e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx index 1f2c88086..067d47de4 100644 --- a/src/client/views/nodes/DragBox.tsx +++ b/src/client/views/nodes/DragBox.tsx @@ -55,7 +55,7 @@ export class DragBox extends DocComponent(DragDocu let doc = res !== undefined && res.success ? res.result as Doc : Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); - doc && DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc], [undefined]), e.clientX, e.clientY); + doc && DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY); } e.stopPropagation(); e.preventDefault(); diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index 856e883e7..533247170 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -137,7 +137,7 @@ export default class Page extends React.Component { view.nativeWidth = this.props.Document.nativeWidth; view.startY = marquee.top + this.props.getScrollFromPage(this.props.page); view.width = this.props.Document[WidthSym](); - DragManager.StartDocumentDrag([], new DragManager.DocumentDragData([view], [undefined]), 0, 0); + DragManager.StartDocumentDrag([], new DragManager.DocumentDragData([view]), 0, 0); } @action diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index cd3dd912c..510672788 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -270,7 +270,7 @@ export class SearchItem extends React.Component { onPointerDown = (e: React.PointerEvent) => { e.stopPropagation(); const doc = Doc.IsPrototype(this.props.doc) ? Doc.MakeDelegate(this.props.doc) : this.props.doc; - DragManager.StartDocumentDrag([e.currentTarget], new DragManager.DocumentDragData([doc], []), e.clientX, e.clientY, { + DragManager.StartDocumentDrag([e.currentTarget], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY, { handlers: { dragComplete: emptyFunction }, hideSource: false, }); -- cgit v1.2.3-70-g09d2 From c453ef0f405125aa0660fb469e2488a75d8dfe54 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Sun, 15 Sep 2019 16:08:21 -0400 Subject: self heal --- src/client/views/linking/LinkFollowBox.tsx | 8 ++++---- src/client/views/nodes/FormattedTextBox.tsx | 11 +++-------- 2 files changed, 7 insertions(+), 12 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 0a3c8a320..3b36bf854 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -257,14 +257,14 @@ export class LinkFollowBox extends React.Component { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!)); if (LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc) { if (guid) { - console.log("guid"); - console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id])); // need to find if jumptodoc is the doc to follow, take id + // console.log("guid"); + // console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id])); // need to find if jumptodoc is the doc to follow, take id jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); LinkFollowBox.destinationDoc.guid = guid; // process to follow: if guid, then we want to find the linkhref and use that to figure out whether we can find the links that correspond to the guid. } else { - console.log("no guid"); // retroactively fixing old in-text links by adding guid - console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id]), 'as well as the linkdoc id', LinkFollowBox.linkDoc[Id]); + // console.log("no guid"); // retroactively fixing old in-text links by adding guid + // console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id]), 'as well as the linkdoc id', LinkFollowBox.linkDoc[Id]); jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); let newguid = Utils.GenerateGuid(); LinkFollowBox.linkDoc.guid = newguid; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index ede0facd8..d9a781c9c 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -141,7 +141,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this.props.Document.guid = undefined; this.props.Document.linkHref = undefined; - console.log('formattextbox', this.props.Document[Id]); reaction( () => StrCast(this.props.Document.guid), async (guid) => { @@ -159,9 +158,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } else { tr = editor.state.tr.setSelection(TextSelection.near(editor.state.doc.resolve(ret.start))); } + editor.focus(); editor.dispatch(tr.scrollIntoView()); - editor.dispatch(tr.scrollIntoView()); // bcz: sometimes selection doesn't fully scroll into view on smaller text boxes <5 lines visibility -- hopefully avoidable by ppl just not using small boxes...? + // editor.dispatch(tr.scrollIntoView()); // bcz: sometimes selection doesn't fully scroll into view on smaller text boxes <5 lines visibility -- hopefully avoidable by ppl just not using small boxes...? + this.props.Document.guid = undefined; this.props.Document.linkHref = undefined; } @@ -192,7 +193,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe marks[linkIndex].attrs.guid = guid; return node; } - console.log('href was and is ', href, marks[linkIndex].attrs.href); } return undefined; } @@ -815,11 +815,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (jumpToDoc) { if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { - // if !guid, then generate guid and apply to full doc - if (!guid) { - console.log('making new guid!'); // hehheehhehehe - linkDoc.guid = Utils.GenerateGuid(); - } DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((jumpToDoc === linkDoc.anchor2 ? linkDoc.anchor2Page : linkDoc.anchor1Page))); return; } -- cgit v1.2.3-70-g09d2 From b4520766b3032ba8b3886197fa46de0cdb1cea50 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Sun, 15 Sep 2019 16:28:29 -0400 Subject: scroll into view --- src/client/views/linking/LinkFollowBox.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 3b36bf854..6e20cf8c1 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -263,7 +263,7 @@ export class LinkFollowBox extends React.Component { LinkFollowBox.destinationDoc.guid = guid; // process to follow: if guid, then we want to find the linkhref and use that to figure out whether we can find the links that correspond to the guid. } else { - // console.log("no guid"); // retroactively fixing old in-text links by adding guid + console.log("no guid"); // retroactively fixing old in-text links by adding guid // console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id]), 'as well as the linkdoc id', LinkFollowBox.linkDoc[Id]); jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); let newguid = Utils.GenerateGuid(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index d9a781c9c..e28d42be1 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -154,14 +154,16 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (ret.frag.size > 2) { let tr; if (ret.frag.firstChild) { - tr = editor.state.tr.setSelection(TextSelection.between(editor.state.doc.resolve(ret.start + 2), editor.state.doc.resolve(ret.start + ret.frag.firstChild.nodeSize))); + let between = TextSelection.between(editor.state.doc.resolve(ret.start + 2), editor.state.doc.resolve(ret.start + ret.frag.firstChild.nodeSize)); + tr = editor.state.tr.setSelection(between); } else { - tr = editor.state.tr.setSelection(TextSelection.near(editor.state.doc.resolve(ret.start))); + let near = TextSelection.near(editor.state.doc.resolve(ret.start)); + tr = editor.state.tr.setSelection(near); } editor.focus(); editor.dispatch(tr.scrollIntoView()); - // editor.dispatch(tr.scrollIntoView()); // bcz: sometimes selection doesn't fully scroll into view on smaller text boxes <5 lines visibility -- hopefully avoidable by ppl just not using small boxes...? + editor.dispatch(tr.scrollIntoView()); // bcz: sometimes selection doesn't fully scroll into view on smaller text boxes <5 lines visibility -- hopefully avoidable by ppl just not using small boxes...? this.props.Document.guid = undefined; this.props.Document.linkHref = undefined; -- cgit v1.2.3-70-g09d2 From 3f38401ee477bd37ad95e5170783ca406437e195 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Sun, 15 Sep 2019 16:41:54 -0400 Subject: cleaning code --- src/client/views/linking/LinkFollowBox.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 6e20cf8c1..66661d178 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -257,20 +257,13 @@ export class LinkFollowBox extends React.Component { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!)); if (LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc) { if (guid) { - // console.log("guid"); - // console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id])); // need to find if jumptodoc is the doc to follow, take id - jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); LinkFollowBox.destinationDoc.guid = guid; - // process to follow: if guid, then we want to find the linkhref and use that to figure out whether we can find the links that correspond to the guid. } else { - console.log("no guid"); // retroactively fixing old in-text links by adding guid - // console.log('source and dest ids respectively are', StrCast(LinkFollowBox.sourceDoc[Id]), StrCast(LinkFollowBox.destinationDoc[Id]), 'as well as the linkdoc id', LinkFollowBox.linkDoc[Id]); jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); + // jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.linkDoc[Id])); let newguid = Utils.GenerateGuid(); LinkFollowBox.linkDoc.guid = newguid; - jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.linkDoc[Id])); LinkFollowBox.destinationDoc.guid = newguid; - // if we find a link that doesnt match a guid but matches the OG link ref that correspond to the original anchor, then we move forward } } } -- cgit v1.2.3-70-g09d2 From 9e2343a94a70559f50694da3687f5c297dd4eca0 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Sun, 15 Sep 2019 16:45:47 -0400 Subject: cleaning code --- src/client/views/linking/LinkFollowBox.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 66661d178..9c65bbcf9 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -259,8 +259,7 @@ export class LinkFollowBox extends React.Component { if (guid) { LinkFollowBox.destinationDoc.guid = guid; } else { - jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.sourceDoc[Id])); - // jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.linkDoc[Id])); + jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.linkDoc[Id])); let newguid = Utils.GenerateGuid(); LinkFollowBox.linkDoc.guid = newguid; LinkFollowBox.destinationDoc.guid = newguid; -- cgit v1.2.3-70-g09d2 From 4c63c4cc4503faa511ef141984274e19c00c41ba Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Sun, 15 Sep 2019 16:54:14 -0400 Subject: working follow link / self heal --- src/client/views/linking/LinkMenuItem.tsx | 10 ++-------- src/client/views/nodes/FormattedTextBox.tsx | 4 +--- 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 5631727ca..0cdc3e42f 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -3,8 +3,8 @@ import { faArrowRight, faChevronDown, faChevronUp, faEdit, faEye, faTimes } from import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, observable } from 'mobx'; import { observer } from "mobx-react"; -import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; -import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; +import { Doc } from '../../../new_fields/Doc'; +import { StrCast, Cast } from '../../../new_fields/Types'; import { DragLinkAsDocument } from '../../util/DragManager'; import { LinkManager } from '../../util/LinkManager'; import { ContextMenu } from '../ContextMenu'; @@ -12,12 +12,6 @@ import { MainView } from '../MainView'; import { LinkFollowBox } from './LinkFollowBox'; import './LinkMenu.scss'; import React = require("react"); -import { CollectionDockingView } from '../collections/CollectionDockingView'; -import { SelectionManager } from '../../util/SelectionManager'; -import { Utils } from '../../../Utils'; -import { Id } from '../../../new_fields/FieldSymbols'; -import { DocumentManager } from '../../util/DocumentManager'; -import { undoBatch } from '../../util/UndoManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index e28d42be1..c292f12ad 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -119,7 +119,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe @undoBatch public setFontColor(color: string) { - this._editorView!.state.storedMarks + this._editorView!.state.storedMarks; if (this._editorView!.state.selection.from === this._editorView!.state.selection.to) return false; if (this._editorView!.state.selection.to - this._editorView!.state.selection.from > this._editorView!.state.doc.nodeSize - 3) { this.props.Document.color = color; @@ -136,8 +136,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe DragManager.StartDragFunctions.push(() => FormattedTextBox.InputBoxOverlay = undefined); } - document.addEventListener("paste", this.paste); - this.props.Document.guid = undefined; this.props.Document.linkHref = undefined; -- cgit v1.2.3-70-g09d2 From 147c208a9a1196d2ded540e28dc3d7f26d5ba0a9 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Sun, 15 Sep 2019 16:56:54 -0400 Subject: finished --- src/client/views/linking/LinkMenuItem.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 0cdc3e42f..d0c0d184d 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -4,7 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import { Doc } from '../../../new_fields/Doc'; -import { StrCast, Cast } from '../../../new_fields/Types'; +import { Cast, StrCast } from '../../../new_fields/Types'; import { DragLinkAsDocument } from '../../util/DragManager'; import { LinkManager } from '../../util/LinkManager'; import { ContextMenu } from '../ContextMenu'; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index c292f12ad..9abc7b329 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -661,7 +661,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let frag = addMarkToFrag(slice.content, (node: Node) => addLinkMark(node, StrCast(doc.title))); slice = new Slice(frag, slice.openStart, slice.openEnd); var tr = view.state.tr.replaceSelection(slice); - view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); } }); -- cgit v1.2.3-70-g09d2 From 5b09512cf4aa2319e498a233c16dba93ae83fbda Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 17 Sep 2019 11:26:54 -0400 Subject: lots of code cleanup in collectionFreeFormDocumentView and DocumentView --- src/Utils.ts | 5 + src/client/views/DocumentDecorations.tsx | 3 +- src/client/views/GlobalKeyHandler.ts | 2 +- .../views/collections/CollectionDockingView.tsx | 5 + .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../document_templates/image_card/ImageCard.tsx | 3 - src/client/views/linking/LinkFollowBox.tsx | 2 - .../nodes/CollectionFreeFormDocumentView.scss | 5 + .../views/nodes/CollectionFreeFormDocumentView.tsx | 48 ++-- src/client/views/nodes/DocumentView.scss | 42 +++ src/client/views/nodes/DocumentView.tsx | 286 ++++++++++----------- src/client/views/nodes/ImageBox.tsx | 5 +- 12 files changed, 215 insertions(+), 193 deletions(-) create mode 100644 src/client/views/nodes/CollectionFreeFormDocumentView.scss (limited to 'src/client/views/linking') diff --git a/src/Utils.ts b/src/Utils.ts index 3921a49c3..415023ac4 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -37,6 +37,7 @@ export class Utils { public static prepend(extension: string): string { return window.location.origin + extension; } + public static CorsProxy(url: string): string { return this.prepend(RouteStore.corsProxy + "/") + encodeURIComponent(url); } @@ -239,6 +240,10 @@ export function timenow() { return now.toLocaleDateString() + ' ' + h + ':' + m + ' ' + ampm; } +export function percent2frac(percent: string) { + return Number(percent.substr(0, percent.length - 1)) / 100; +} + export function numberRange(num: number) { return Array.from(Array(num)).map((v, i) => i); } export function returnTrue() { return true; } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 240abaf6b..7829bd7f1 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -16,7 +16,7 @@ import { undoBatch, UndoManager } from "../util/UndoManager"; import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss"; import { CollectionView } from "./collections/CollectionView"; import './DocumentDecorations.scss'; -import { DocumentView, PositionDocument } from "./nodes/DocumentView"; +import { DocumentView } from "./nodes/DocumentView"; import { FieldView } from "./nodes/FieldView"; import { FormattedTextBox, GoogleRef } from "./nodes/FormattedTextBox"; import { IconBox } from "./nodes/IconBox"; @@ -34,6 +34,7 @@ import { ObjectField } from '../../new_fields/ObjectField'; import { DocServer } from '../DocServer'; import { CompileScript } from '../util/Scripting'; import { ComputedField } from '../../new_fields/ScriptField'; +import { PositionDocument } from './nodes/CollectionFreeFormDocumentView'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index f9ee22f61..ba125d6e5 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -166,7 +166,7 @@ export default class KeyManager { break; case "o": let target = SelectionManager.SelectedDocuments()[0]; - target && target.fullScreenClicked(); + target && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(target) break; case "r": preventDefault = false; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index bf55dba31..a350cfcc5 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -86,6 +86,7 @@ export class CollectionDockingView extends React.Component { @@ -169,6 +171,7 @@ export class CollectionDockingView extends React.Component { let docs = Cast(this.props.Document.data, listSpec(Doc)); @@ -207,6 +210,8 @@ export class CollectionDockingView extends React.Component { Doc.GetProto(document).lastOpened = new DateField; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index e2d9bbb33..f32843d98 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -862,7 +862,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let layoutItems: ContextMenuProps[] = []; if (this.childDocs.some(d => BoolCast(d.isTemplate))) { - layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); + layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); } layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" }); layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: async () => this.Document.fitToBox = !this.fitToBox, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" }); diff --git a/src/client/views/document_templates/image_card/ImageCard.tsx b/src/client/views/document_templates/image_card/ImageCard.tsx index 9931515f3..868afc423 100644 --- a/src/client/views/document_templates/image_card/ImageCard.tsx +++ b/src/client/views/document_templates/image_card/ImageCard.tsx @@ -1,8 +1,5 @@ import * as React from 'react'; -import { DocComponent } from '../../DocComponent'; import { FieldViewProps } from '../../nodes/FieldView'; -import { createSchema, makeInterface } from '../../../../new_fields/Schema'; -import { createInterface } from 'readline'; import { ImageBox } from '../../nodes/ImageBox'; export default class ImageCard extends React.Component { diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index f8807641b..b1c6c367f 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -172,7 +172,6 @@ export class LinkFollowBox extends React.Component { if (LinkFollowBox.destinationDoc) { let view: DocumentView | null = DocumentManager.Instance.getDocumentView(LinkFollowBox.destinationDoc); view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); - SelectionManager.DeselectAll(); } } @@ -188,7 +187,6 @@ export class LinkFollowBox extends React.Component { let view = DocumentManager.Instance.getDocumentView(options.context); view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); this.highlightDoc(); - SelectionManager.DeselectAll(); } } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.scss b/src/client/views/nodes/CollectionFreeFormDocumentView.scss new file mode 100644 index 000000000..c0d9e1267 --- /dev/null +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.scss @@ -0,0 +1,5 @@ +.collectionFreeFormDocumentView-container { + transform-origin: left top; + position: absolute; + background-color: transparent; +} \ No newline at end of file diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 865eb27d5..9f0bd736d 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,11 +1,12 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; import { createSchema, makeInterface } from "../../../new_fields/Schema"; -import { BoolCast, FieldValue, NumCast, StrCast, Cast } from "../../../new_fields/Types"; +import { FieldValue, NumCast, StrCast, Cast } from "../../../new_fields/Types"; import { Transform } from "../../util/Transform"; import { DocComponent } from "../DocComponent"; -import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView"; -import "./DocumentView.scss"; +import { percent2frac } from "../../../Utils" +import { DocumentView, DocumentViewProps, documentSchema } from "./DocumentView"; +import "./CollectionFreeFormDocumentView.scss"; import React = require("react"); import { Doc } from "../../../new_fields/Doc"; import { random } from "animejs"; @@ -17,30 +18,31 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { height?: number; jitterRotation: number; } - -const schema = createSchema({ +const positionSchema = createSchema({ zIndex: "number", + x: "number", + y: "number", + z: "number", }); -//TODO Types: The import order is wrong, so positionSchema is undefined -type FreeformDocument = makeInterface<[typeof schema, typeof positionSchema]>; -const FreeformDocument = makeInterface(schema, positionSchema); +export type PositionDocument = makeInterface<[typeof documentSchema, typeof positionSchema]>; +export const PositionDocument = makeInterface(documentSchema, positionSchema); @observer -export class CollectionFreeFormDocumentView extends DocComponent(FreeformDocument) { +export class CollectionFreeFormDocumentView extends DocComponent(PositionDocument) { @computed get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) rotate(${random(-1, 1) * this.props.jitterRotation}deg)`; } @computed get X() { return this.renderScriptDim ? this.renderScriptDim.x : this.props.x !== undefined ? this.props.x : this.Document.x || 0; } @computed get Y() { return this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.Document.y || 0; } - @computed get width(): number { return BoolCast(this.props.Document.willMaximize) ? 0 : this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.Document.width || 0; } - @computed get height(): number { return BoolCast(this.props.Document.willMaximize) ? 0 : this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.Document.height || 0; } - @computed get nativeWidth(): number { return FieldValue(this.Document.nativeWidth, 0); } - @computed get nativeHeight(): number { return FieldValue(this.Document.nativeHeight, 0); } - @computed get scaleToOverridingWidth() { return this.width / NumCast(this.props.Document.width, this.width); } + @computed get width() { return this.Document.willMaximize ? 0 : this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.Document.width || 0; } + @computed get height() { return this.Document.willMaximize ? 0 : this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.Document.height || 0; } + @computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); } + @computed get nativeHeight() { return FieldValue(this.Document.nativeHeight, 0); } + @computed get scaleToOverridingWidth() { return this.width / FieldValue(this.Document.width, this.width); } @computed get renderScriptDim() { if (this.Document.renderScript) { - let someView = Cast(this.Document.someView, Doc); - let minimap = Cast(this.Document.minimap, Doc); + let someView = Cast(this.props.Document.someView, Doc); + let minimap = Cast(this.props.Document.minimap, Doc); if (someView instanceof Doc && minimap instanceof Doc) { let x = (NumCast(someView.panX) - NumCast(someView.width) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitX) - NumCast(minimap.fitW) / 2)) / NumCast(minimap.fitW) * NumCast(minimap.width) - NumCast(minimap.width) / 2; let y = (NumCast(someView.panY) - NumCast(someView.height) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitY) - NumCast(minimap.fitH) / 2)) / NumCast(minimap.fitH) * NumCast(minimap.height) - NumCast(minimap.height) / 2; @@ -52,7 +54,7 @@ export class CollectionFreeFormDocumentView extends DocComponent this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? this.width / this.nativeWidth : 1; + contentScaling = () => this.nativeWidth > 0 && !this.props.Document.ignoreAspect ? this.width / this.nativeWidth : 1; panelWidth = () => this.props.PanelWidth(); panelHeight = () => this.props.PanelHeight(); getTransform = (): Transform => this.props.ScreenToLocalTransform() @@ -74,15 +76,12 @@ export class CollectionFreeFormDocumentView extends DocComponent { - let ruleProvider = this.props.ruleProvider; - let ruleRounding = ruleProvider ? StrCast(Doc.GetProto(ruleProvider)["ruleRounding_" + NumCast(this.props.Document.heading)]) : undefined; - let br = StrCast(this.layoutDoc.layout instanceof Doc ? this.layoutDoc.layout.borderRounding : this.props.Document.borderRounding); + let ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; + let br = StrCast(((this.layoutDoc.layout as Doc) || this.Document).borderRounding); br = !br && ruleRounding ? ruleRounding : br; if (br.endsWith("%")) { - let percent = Number(br.substr(0, br.length - 1)) / 100; let nativeDim = Math.min(NumCast(this.layoutDoc.nativeWidth), NumCast(this.layoutDoc.nativeHeight)); - let minDim = percent * (nativeDim ? nativeDim : Math.min(this.props.PanelWidth(), this.props.PanelHeight())); - return minDim; + return percent2frac(br) * (nativeDim ? nativeDim : Math.min(this.props.PanelWidth(), this.props.PanelHeight())); } return undefined; } @@ -103,9 +102,6 @@ export class CollectionFreeFormDocumentView extends DocComponent number; } -const schema = createSchema({ - layout: "string", +export const documentSchema = createSchema({ + layout: "string", // should also allow Doc but that can't be expressed in the schema + title: "string", nativeWidth: "number", nativeHeight: "number", backgroundColor: "string", opacity: "number", hidden: "boolean", onClick: ScriptField, -}); - -export const positionSchema = createSchema({ - nativeWidth: "number", - nativeHeight: "number", + willMaximize: "boolean", + ignoreAspect: "boolean", + autoHeight: "boolean", + isTemplate: "boolean", + isButton: "boolean", + isBackground: "boolean", + ignoreClick: "boolean", + type: "string", + maximizeLocation: "string", + lockedPosition: "boolean", + excludeFromLibrary: "boolean", width: "number", height: "number", - x: "number", - y: "number", - z: "number", + borderRounding: "string", + fitToBox: "boolean", + searchFields: "string", + heading: "number", + showCaption: "string", + showTitle: "string" }); -export type PositionDocument = makeInterface<[typeof positionSchema]>; -export const PositionDocument = makeInterface(positionSchema); - -type Document = makeInterface<[typeof schema]>; -const Document = makeInterface(schema); +type Document = makeInterface<[typeof documentSchema]>; +const Document = makeInterface(documentSchema); @observer export class DocumentView extends DocComponent(Document) { @@ -259,7 +266,7 @@ export class DocumentView extends DocComponent(Docu if (e.nativeEvent.cancelBubble) return; // || SelectionManager.IsSelected(this)) -- bcz: needed because EditableView may stopPropagation which won't apparently stop this event from firing. if (this.onClickHandler && this.onClickHandler.script) { e.stopPropagation(); - this.onClickHandler.script.run({ this: this.props.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document }); + this.onClickHandler.script.run({ this: this.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document }); e.preventDefault(); return; } @@ -268,23 +275,18 @@ export class DocumentView extends DocComponent(Docu if (this._doubleTap && this.props.renderDepth) { e.stopPropagation(); let fullScreenAlias = Doc.MakeAlias(this.props.Document); - fullScreenAlias.templates = new List(); Doc.UseDetailLayout(fullScreenAlias); - fullScreenAlias.showCaption = true; + fullScreenAlias.showCaption = "caption"; this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab"); SelectionManager.DeselectAll(); Doc.UnBrushDoc(this.props.Document); } - else if (CurrentUserUtils.MainDocId !== this.props.Document[Id] && + else if (!this.Document.ignoreClick && CurrentUserUtils.MainDocId !== this.props.Document[Id] && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { - if (BoolCast(this.props.Document.ignoreClick)) { - return; - } e.stopPropagation(); SelectionManager.SelectDoc(this, e.ctrlKey); - let isExpander = (e.target as any).id === "isExpander"; - if (BoolCast(this.props.Document.isButton) || this.props.Document.type === DocumentType.BUTTON || isExpander) { + if (this.Document.isButton || this.Document.type === DocumentType.BUTTON) { let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs); let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs); let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document); @@ -292,12 +294,12 @@ export class DocumentView extends DocComponent(Docu expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs; expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs; // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),]; - if (expandedDocs.length) { // bcz: need a better way to associate behaviors with click events on widget-documents + if (expandedDocs.length) { SelectionManager.DeselectAll(); - let maxLocation = StrCast(this.props.Document.maximizeLocation, "inPlace"); + let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace"); let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target); if (altKey || ctrlKey) { - maxLocation = this.props.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace")); + maxLocation = this.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace")); if (!maxLocation || maxLocation === "inPlace") { let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !d.isMinimized, false); @@ -379,8 +381,8 @@ export class DocumentView extends DocComponent(Docu document.removeEventListener("pointermove", this.onPointerMove); } else if (!e.cancelBubble && this.active) { - if (!this.props.Document.excludeFromLibrary && (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3)) { - if (!e.altKey && !this.topMost && e.buttons === 1 && !BoolCast(this.props.Document.lockedPosition)) { + if (!this.Document.excludeFromLibrary && (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3)) { + if (!e.altKey && !this.topMost && e.buttons === 1 && !BoolCast(this.Document.lockedPosition)) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); @@ -400,39 +402,33 @@ export class DocumentView extends DocComponent(Docu @undoBatch deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument && this.props.removeDocument(this.props.Document); } - @undoBatch - fieldsClicked = (): void => { - let kvp = Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }); - this.props.addDocTab(kvp, this.dataDoc, "onRight"); - } - @undoBatch makeNativeViewClicked = (): void => { makeNativeView(this.props.Document); } @undoBatch makeCustomViewClicked = (): void => { - this.props.Document.nativeLayout = this.props.Document.layout; - this.props.Document.nativeType = this.props.Document.type; - this.props.Document.nonCustomAutoHeight = this.props.Document.autoHeight; - this.props.Document.nonCustomWidth = this.props.Document.width; - this.props.Document.nonCustomHeight = this.props.Document.height; - this.props.Document.nonCustomNativeWidth = this.props.Document.nativeWidth; - this.props.Document.nonCustomNativeHeight = this.props.Document.nativeHeight; - this.props.Document.nonCustomIgnoreAspect = this.props.Document.ignoreAspect; + this.props.Document.nativeLayout = this.Document.layout; + this.props.Document.nativeType = this.Document.type; + this.props.Document.nonCustomAutoHeight = this.Document.autoHeight; + this.props.Document.nonCustomWidth = this.Document.width; + this.props.Document.nonCustomHeight = this.Document.height; + this.props.Document.nonCustomNativeWidth = this.Document.nativeWidth; + this.props.Document.nonCustomNativeHeight = this.Document.nativeHeight; + this.props.Document.nonCustomIgnoreAspect = this.Document.ignoreAspect; PromiseValue(Cast(this.props.Document.customLayout, Doc)).then(custom => { if (custom) { - this.props.Document.type = DocumentType.TEMPLATE; + this.Document.type = DocumentType.TEMPLATE; this.props.Document.layout = custom; - !custom.nativeWidth && (this.props.Document.nativeWidth = 0); - !custom.nativeHeight && (this.props.Document.nativeHeight = 0); - !custom.nativeWidth && (this.props.Document.ignoreAspect = true); - this.props.Document.autoHeight = this.props.Document.autoHeight; - this.props.Document.width = this.props.Document.customWidth; - this.props.Document.height = this.props.Document.customHeight; - this.props.Document.nativeWidth = this.props.Document.customNativeWidth; - this.props.Document.nativeHeight = this.props.Document.customNativeHeight; - this.props.Document.ignoreAspect = this.props.Document.ignoreAspect; + !custom.nativeWidth && (this.Document.nativeWidth = 0); + !custom.nativeHeight && (this.Document.nativeHeight = 0); + !custom.nativeWidth && (this.Document.ignoreAspect = true); + this.Document.autoHeight = BoolCast(this.Document.customAutoHeight); + this.Document.width = NumCast(this.props.Document.customWidth); + this.Document.height = NumCast(this.props.Document.customHeight); + this.Document.nativeWidth = NumCast(this.props.Document.customNativeWidth); + this.Document.nativeHeight = NumCast(this.props.Document.customNativeHeight); + this.Document.ignoreAspect = BoolCast(this.Document.customIgnoreAspect); this.props.Document.customAutoHeight = undefined; this.props.Document.customWidth = undefined; this.props.Document.customHeight = undefined; @@ -440,21 +436,21 @@ export class DocumentView extends DocComponent(Docu this.props.Document.customNativeHeight = undefined; this.props.Document.customIgnoreAspect = undefined; } else { - let options = { title: "data", width: NumCast(this.props.Document.width), x: -NumCast(this.props.Document.width) / 2, y: -NumCast(this.props.Document.height) / 2, }; - let fieldTemplate = this.props.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) : - this.props.Document.type === DocumentType.VID ? Docs.Create.VideoDocument("http://www.cs.brown.edu", options) : + let options = { title: "data", width: (this.Document.width || 0), x: -(this.Document.width || 0) / 2, y: - (this.Document.height || 0) / 2, }; + let fieldTemplate = this.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) : + this.Document.type === DocumentType.VID ? Docs.Create.VideoDocument("http://www.cs.brown.edu", options) : Docs.Create.ImageDocument("http://www.cs.brown.edu", options); - fieldTemplate.backgroundColor = StrCast(this.props.Document.backgroundColor); + fieldTemplate.backgroundColor = this.Document.backgroundColor; fieldTemplate.heading = 1; fieldTemplate.autoHeight = true; - let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: StrCast(this.Document.title) + "layout", width: NumCast(this.props.Document.width) + 20, height: Math.max(100, NumCast(this.props.Document.height) + 45) }); + let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: this.Document.title + "layout", width: (this.Document.width || 0) + 20, height: Math.max(100, (this.Document.height || 0) + 45) }); let proto = Doc.GetProto(docTemplate); Doc.MakeMetadataFieldTemplate(fieldTemplate, proto, true); Doc.ApplyTemplateTo(docTemplate, this.props.Document, undefined, false); - Doc.GetProto(this.dataDoc || this.props.Document).customLayout = this.props.Document.layout; + Doc.GetProto(this.dataDoc || this.props.Document).customLayout = this.Document.layout; } }); } @@ -468,21 +464,6 @@ export class DocumentView extends DocComponent(Docu } else { doc.isButton = true; } - - // if (doc.isButton) { - // if (!doc.nativeWidth) { - // doc.nativeWidth = this.props.Document[WidthSym](); - // doc.nativeHeight = this.props.Document[HeightSym](); - // } - // } else { - // doc.nativeWidth = doc.nativeHeight = undefined; - // } - } - - @undoBatch - public fullScreenClicked = (): void => { - CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this); - SelectionManager.DeselectAll(); } @undoBatch @@ -543,10 +524,10 @@ export class DocumentView extends DocComponent(Docu @undoBatch @action freezeNativeDimensions = (): void => { - let proto = this.props.Document.isTemplate ? this.props.Document : Doc.GetProto(this.props.Document); - this.props.Document.autoHeight = proto.autoHeight = false; - proto.ignoreAspect = !BoolCast(proto.ignoreAspect); - if (!BoolCast(proto.ignoreAspect) && !proto.nativeWidth) { + let proto = this.Document.isTemplate ? this.props.Document : Doc.GetProto(this.props.Document); + proto.autoHeight = this.Document.autoHeight = false; + proto.ignoreAspect = !proto.ignoreAspect; + if (!proto.ignoreAspect && !proto.nativeWidth) { proto.nativeWidth = this.props.PanelWidth(); proto.nativeHeight = this.props.PanelHeight(); } @@ -555,12 +536,12 @@ export class DocumentView extends DocComponent(Docu @action makeIntoPortal = (): void => { if (!DocListCast(this.props.Document.links).find(doc => { - if (Cast(doc.anchor2, Doc) instanceof Doc && (Cast(doc.anchor2, Doc) as Doc)!.title === this.props.Document.title + ".portal") return true; + if (Cast(doc.anchor2, Doc) instanceof Doc && (Cast(doc.anchor2, Doc) as Doc)!.title === this.Document.title + ".portal") return true; return false; })) { - let portalID = (this.props.Document.title + ".portal").replace(/^-/, "").replace(/\([0-9]*\)$/, ""); + let portalID = (this.Document.title + ".portal").replace(/^-/, "").replace(/\([0-9]*\)$/, ""); DocServer.GetRefField(portalID).then(existingPortal => { - let portal = existingPortal instanceof Doc ? existingPortal : Docs.Create.FreeformDocument([], { width: this.props.Document[WidthSym]() + 10, height: this.props.Document[HeightSym](), title: portalID }); + let portal = existingPortal instanceof Doc ? existingPortal : Docs.Create.FreeformDocument([], { width: (this.Document.width || 0) + 10, height: this.Document.height || 0, title: portalID }); DocUtils.MakeLink(this.props.Document, portal, undefined, portalID); Doc.GetProto(this.props.Document).isButton = true; }) @@ -618,15 +599,14 @@ export class DocumentView extends DocComponent(Docu const cm = ContextMenu.Instance; let subitems: ContextMenuProps[] = []; - subitems.push({ description: "Open Full Screen", event: this.fullScreenClicked, icon: "desktop" }); - subitems.push({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, this.dataDoc, "inTab"), icon: "folder" }); - subitems.push({ description: "Open Tab Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "inTab"), icon: "folder" }); - subitems.push({ description: "Open Right", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, this.dataDoc, "onRight"), icon: "caret-square-right" }); - subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" }); - subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" }); + subitems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this), icon: "desktop" }); + subitems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.dataDoc, "inTab"), icon: "folder" }); + subitems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.dataDoc, "onRight"), icon: "caret-square-right" }); + subitems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "inTab"), icon: "folder" }); + subitems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" }); + subitems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" }); cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); - let existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); @@ -643,7 +623,7 @@ export class DocumentView extends DocComponent(Docu }, icon: "window-restore" }); onClicks.push({ description: this.layoutDoc.ignoreClick ? "Select" : "Do Nothing", event: () => this.layoutDoc.ignoreClick = !this.layoutDoc.ignoreClick, icon: this.layoutDoc.ignoreClick ? "unlock" : "lock" }); - onClicks.push({ description: this.props.Document.isButton || this.props.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.makeBtnClicked, icon: "concierge-bell" }); + onClicks.push({ description: this.Document.isButton || this.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.makeBtnClicked, icon: "concierge-bell" }); onClicks.push({ description: "Edit onClick Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", obj.x, obj.y) }); onClicks.push({ description: "Edit onClick Foreach Doc Script", icon: "edit", event: (obj: any) => { @@ -655,20 +635,20 @@ export class DocumentView extends DocComponent(Docu let existing = ContextMenu.Instance.findByDescription("Layout..."); let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; - layoutItems.push({ description: this.props.Document.isBackground ? "As Foreground" : "As Background", event: this.makeBackground, icon: this.props.Document.lockedPosition ? "unlock" : "lock" }); + layoutItems.push({ description: this.Document.isBackground ? "As Foreground" : "As Background", event: this.makeBackground, icon: this.Document.lockedPosition ? "unlock" : "lock" }); if (this.props.DataDoc) { layoutItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc!), icon: "concierge-bell" }) } layoutItems.push({ description: `${this.layoutDoc.chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.layoutDoc.chromeStatus = (this.layoutDoc.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" }); layoutItems.push({ description: `${this.layoutDoc.autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc.autoHeight = !this.layoutDoc.autoHeight, icon: "plus" }); - layoutItems.push({ description: this.props.Document.ignoreAspect || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" }); + layoutItems.push({ description: this.Document.ignoreAspect || !this.Document.nativeWidth || !this.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" }); layoutItems.push({ description: this.layoutDoc.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.layoutDoc.lockedPosition) ? "unlock" : "lock" }); layoutItems.push({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" }); layoutItems.push({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" }); - if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) { + if (this.props.Document.detailedLayout && !this.Document.isTemplate) { layoutItems.push({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" }); } - if (this.props.Document.type !== DocumentType.COL && this.props.Document.type !== DocumentType.TEMPLATE) { + if (this.Document.type !== DocumentType.COL && this.Document.type !== DocumentType.TEMPLATE) { layoutItems.push({ description: "Use Custom Layout", event: this.makeCustomViewClicked, icon: "concierge-bell" }); } else if (this.props.Document.nativeLayout) { layoutItems.push({ description: "Use Native Layout", event: this.makeNativeViewClicked, icon: "concierge-bell" }); @@ -700,7 +680,7 @@ export class DocumentView extends DocComponent(Docu } }); - cm.addItem({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, StrCast(this.props.Document.title), this.props.addDocument, this.props.removeDocument), icon: "file" }); + cm.addItem({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" }); cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); type User = { email: string, userDocumentId: string }; let usersMenu: ContextMenuProps[] = []; @@ -780,7 +760,7 @@ export class DocumentView extends DocComponent(Docu select={this.select} onClick={this.onClickHandler} layoutKey={"layout"} - fitToBox={BoolCast(this.props.Document.fitToBox) ? true : this.props.fitToBox} + fitToBox={this.Document.fitToBox ? true : this.props.fitToBox} DataDoc={this.dataDoc} />); } @@ -796,55 +776,66 @@ export class DocumentView extends DocComponent(Docu return (showTitle ? 25 : 0) + 1;// bcz: why 8?? } - get layoutDoc() { + get layoutDoc(): Document { // if this document's layout field contains a document (ie, a rendering template), then we will use that // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string. - return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document; + return Document(this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document); } - render() { - let ruleProvider = this.props.ruleProvider; - let ruleColor = ruleProvider ? StrCast(Doc.GetProto(ruleProvider)["ruleColor_" + NumCast(this.props.Document.heading)]) : undefined; - let ruleRounding = ruleProvider ? StrCast(Doc.GetProto(ruleProvider)["ruleRounding_" + NumCast(this.props.Document.heading)]) : undefined; - let colorSet = this.layoutDoc.backgroundColor !== this.layoutDoc.defaultBackgroundColor; - let clusterCol = this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.clusterOverridesDefaultBackground; - - let backgroundColor = this.layoutDoc.isBackground || (clusterCol && !colorSet) ? + const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined; + const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; + const colorSet = this.layoutDoc.backgroundColor !== this.layoutDoc.defaultBackgroundColor; + const clusterCol = this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.clusterOverridesDefaultBackground; + const backgroundColor = this.layoutDoc.isBackground || (clusterCol && !colorSet) ? this.props.backgroundColor(this.layoutDoc) || StrCast(this.layoutDoc.backgroundColor) : ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.layoutDoc); - let foregroundColor = StrCast(this.layoutDoc.color); - var nativeWidth = this.props.Document.willMaximize ? 0 : this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%"; - var nativeHeight = this.props.Document.willMaximize ? 0 : BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; - let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined; - let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.layoutDoc.showTitle); - let showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : StrCast(this.layoutDoc.showCaption); - let templates = Cast(this.layoutDoc.templates, listSpec("string")); - if (!showOverlays && templates instanceof List) { - templates.map(str => { - if (!showTitle && str.indexOf("{props.Document.title}") !== -1) showTitle = "title"; - if (!showCaption && str.indexOf("fieldKey={\"caption\"}") !== -1) showCaption = "caption"; - }); - } - let showTextTitle = showTitle && StrCast(this.layoutDoc.layout).startsWith(" - {StrCast(this.props.Document.search_fields)} + + const nativeWidth = this.Document.willMaximize ? 0 : this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%"; + const nativeHeight = this.Document.willMaximize ? 0 : this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; + const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined; + const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.layoutDoc.showTitle; + const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.layoutDoc.showCaption; + const showTextTitle = showTitle && StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1 ? showTitle : undefined; + const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document); + const borderRounding = this.Document.borderRounding || ruleRounding; + const localScale = this.props.ScreenToLocalTransform().Scale * fullDegree; + const searchHighlight = (!this.Document.searchFields ? (null) : +
+ {this.Document.searchFields} +
); + const captionView = (!showCaption ? (null) : +
+ +
); + const titleView = (!showTitle ? (null) : +
+ StrCast((this.layoutDoc.isTemplate || !this.dataDoc ? this.layoutDoc : this.dataDoc)[showTitle])} + SetValue={(value: string) => ((this.layoutDoc.isTemplate ? this.layoutDoc : Doc.GetProto(this.layoutDoc))[showTitle] = value) ? true : true} + />
); return (
(Docu onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} > {!showTitle && !showCaption ? - this.props.Document.search_fields ?
- {this.contents} - {searchHighlight} -
: - this.contents : -
-
+ this.Document.searchFields ? + (
+ {this.contents} + {searchHighlight} +
) + : + this.contents + : +
+
{this.contents}
- {!showTitle ? (null) : -
- StrCast((this.layoutDoc.isTemplate || !this.dataDoc ? this.layoutDoc : this.dataDoc)[showTitle!])} - SetValue={(value: string) => ((this.layoutDoc.isTemplate ? this.layoutDoc : Doc.GetProto(this.layoutDoc))[showTitle!] = value) ? true : true} - /> -
- } - {!showCaption ? (null) : -
- -
- } + {titleView} + {captionView} {searchHighlight}
} diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 95f304641..beccce9dd 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -376,7 +376,6 @@ export class ImageBox extends DocComponent(ImageD // let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); // let w = bptX - sptX; - let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx let nativeWidth = FieldValue(this.Document.nativeWidth, pw); let nativeHeight = FieldValue(this.Document.nativeHeight, 0); let paths: string[] = [Utils.CorsProxy("http://www.cs.brown.edu/~bcz/noImage.png")]; @@ -402,11 +401,11 @@ export class ImageBox extends DocComponent(ImageD if (!this.props.Document.ignoreAspect && !this.props.leaveNativeSize) this.resize(srcpath, this.props.Document); return ( -
- Date: Thu, 19 Sep 2019 00:11:23 -0400 Subject: added ContainingCollectionDoc to props that get passed around. --- src/client/documents/Documents.ts | 2 +- .../util/Import & Export/DirectoryImportBox.tsx | 5 +- src/client/util/TooltipTextMenu.tsx | 4 +- src/client/views/DocumentDecorations.tsx | 11 +- src/client/views/InkingControl.tsx | 20 +-- src/client/views/MainOverlayTextBox.tsx | 6 +- src/client/views/MainView.tsx | 2 + src/client/views/OverlayView.tsx | 1 + .../views/collections/CollectionDockingView.tsx | 1 + .../views/collections/CollectionSchemaCells.tsx | 1 + .../CollectionSchemaMovableTableHOC.tsx | 8 +- .../views/collections/CollectionSchemaView.tsx | 3 + .../CollectionFreeFormLinksView.tsx | 6 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 + src/client/views/linking/LinkFollowBox.tsx | 30 ++-- src/client/views/nodes/DocumentView.tsx | 164 ++++++++++----------- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/KeyValuePair.tsx | 1 + src/client/views/nodes/PDFBox.tsx | 2 +- .../views/presentationview/PresentationElement.tsx | 1 + src/client/views/search/FilterBox.tsx | 6 +- src/client/views/search/SearchItem.tsx | 1 + 22 files changed, 136 insertions(+), 142 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 99707db19..2fa0d2dcb 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -640,7 +640,7 @@ export namespace DocUtils { export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", sourceContext?: Doc, id?: string, anchored1?: boolean) { if (LinkManager.Instance.doesLinkExist(source, target)) return undefined; let sv = DocumentManager.Instance.getDocumentView(source); - if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return; + if (sv && sv.props.ContainingCollectionDoc === target) return; if (target === CurrentUserUtils.UserDocument) return undefined; let linkDocProto = new Doc(id, true); diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 75b0b52a7..dc6a0cb7a 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -134,11 +134,10 @@ export default class DirectoryImportBox extends React.Component x: NumCast(doc.x), y: NumCast(doc.y) + offset }; - let parent = this.props.ContainingCollectionView; - if (parent) { + if (this.props.ContainingCollectionDoc) { let importContainer = Docs.Create.StackingDocument(docs, options); importContainer.singleColumn = false; - Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer); + Doc.AddDocToList(Doc.GetProto(this.props.ContainingCollectionDoc), "data", importContainer); !this.persistent && this.props.removeDocument && this.props.removeDocument(doc); DocumentManager.Instance.jumpToDocument(importContainer, true); diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 5764af282..aa096dd64 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -310,8 +310,8 @@ export class TooltipTextMenu { dragComplete: action(() => { let linkDoc = dragData.linkDocument; let proto = Doc.GetProto(linkDoc); - if (proto && docView && docView.props.ContainingCollectionView) { - proto.sourceContext = docView.props.ContainingCollectionView.props.Document; + if (proto && docView) { + proto.sourceContext = docView.props.ContainingCollectionDoc; } linkDoc instanceof Doc && this.makeLink(Utils.prepend("/doc/" + linkDoc[Id]), ctrlKey ? "onRight" : "inTab"); }), diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index b730f88a4..ad38d16aa 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -152,8 +152,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> SelectionManager.DeselectAll(); let fieldTemplate = fieldTemplateView.props.Document; let containerView = fieldTemplateView.props.ContainingCollectionView; - if (containerView) { - let docTemplate = containerView.props.Document; + let docTemplate = fieldTemplateView.props.ContainingCollectionDoc; + if (containerView && docTemplate) { let metaKey = text.startsWith(">>") ? text.slice(2, text.length) : text.slice(1, text.length); if (metaKey !== containerView.props.fieldKey && containerView.props.DataDoc) { const fd = fieldTemplate.data; @@ -431,8 +431,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> dist = dist < 3 ? 0 : dist; let usingRule = false; SelectionManager.SelectedDocuments().map(dv => { - let cv = dv.props.ContainingCollectionView; - let ruleProvider = cv && cv.props.ruleProvider; + let ruleProvider = dv.props.ruleProvider; let heading = NumCast(dv.props.Document.heading); ruleProvider && heading && (Doc.GetProto(ruleProvider)["ruleRounding_" + heading] = `${Math.min(100, dist)}%`); usingRule = usingRule || (ruleProvider && heading ? true : false); @@ -502,7 +501,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> document.removeEventListener("pointermove", this.onLinkerButtonMoved); document.removeEventListener("pointerup", this.onLinkerButtonUp); let selDoc = SelectionManager.SelectedDocuments()[0]; - let container = selDoc.props.ContainingCollectionView ? selDoc.props.ContainingCollectionView.props.Document.proto : undefined; + let container = selDoc.props.ContainingCollectionDoc ? selDoc.props.ContainingCollectionDoc.proto : undefined; let dragData = new DragManager.LinkDragData(selDoc.props.Document, container ? [container] : []); FormattedTextBox.InputBoxOverlay = undefined; this._linkDrag = UndoManager.StartBatch("Drag Link"); @@ -847,7 +846,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let templates: Map = new Map(); Array.from(Object.values(Templates.TemplateList)).map(template => - templates.set(template, SelectionManager.SelectedDocuments().reduce((checked, doc) => checked || (doc.props.Document["show" + template.Name] ? true : false), false))); + templates.set(template, SelectionManager.SelectedDocuments().reduce((checked, doc) => checked || (doc.props.Document["show" + template.Name] ? true : false), false as boolean))); bounds.x = Math.max(0, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2; bounds.y = Math.max(0, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight; diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 57dad5e6b..a10df0e75 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -52,16 +52,16 @@ export class InkingControl extends React.Component { let targetDoc = view.props.Document.layout instanceof Doc ? view.props.Document.layout : view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document); let oldColor = StrCast(targetDoc.backgroundColor); let matchedColor = this._selectedColor; - const cv = view.props.ContainingCollectionView; - let ruleProvider: Doc | undefined; - if (cv) { - if (!cv.props.Document.colorPalette) { - let defaultPalette = ["rg14,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)", + const cvd = view.props.ContainingCollectionDoc; + let ruleProvider = view.props.ruleProvider; + if (cvd) { + if (!cvd.colorPalette) { + let defaultPalette = ["rg(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)", "rgb(209,150,226)", "rgb(127,235,144)", "rgb(252,188,189)", "rgb(247,175,81)",]; - let colorPalette = Cast(cv.props.Document.colorPalette, listSpec("string")); - if (!colorPalette) cv.props.Document.colorPalette = new List(defaultPalette); + let colorPalette = Cast(cvd.colorPalette, listSpec("string")); + if (!colorPalette) cvd.colorPalette = new List(defaultPalette); } - let cp = Cast(cv.props.Document.colorPalette, listSpec("string")) as string[]; + let cp = Cast(cvd.colorPalette, listSpec("string")) as string[]; let closest = 0; let dist = 10000000; let ccol = Utils.fromRGBAstr(StrCast(targetDoc.backgroundColor)); @@ -74,9 +74,9 @@ export class InkingControl extends React.Component { } } cp[closest] = "rgba(" + color.rgb.r + "," + color.rgb.g + "," + color.rgb.b + "," + color.rgb.a + ")"; - cv.props.Document.colorPalette = new List(cp); + cvd.colorPalette = new List(cp); matchedColor = cp[closest]; - ruleProvider = (view.props.Document.heading && cv && cv.props.ruleProvider) ? cv.props.ruleProvider : undefined; + ruleProvider = (view.props.Document.heading && ruleProvider) ? ruleProvider : undefined; ruleProvider && ((Doc.GetProto(ruleProvider)["ruleColor_" + NumCast(view.props.Document.heading)] = Utils.toRGBAstr(color.rgb))); } !ruleProvider && (targetDoc.backgroundColor = matchedColor); diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 8e72d236c..ac1b437af 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -142,9 +142,9 @@ export class MainOverlayTextBox extends React.Component DataDoc={FormattedTextBox.InputBoxOverlay.props.DataDoc} onClick={undefined} ruleProvider={this._textBox ? this._textBox.props.ruleProvider : undefined} - ChromeHeight={this.ChromeHeight} - isSelected={returnTrue} select={emptyFunction} renderDepth={0} - ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} ContentScaling={returnOne} + ChromeHeight={this.ChromeHeight} isSelected={returnTrue} select={emptyFunction} renderDepth={0} + ContainingCollectionDoc={undefined} ContainingCollectionView={undefined} + whenActiveChanged={emptyFunction} active={returnTrue} ContentScaling={returnOne} ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} pinToPres={returnZero} addDocTab={this.addDocTab} outer_div={(tooltip: HTMLElement) => { this._tooltip = tooltip; this.updateTooltip(); }} />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 2cec1c052..8b0caf9a6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -335,6 +335,7 @@ export class MainView extends React.Component { whenActiveChanged={emptyFunction} bringToFront={emptyFunction} ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} zoomToScale={emptyFunction} getScale={returnOne} />} @@ -399,6 +400,7 @@ export class MainView extends React.Component { whenActiveChanged={emptyFunction} bringToFront={emptyFunction} ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} zoomToScale={emptyFunction} getScale={returnOne}> ; diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 15faea3cd..8124ce653 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -189,6 +189,7 @@ export class OverlayView extends React.Component { addDocTab={emptyFunction} pinToPres={emptyFunction} ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} zoomToScale={emptyFunction} getScale={returnOne} />
; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 55ba3a314..cab085d9b 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -639,6 +639,7 @@ export class DockedFrameRenderer extends React.Component { addDocTab={this.addDocTab} pinToPres={this.PinDoc} ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} zoomToScale={emptyFunction} getScale={returnOne} />; } diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 3452e8702..059967a7d 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -151,6 +151,7 @@ export class CollectionSchemaCell extends React.Component { fieldExt: "", ruleProvider: undefined, ContainingCollectionView: this.props.CollectionView, + ContainingCollectionDoc: this.props.CollectionView.props.Document, isSelected: returnFalse, select: emptyFunction, renderDepth: this.props.renderDepth + 1, diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index ec40043cc..39abc41ec 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -201,12 +201,8 @@ export class MovableRow extends React.Component { @action move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => { let targetView = DocumentManager.Instance.getDocumentView(target); - if (targetView) { - let targetContainingColl = targetView.props.ContainingCollectionView; //.props.ContainingCollectionView.props.Document; - if (targetContainingColl) { - let targetContCollDoc = targetContainingColl.props.Document; - return doc !== target && doc !== targetContCollDoc && this.props.removeDoc(doc) && addDoc(doc); - } + if (targetView && targetView.props.ContainingCollectionDoc) { + return doc !== target && doc !== targetView.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc); } return doc !== target && this.props.removeDoc(doc) && addDoc(doc); } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 4d2b8e1c1..a742054d0 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -196,6 +196,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { childDocs={this.childDocs} CollectionView={this.props.CollectionView} ContainingCollectionView={this.props.ContainingCollectionView} + ContainingCollectionDoc={this.props.ContainingCollectionDoc} fieldKey={this.props.fieldKey} renderDepth={this.props.renderDepth} moveDocument={this.props.moveDocument} @@ -247,6 +248,7 @@ export interface SchemaTableProps { childDocs?: Doc[]; CollectionView: CollectionView | CollectionPDFView | CollectionVideoView; ContainingCollectionView: Opt; + ContainingCollectionDoc: Opt; fieldKey: string; renderDepth: number; deleteDocument: (document: Doc) => boolean; @@ -1004,6 +1006,7 @@ export class CollectionSchemaPreview extends React.Component child[Id] === collid).map(view => DocumentManager.Instance.getDocumentViews(view).map(view => equalViews.push(view))); } - return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document); + return equalViews.filter(sv => sv.props.ContainingCollectionDoc === this.props.Document); } @computed diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c9e78cee6..ad77e0428 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -659,6 +659,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { PanelHeight: childLayout[HeightSym], ContentScaling: returnOne, ContainingCollectionView: this.props.CollectionView, + ContainingCollectionDoc: this.props.CollectionView.props.Document, focus: this.focusDocument, backgroundColor: this.getClusterColor, parentActive: this.props.active, @@ -685,6 +686,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { PanelHeight: layoutDoc[HeightSym], ContentScaling: returnOne, ContainingCollectionView: this.props.CollectionView, + ContainingCollectionDoc: this.props.CollectionView.props.Document, focus: this.focusDocument, backgroundColor: returnEmptyString, parentActive: this.props.active, diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index b1c6c367f..d7cb2585e 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -85,11 +85,10 @@ export class LinkFollowBox extends React.Component { } async resetPan() { - if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionView) { - let colDoc = this.sourceView.props.ContainingCollectionView.props.Document; - runInAction(() => { this.canPan = false; }); - if (colDoc.viewType && colDoc.viewType === CollectionViewType.Freeform) { - let docs = Cast(colDoc.data, listSpec(Doc), []); + if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionDoc) { + runInAction(() => this.canPan = false); + if (this.sourceView.props.ContainingCollectionDoc.viewType === CollectionViewType.Freeform) { + let docs = Cast(this.sourceView.props.ContainingCollectionDoc.data, listSpec(Doc), []); let aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(LinkFollowBox.destinationDoc)); aliases.forEach(alias => { @@ -371,9 +370,9 @@ export class LinkFollowBox extends React.Component { this.shouldUseOnlyParentContext = (this.selectedMode === FollowModes.INPLACE || this.selectedMode === FollowModes.PAN); if (this.shouldUseOnlyParentContext) { - if (this.sourceView && this.sourceView.props.ContainingCollectionView) { - this.selectedContext = this.sourceView.props.ContainingCollectionView.props.Document; - this.selectedContextString = (StrCast(this.sourceView.props.ContainingCollectionView.props.Document.title)); + if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { + this.selectedContext = this.sourceView.props.ContainingCollectionDoc; + this.selectedContextString = (StrCast(this.sourceView.props.ContainingCollectionDoc.title)); } } } @@ -394,9 +393,8 @@ export class LinkFollowBox extends React.Component { @computed get canOpenInPlace() { - if (this.sourceView && this.sourceView.props.ContainingCollectionView) { - let colView = this.sourceView.props.ContainingCollectionView; - let colDoc = colView.props.Document; + if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { + let colDoc = this.sourceView.props.ContainingCollectionDoc; if (colDoc.viewType && colDoc.viewType === CollectionViewType.Freeform) return true; } return false; @@ -457,17 +455,15 @@ export class LinkFollowBox extends React.Component { @computed get parentName() { - if (this.sourceView && this.sourceView.props.ContainingCollectionView) { - let colView = this.sourceView.props.ContainingCollectionView; - return colView.props.Document.title; + if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { + return this.sourceView.props.ContainingCollectionDoc.title; } } @computed get parentID(): string { - if (this.sourceView && this.sourceView.props.ContainingCollectionView) { - let colView = this.sourceView.props.ContainingCollectionView; - return StrCast(colView.props.Document[Id]); + if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { + return StrCast(this.sourceView.props.ContainingCollectionDoc[Id]); } return "col"; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d4e396752..39bba2eb2 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -67,6 +67,7 @@ library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointRight, fa.faCom export interface DocumentViewProps { ContainingCollectionView: Opt; + ContainingCollectionDoc: Opt; Document: Doc; DataDoc?: Doc; fitToBox?: boolean; @@ -208,88 +209,83 @@ export class DocumentView extends DocComponent(Docu } onClick = async (e: React.MouseEvent) => { - if (e.nativeEvent.cancelBubble) return; // || SelectionManager.IsSelected(this)) -- bcz: needed because EditableView may stopPropagation which won't apparently stop this event from firing. - if (this.onClickHandler && this.onClickHandler.script) { + if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && CurrentUserUtils.MainDocId !== this.props.Document[Id] && + (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { e.stopPropagation(); - this.onClickHandler.script.run({ this: this.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document }); e.preventDefault(); - return; + if (this._doubleTap && this.props.renderDepth) { + let fullScreenAlias = Doc.MakeAlias(this.props.Document); + let layoutNative = await PromiseValue(Cast(this.props.Document.layoutNative, Doc)); + if (layoutNative && fullScreenAlias.layout === layoutNative.layout) { + await swapViews(fullScreenAlias, "layoutCustom", "layoutNative"); + } + this.props.addDocTab(fullScreenAlias, undefined, "inTab"); + SelectionManager.DeselectAll(); + Doc.UnBrushDoc(this.props.Document); + } else if (this.onClickHandler && this.onClickHandler.script) { + this.onClickHandler.script.run({ this: this.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document }); + } else if (this.Document.isButton) { + SelectionManager.SelectDoc(this, e.ctrlKey); // don't think this should happen if a button action is actually triggered. + this.buttonClick(e.altKey, e.ctrlKey); + } else SelectionManager.SelectDoc(this, e.ctrlKey); } - let altKey = e.altKey; - let ctrlKey = e.ctrlKey; - if (this._doubleTap && this.props.renderDepth) { - e.stopPropagation(); - let fullScreenAlias = Doc.MakeAlias(this.props.Document); - let layoutNative = await PromiseValue(Cast(this.props.Document.layoutNative, Doc)); - if (layoutNative && fullScreenAlias.layout === layoutNative.layout) { - await swapViews(fullScreenAlias, "layoutCustom", "layoutNative"); - } - this.props.addDocTab(fullScreenAlias, undefined, "inTab"); + } + + buttonClick = async (altKey: boolean, ctrlKey: boolean) => { + let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs); + let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs); + let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document); + let expandedDocs: Doc[] = []; + expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs; + expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs; + // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),]; + if (expandedDocs.length) { SelectionManager.DeselectAll(); - Doc.UnBrushDoc(this.props.Document); - } - else if (!this.Document.ignoreClick && CurrentUserUtils.MainDocId !== this.props.Document[Id] && - (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && - Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { - e.stopPropagation(); - SelectionManager.SelectDoc(this, e.ctrlKey); - if (this.Document.isButton || this.Document.type === DocumentType.BUTTON) { - let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs); - let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs); - let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document); - let expandedDocs: Doc[] = []; - expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs; - expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs; - // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),]; - if (expandedDocs.length) { - SelectionManager.DeselectAll(); - let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace"); - let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target); - if (altKey || ctrlKey) { - maxLocation = this.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace")); - if (!maxLocation || maxLocation === "inPlace") { - let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); - let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !d.isMinimized, false); - expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false); - let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); - if (!hasView) { - this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(getDispDoc(maxDoc), false)); - } - expandedDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized); - } - } - if (maxLocation && maxLocation !== "inPlace" && CollectionDockingView.Instance) { - let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data); - if (dataDocs) { - expandedDocs.forEach(maxDoc => - (!CollectionDockingView.Instance.CloseRightSplit(Doc.GetProto(maxDoc)) && - this.props.addDocTab(getDispDoc(maxDoc), undefined, maxLocation))); - } - } else { - let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2); - this.collapseTargetsToPoint(scrpt, expandedDocs); + let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace"); + let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target); + if (altKey || ctrlKey) { + maxLocation = this.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace")); + if (!maxLocation || maxLocation === "inPlace") { + let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); + let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !d.isMinimized, false); + expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false); + let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); + if (!hasView) { + this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(getDispDoc(maxDoc), false)); } + expandedDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized); } - else if (linkedDocs.length) { - SelectionManager.DeselectAll(); - let first = linkedDocs.filter(d => Doc.AreProtosEqual(d.anchor1 as Doc, this.props.Document) && !d.anchor1anchored); - let firstUnshown = first.filter(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0); - if (firstUnshown.length) first = [firstUnshown[0]]; - let linkedFwdDocs = first.length ? [first[0].anchor2 as Doc, first[0].anchor1 as Doc] : [expandedDocs[0], expandedDocs[0]]; - - // @TODO: shouldn't always follow target context - let linkedFwdContextDocs = [first.length ? await (first[0].targetContext) as Doc : undefined, undefined]; - let linkedFwdPage = [first.length ? NumCast(first[0].anchor2Page, undefined) : undefined, undefined]; - - if (!linkedFwdDocs.some(l => l instanceof Promise)) { - let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab"); - let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined; - DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, - // 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 => this.props.focus(this.props.Document, true, 1, () => { this.props.addDocTab(doc, undefined, maxLocation); return true; }), - linkedFwdPage[altKey ? 1 : 0], targetContext); - } + } + if (maxLocation && maxLocation !== "inPlace" && CollectionDockingView.Instance) { + let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data); + if (dataDocs) { + expandedDocs.forEach(maxDoc => + (!CollectionDockingView.Instance.CloseRightSplit(Doc.GetProto(maxDoc)) && + this.props.addDocTab(getDispDoc(maxDoc), undefined, maxLocation))); } + } else { + let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2); + this.collapseTargetsToPoint(scrpt, expandedDocs); + } + } + else if (linkedDocs.length) { + SelectionManager.DeselectAll(); + let first = linkedDocs.filter(d => Doc.AreProtosEqual(d.anchor1 as Doc, this.props.Document) && !d.anchor1anchored); + let firstUnshown = first.filter(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0); + if (firstUnshown.length) first = [firstUnshown[0]]; + let linkedFwdDocs = first.length ? [first[0].anchor2 as Doc, first[0].anchor1 as Doc] : [expandedDocs[0], expandedDocs[0]]; + + // @TODO: shouldn't always follow target context + let linkedFwdContextDocs = [first.length ? await (first[0].targetContext) as Doc : undefined, undefined]; + let linkedFwdPage = [first.length ? NumCast(first[0].anchor2Page, undefined) : undefined, undefined]; + + if (!linkedFwdDocs.some(l => l instanceof Promise)) { + let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab"); + let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionDoc) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined; + DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, + // 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 => this.props.focus(this.props.Document, true, 1, () => { this.props.addDocTab(doc, undefined, maxLocation); return true; }), + linkedFwdPage[altKey ? 1 : 0], targetContext); } } } @@ -387,25 +383,21 @@ export class DocumentView extends DocComponent(Docu let targetDoc = this.props.Document; let annotations = await DocListCastAsync(sourceDoc.annotations); sourceDoc.linkedToDoc = true; - de.data.targetContext = this.props.ContainingCollectionView!.props.Document; + de.data.targetContext = this.props.ContainingCollectionDoc; targetDoc.targetContext = de.data.targetContext; annotations && annotations.forEach(anno => anno.target = targetDoc); - DocUtils.MakeLink(sourceDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Link from ${StrCast(sourceDoc.title)}`); + DocUtils.MakeLink(sourceDoc, targetDoc, this.props.ContainingCollectionDoc, `Link from ${StrCast(sourceDoc.title)}`); } if (de.data instanceof DragManager.DocumentDragData && de.data.applyAsTemplate) { Doc.ApplyTemplateTo(de.data.draggedDocuments[0], this.props.Document); e.stopPropagation(); } if (de.data instanceof DragManager.LinkDragData) { - let sourceDoc = de.data.linkSourceDocument; - let destDoc = this.props.Document; - e.stopPropagation(); // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true); // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView); - de.data.droppedDocuments.push(destDoc); - de.data.linkDocument = DocUtils.MakeLink(sourceDoc, destDoc, this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document); + de.data.linkDocument = DocUtils.MakeLink(de.data.linkSourceDocument, this.props.Document, this.props.ContainingCollectionDoc); } } @@ -436,7 +428,7 @@ export class DocumentView extends DocComponent(Docu @undoBatch @action makeIntoPortal = async () => { - let anchors = await Promise.all(DocListCast(this.props.Document.links).map(async (d: Doc) => await Cast(d.anchor2, Doc))); + let anchors = await Promise.all(DocListCast(this.props.Document.links).map(async (d: Doc) => Cast(d.anchor2, Doc))); if (!anchors.find(anchor2 => anchor2 && anchor2.title === this.Document.title + ".portal" ? true : false)) { let portalID = (this.Document.title + ".portal").replace(/^-/, "").replace(/\([0-9]*\)$/, ""); DocServer.GetRefField(portalID).then(existingPortal => { @@ -512,7 +504,7 @@ export class DocumentView extends DocComponent(Docu onClicks.push({ description: "Edit onClick Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", obj.x, obj.y) }); onClicks.push({ description: "Edit onClick Foreach Doc Script", icon: "edit", event: (obj: any) => { - this.props.Document.collectionContext = this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document; + this.props.Document.collectionContext = this.props.ContainingCollectionDoc; ScriptBox.EditButtonScript("Foreach Collection Doc (d) => ", this.props.Document, "onClick", obj.x, obj.y, "docList(this.collectionContext.data).map(d => {", "});\n"); } }); @@ -637,7 +629,7 @@ export class DocumentView extends DocComponent(Docu const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined; const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; const colorSet = this.Document.backgroundColor !== this.Document.defaultBackgroundColor; - const clusterCol = this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.clusterOverridesDefaultBackground; + const clusterCol = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.clusterOverridesDefaultBackground; const backgroundColor = this.Document.isBackground || (clusterCol && !colorSet) ? this.props.backgroundColor(this.Document) || StrCast(this.Document.backgroundColor) : ruleColor && !colorSet ? ruleColor : StrCast(this.Document.backgroundColor) || this.props.backgroundColor(this.Document); @@ -753,7 +745,7 @@ export async function swapViews(doc: Doc, newLayoutField: string, oldLayoutField doc.type = newLayoutExt.type; doc.layout = await newLayoutExt.layout; } -}; +} Scripting.addGlobal(function toggleDetail(doc: any) { let native = typeof doc.layout === "string"; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 943d181d6..faf11e9be 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -30,6 +30,7 @@ export interface FieldViewProps { leaveNativeSize?: boolean; fitToBox?: boolean; ContainingCollectionView: Opt; + ContainingCollectionDoc: Opt; ruleProvider: Doc | undefined; Document: Doc; DataDoc?: Doc; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 7e0f3735d..c7e0f51d7 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -55,6 +55,7 @@ export class KeyValuePair extends React.Component { Document: this.props.doc, DataDoc: this.props.doc, ContainingCollectionView: undefined, + ContainingCollectionDoc: undefined, ruleProvider: undefined, fieldKey: this.props.keyName, fieldExt: "", diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 64b84ba55..c8534ed0d 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -31,7 +31,7 @@ export class PDFBox extends DocComponent(PdfDocumen @observable private _alt = false; @observable private _pdf: Opt; - @computed get containingCollectionDocument() { return this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document; } + @computed get containingCollectionDocument() { return this.props.ContainingCollectionDoc; } @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); } diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 7be44faf6..126d62c52 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -366,6 +366,7 @@ export default class PresentationElement extends React.Component
{ zoomToScale={emptyFunction} getScale={returnOne} ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} ContentScaling={scale} />
; -- cgit v1.2.3-70-g09d2 From 2cdca63ac039a7c66a9c93acb35fe51467269e64 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 19 Sep 2019 11:29:11 -0400 Subject: switche calls to COllectionDockingView... to addDocTabs. fixed following links to navigate/restore properly. --- src/client/util/DocumentManager.ts | 15 ++-- src/client/util/TooltipTextMenu.tsx | 8 +- src/client/views/GlobalKeyHandler.ts | 4 +- src/client/views/MainOverlayTextBox.tsx | 4 +- src/client/views/MainView.tsx | 10 ++- src/client/views/OverlayView.tsx | 2 +- .../views/collections/CollectionBaseView.tsx | 4 +- .../views/collections/CollectionDockingView.tsx | 85 ++++++++++++---------- .../views/collections/CollectionSchemaCells.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 8 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 17 +++-- src/client/views/linking/LinkFollowBox.tsx | 16 ++-- src/client/views/linking/LinkMenu.tsx | 2 +- src/client/views/linking/LinkMenuGroup.tsx | 24 +++--- src/client/views/linking/LinkMenuItem.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 24 ++---- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 7 +- src/client/views/pdf/Annotation.tsx | 8 +- src/client/views/pdf/PDFViewer.tsx | 2 +- src/client/views/search/SearchItem.tsx | 4 +- 23 files changed, 127 insertions(+), 129 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index ec731da84..65ab32539 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -10,6 +10,7 @@ import { DocumentView } from '../views/nodes/DocumentView'; import { LinkManager } from './LinkManager'; import { undoBatch, UndoManager } from './UndoManager'; import { Scripting } from './Scripting'; +import { emptyFunction } from '../../Utils'; export class DocumentManager { @@ -146,6 +147,7 @@ export class DocumentManager { if (!contextDoc) { let docs = docContext ? await DocListCastAsync(docContext.data) : undefined; let found = false; + // bcz: this just searches within the context for the target -- perhaps it should recursively search through all children? docs && docs.map(d => found = found || Doc.AreProtosEqual(d, docDelegate)); if (docContext && found) { let targetContextView: DocumentView | null; @@ -154,16 +156,19 @@ export class DocumentManager { docContext.panTransformType = "Ease"; targetContextView.props.focus(docDelegate, willZoom); } else { - (dockFunc || CollectionDockingView.Instance.AddRightSplit)(docContext, undefined); + (dockFunc || CollectionDockingView.AddRightSplit)(docContext, undefined); setTimeout(() => { - this.jumpToDocument(docDelegate, willZoom, forceDockFunc, dockFunc, linkPage); - }, 10); + let dv = DocumentManager.Instance.getDocumentView(docContext); + dv && this.jumpToDocument(docDelegate, willZoom, forceDockFunc, + doc => dv!.props.focus(dv!.props.Document, true, 1, () => dv!.props.addDocTab(doc, undefined, "inPlace")), + linkPage); + }, 1050); } } else { const actualDoc = Doc.MakeAlias(docDelegate); Doc.BrushDoc(actualDoc); if (linkPage !== undefined) actualDoc.curPage = linkPage; - (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc, undefined); + (dockFunc || CollectionDockingView.AddRightSplit)(actualDoc, undefined); } } else { let contextView: DocumentView | null; @@ -172,7 +177,7 @@ export class DocumentManager { contextDoc.panTransformType = "Ease"; contextView.props.focus(docDelegate, willZoom); } else { - (dockFunc || CollectionDockingView.Instance.AddRightSplit)(contextDoc, undefined); + (dockFunc || CollectionDockingView.AddRightSplit)(contextDoc, undefined); setTimeout(() => { this.jumpToDocument(docDelegate, willZoom, forceDockFunc, dockFunc, linkPage); }, 10); diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index aa096dd64..b6de048e4 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -58,10 +58,6 @@ export class TooltipTextMenu { private _collapsed: boolean = false; - @observable - private _storedMarks: Mark[] | null | undefined; - - constructor(view: EditorView, editorProps: FieldViewProps & FormattedTextBoxProps) { this.view = view; this.editorProps = editorProps; @@ -84,8 +80,6 @@ export class TooltipTextMenu { this.dragElement(dragger); - this._storedMarks = this.view.state.storedMarks; - // this.createCollapse(); // if (this._collapseBtn) { // this.tooltip.appendChild(this._collapseBtn.render(this.view).dom); @@ -280,7 +274,7 @@ export class TooltipTextMenu { if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f, false); } - else if (CollectionDockingView.Instance) CollectionDockingView.Instance.AddRightSplit(f, undefined); + else this.editorProps.addDocTab(f, undefined, "onRight"); } })); } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index ef5d76ce8..2fa03e969 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -141,7 +141,7 @@ export default class KeyManager { return { stopPropagation: false, preventDefault: false }; } } - MainView.Instance.mainFreeform && CollectionDockingView.Instance.AddRightSplit(MainView.Instance.mainFreeform, undefined); + MainView.Instance.mainFreeform && CollectionDockingView.AddRightSplit(MainView.Instance.mainFreeform, undefined); break; case "arrowleft": if (document.activeElement) { @@ -149,7 +149,7 @@ export default class KeyManager { return { stopPropagation: false, preventDefault: false }; } } - MainView.Instance.mainFreeform && CollectionDockingView.Instance.CloseRightSplit(MainView.Instance.mainFreeform); + MainView.Instance.mainFreeform && CollectionDockingView.CloseRightSplit(MainView.Instance.mainFreeform); break; case "backspace": if (document.activeElement) { diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index ac1b437af..f32fb584a 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -119,9 +119,7 @@ export class MainOverlayTextBox extends React.Component } addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => { - if (true) { // location === "onRight") { need to figure out stack to add "inTab" - CollectionDockingView.Instance.AddRightSplit(doc, dataDoc); - } + this._textBox && this._textBox.props.addDocTab(doc, dataDoc, location); } render() { this.TextDoc; this.TextDataDoc; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 8b0caf9a6..097040b6c 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -288,6 +288,7 @@ export class MainView extends React.Component { } } }, 100); + return true; } onDrop = (e: React.DragEvent) => { @@ -319,7 +320,7 @@ export class MainView extends React.Component { this.flyoutWidth; - addDocTabFunc = (doc: Doc) => { + addDocTabFunc = (doc: Doc, data: Opt, where: string) => { + if (where === "close") + return CollectionDockingView.CloseRightSplit(doc); if (doc.dockingConfig) { this.openWorkspace(doc); + return true; } else { - CollectionDockingView.Instance.AddRightSplit(doc, undefined); + return CollectionDockingView.AddRightSplit(doc, undefined); } } @computed diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 8124ce653..45e0a3562 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -186,7 +186,7 @@ export class OverlayView extends React.Component { whenActiveChanged={emptyFunction} focus={emptyFunction} backgroundColor={returnEmptyString} - addDocTab={emptyFunction} + addDocTab={returnFalse} pinToPres={emptyFunction} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index fdb2f0dc9..0399371ff 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -103,7 +103,6 @@ export class CollectionBaseView extends React.Component { if (this.props.fieldExt) { // bcz: fieldExt !== undefined means this is an overlay layer Doc.GetProto(doc).annotationOn = this.props.Document; } - allowDuplicates = true; let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document; let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; const value = Cast(targetDataDoc[targetField], listSpec(Doc)); @@ -126,7 +125,8 @@ export class CollectionBaseView extends React.Component { let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document; let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; let value = Cast(targetDataDoc[targetField], listSpec(Doc), []); - let index = value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1); + let index = value.reduce((p, v, i) => (v instanceof Doc && v === doc) ? i : p, -1); + index = index !== -1 ? index : value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1); PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn => annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined)); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index cab085d9b..277fa0066 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -1,36 +1,35 @@ +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faFile } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import 'golden-layout/src/css/goldenlayout-base.css'; import 'golden-layout/src/css/goldenlayout-dark-theme.css'; -import { action, Lambda, observable, reaction, trace, computed } from "mobx"; +import { action, computed, Lambda, observable, reaction } from "mobx"; import { observer } from "mobx-react"; 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 { Id } from '../../../new_fields/FieldSymbols'; +import { List } from '../../../new_fields/List'; import { FieldId } from "../../../new_fields/RefField"; import { listSpec } from "../../../new_fields/Schema"; -import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; -import { emptyFunction, returnTrue, Utils, returnOne, returnEmptyString } from "../../../Utils"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; +import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; +import { Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragLinksAsDocuments, DragManager } from "../../util/DragManager"; import { SelectionManager } from '../../util/SelectionManager'; import { Transform } from '../../util/Transform'; -import { undoBatch, UndoManager } from "../../util/UndoManager"; +import { undoBatch } from "../../util/UndoManager"; +import { MainView } from '../MainView'; import { DocumentView } from "../nodes/DocumentView"; import "./CollectionDockingView.scss"; import { SubCollectionViewProps } from "./CollectionSubView"; import { ParentDocSelector } from './ParentDocumentSelector'; import React = require("react"); -import { MainView } from '../MainView'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faFile, faUnlockAlt } from '@fortawesome/free-solid-svg-icons'; -import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; -import { Docs } from '../../documents/Documents'; -import { DateField } from '../../../new_fields/DateField'; -import { List } from '../../../new_fields/List'; -import { DocumentType } from '../../documents/DocumentTypes'; library.add(faFile); @observer @@ -59,7 +58,7 @@ export class CollectionDockingView extends React.Component { + public static CloseRightSplit(document: Doc): boolean { + if (!CollectionDockingView.Instance) return false; + let instance = CollectionDockingView.Instance; let retVal = false; - if (this._goldenLayout.root.contentItems[0].isRow) { - retVal = Array.from(this._goldenLayout.root.contentItems[0].contentItems).some((child: any) => { + if (instance._goldenLayout.root.contentItems[0].isRow) { + retVal = Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => { if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" && + DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId) && Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)!.Document, document)) { child.contentItems[0].remove(); - this.layoutChanged(document); + instance.layoutChanged(document); return true; } else { Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { - if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) { + if (DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId) && + Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) { child.contentItems[j].remove(); child.config.activeItemIndex = Math.max(child.contentItems.length - 1, 0); - let docs = Cast(this.props.Document.data, listSpec(Doc)); + let docs = Cast(instance.props.Document.data, listSpec(Doc)); docs && docs.indexOf(document) !== -1 && docs.splice(docs.indexOf(document), 1); return true; } @@ -146,7 +149,7 @@ export class CollectionDockingView extends React.Component { - let docs = Cast(this.props.Document.data, listSpec(Doc)); + public static AddRightSplit(document: Doc, dataDoc: Doc | undefined, minimize: boolean = false) { + if (!CollectionDockingView.Instance) return false; + let instance = CollectionDockingView.Instance; + let docs = Cast(instance.props.Document.data, listSpec(Doc)); if (docs) { docs.push(document); } @@ -183,15 +188,15 @@ export class CollectionDockingView extends React.Component, dragSpan); - ReactDOM.render( CollectionDockingView.Instance.AddTab(stack, doc, dataDoc)} />, upDiv); + ReactDOM.render( { + where === "onRight" ? CollectionDockingView.AddRightSplit(doc, dataDoc) : CollectionDockingView.Instance.AddTab(stack, doc, dataDoc); + return true; + }} />, upDiv); tab.reactComponents = [dragSpan, upDiv]; tab.element.append(dragSpan); tab.element.append(upDiv); @@ -604,15 +612,16 @@ export class DockedFrameRenderer extends React.Component { } get previewPanelCenteringOffset() { return this.nativeWidth() && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth()) / 2 : 0; } - addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => { + addDocTab = (doc: Doc, dataDoc: Opt, location: string) => { if (doc.dockingConfig) { MainView.Instance.openWorkspace(doc); + return true; } else if (location === "onRight") { - CollectionDockingView.Instance.AddRightSplit(doc, dataDoc); + return CollectionDockingView.AddRightSplit(doc, dataDoc); } else if (location === "close") { - CollectionDockingView.Instance.CloseRightSplit(doc); + return CollectionDockingView.CloseRightSplit(doc); } else { - CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc); + return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc); } } @computed get docView() { diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 059967a7d..0306d415c 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -39,7 +39,7 @@ export interface CellProps { Document: Doc; fieldKey: string; renderDepth: number; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; isFocused: boolean; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index a742054d0..7bd2a1971 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -256,7 +256,7 @@ export interface SchemaTableProps { ScreenToLocalTransform: () => Transform; active: () => boolean; onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; isSelected: () => boolean; isFocused: (document: Doc) => boolean; @@ -915,7 +915,7 @@ interface CollectionSchemaPreviewProps { removeDocument: (document: Doc) => boolean; active: () => boolean; whenActiveChanged: (isActive: boolean) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; setPreviewScript: (script: string) => void; previewScript?: string; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index b4026a810..08d87c7b2 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -40,7 +40,7 @@ export interface TreeViewProps { ruleProvider: Doc | undefined; moveDocument: DragManager.MoveFunction; dropAction: "alias" | "copy" | undefined; - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; panelWidth: () => number; panelHeight: () => number; @@ -414,7 +414,7 @@ class TreeView extends React.Component { remove: ((doc: Doc) => boolean), move: DragManager.MoveFunction, dropAction: dropActionType, - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void, + addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean, pinToPres: (document: Doc) => void, screenToLocalXf: () => Transform, outerXf: () => { translateX: number, translateY: number }, @@ -562,8 +562,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { outerXf = () => Utils.GetScreenTransform(this._mainEle!); onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {}); openNotifsCol = () => { - if (CollectionTreeView.NotifsCol && CollectionDockingView.Instance) { - CollectionDockingView.Instance.AddRightSplit(CollectionTreeView.NotifsCol, undefined); + if (CollectionTreeView.NotifsCol) { + this.props.addDocTab(CollectionTreeView.NotifsCol, undefined, "onRight"); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ad77e0428..7383c5551 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -508,14 +508,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }); } - let panelDim = this.props.ScreenToLocalTransform().transformDirection(this._pwidth / this.zoomScaling(), - this._pheight / this.zoomScaling()); - let panelwidth = panelDim[0]; - let panelheight = panelDim[1]; - if (ranges[0][0] - dx > (this.panX() + panelwidth / 2)) x = ranges[0][1] + panelwidth / 2; - if (ranges[0][1] - dx < (this.panX() - panelwidth / 2)) x = ranges[0][0] - panelwidth / 2; - if (ranges[1][0] - dy > (this.panY() + panelheight / 2)) y = ranges[1][1] + panelheight / 2; - if (ranges[1][1] - dy < (this.panY() - panelheight / 2)) y = ranges[1][0] - panelheight / 2; + let cscale = this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.scale) : 1; + let panelDim = this.props.ScreenToLocalTransform().transformDirection(this._pwidth / this.zoomScaling() * cscale, + this._pheight / this.zoomScaling() * cscale); + if (ranges[0][0] - dx > (this.panX() + panelDim[0] / 2)) x = ranges[0][1] + panelDim[0] / 2; + if (ranges[0][1] - dx < (this.panX() - panelDim[0] / 2)) x = ranges[0][0] - panelDim[0] / 2; + if (ranges[1][0] - dy > (this.panY() + panelDim[1] / 2)) y = ranges[1][1] + panelDim[1] / 2; + if (ranges[1][1] - dy < (this.panY() - panelDim[1] / 2)) y = ranges[1][0] - panelDim[1] / 2; } this.setPan(x - dx, y - dy); this._lastX = e.pageX; @@ -613,8 +612,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if (willZoom) { this.setScaleToZoom(doc, scale); } + console.log("Focused " + this.Document.title + " " + s); afterFocus && setTimeout(() => { if (afterFocus && afterFocus()) { + console.log("UnFocused " + this.Document.title + " " + s); this.Document.panX = px; this.Document.panY = py; this.Document.scale = s; diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index d7cb2585e..81b0249dd 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -2,7 +2,7 @@ import { observable, computed, action, runInAction, reaction, IReactionDisposer import React = require("react"); import { observer } from "mobx-react"; import { FieldViewProps, FieldView } from "../nodes/FieldView"; -import { Doc, DocListCastAsync } from "../../../new_fields/Doc"; +import { Doc, DocListCastAsync, Opt } from "../../../new_fields/Doc"; import { undoBatch } from "../../util/UndoManager"; import { NumCast, FieldValue, Cast, StrCast } from "../../../new_fields/Types"; import { CollectionViewType } from "../collections/CollectionBaseView"; @@ -195,9 +195,9 @@ export class LinkFollowBox extends React.Component { } - _addDocTab: (undefined | ((doc: Doc, dataDoc: Doc | undefined, where: string) => void)); + _addDocTab: (undefined | ((doc: Doc, dataDoc: Opt, where: string) => boolean)); - setAddDocTab = (addFunc: (doc: Doc, dataDoc: Doc | undefined, where: string) => void) => { + setAddDocTab = (addFunc: (doc: Doc, dataDoc: Opt, where: string) => boolean) => { this._addDocTab = addFunc; } @@ -211,7 +211,7 @@ export class LinkFollowBox extends React.Component { options.context.panX = newPanX; options.context.panY = newPanY; } - CollectionDockingView.Instance.AddRightSplit(options.context, undefined); + (this._addDocTab || this.props.addDocTab)(options.context, undefined, "onRight"); if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom }); @@ -224,7 +224,7 @@ export class LinkFollowBox extends React.Component { openLinkRight = () => { if (LinkFollowBox.destinationDoc) { let alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); - CollectionDockingView.Instance.AddRightSplit(alias, undefined); + (this._addDocTab || this.props.addDocTab)(alias, undefined, "onRight"); this.highlightDoc(); SelectionManager.DeselectAll(); } @@ -244,7 +244,7 @@ export class LinkFollowBox extends React.Component { let sourceContext = await Cast(proto.sourceContext, Doc); const shouldZoom = options ? options.shouldZoom : false; - let dockingFunc = (document: Doc) => { this._addDocTab && this._addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; + let dockingFunc = (document: Doc) => { (this._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; if (LinkFollowBox.destinationDoc === LinkFollowBox.linkDoc.anchor2 && targetContext) { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext); @@ -271,7 +271,7 @@ export class LinkFollowBox extends React.Component { if (LinkFollowBox.destinationDoc) { let fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc); // this.prosp.addDocTab is empty -- use the link source's addDocTab - this._addDocTab && this._addDocTab(fullScreenAlias, undefined, "inTab"); + (this._addDocTab || this.props.addDocTab)(fullScreenAlias, undefined, "inTab"); this.highlightDoc(); SelectionManager.DeselectAll(); @@ -288,7 +288,7 @@ export class LinkFollowBox extends React.Component { options.context.panX = newPanX; options.context.panY = newPanY; } - this._addDocTab && this._addDocTab(options.context, undefined, "inTab"); + (this._addDocTab || this.props.addDocTab)(options.context, undefined, "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 842ce45b1..27af873b5 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) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; } @observer diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index d711ac284..1891919ce 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -1,27 +1,25 @@ -import { action, observable } from "mobx"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action } from "mobx"; import { observer } from "mobx-react"; -import { DocumentView } from "../nodes/DocumentView"; -import { LinkMenuItem } from "./LinkMenuItem"; -import { LinkEditor } from "./LinkEditor"; -import './LinkMenu.scss'; -import React = require("react"); -import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Doc } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; -import { LinkManager } from "../../util/LinkManager"; -import { DragLinksAsDocuments, DragManager, SetupDrag } from "../../util/DragManager"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { emptyFunction } from "../../../Utils"; import { Docs } from "../../documents/Documents"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { DragManager, SetupDrag } from "../../util/DragManager"; +import { LinkManager } from "../../util/LinkManager"; import { UndoManager } from "../../util/UndoManager"; -import { StrCast } from "../../../new_fields/Types"; -import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; +import { DocumentView } from "../nodes/DocumentView"; +import './LinkMenu.scss'; +import { LinkMenuItem } from "./LinkMenuItem"; +import React = require("react"); interface LinkMenuGroupProps { sourceDoc: Doc; group: Doc[]; groupType: string; showEditor: (linkDoc: Doc) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; docView: DocumentView; } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 19a0023e9..82fe3df23 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -21,7 +21,7 @@ interface LinkMenuItemProps { sourceDoc: Doc; destinationDoc: Doc; showEditor: (linkDoc: Doc) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; } @observer diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4a37457c0..50691fd38 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -86,7 +86,7 @@ export interface DocumentViewProps { parentActive: () => boolean; whenActiveChanged: (isActive: boolean) => void; bringToFront: (doc: Doc, sendToBack?: boolean) => void; - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void; zoomToScale: (scale: number) => void; @@ -242,23 +242,13 @@ export class DocumentView extends DocComponent(Docu if (expandedDocs.length) { SelectionManager.DeselectAll(); let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace"); - if (altKey || ctrlKey) { - maxLocation = this.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" ? "inTab" : "inPlace")); - if (maxLocation === "inPlace") { - let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); - let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !d.isMinimized, false); - expandedDocs.forEach(maxDoc => maxDoc.isMinimized = false); - let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); - !hasView && expandedDocs.forEach(async maxDoc => this.props.addDocument && this.props.addDocument(maxDoc, false)); - expandedDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized); - } - } - if (maxLocation !== "inPlace" && CollectionDockingView.Instance) { - expandedDocs.forEach(maxDoc => - (!CollectionDockingView.Instance.CloseRightSplit(maxDoc) && this.props.addDocTab(maxDoc, undefined, maxLocation))); - } else { + maxLocation = this.Document.maximizeLocation = (!ctrlKey ? !altKey ? maxLocation : (maxLocation !== "inPlace" ? "inPlace" : "onRight") : (maxLocation !== "inPlace" ? "inPlace" : "inTab")); + if (maxLocation === "inPlace") { + expandedDocs.forEach(maxDoc => this.props.addDocument && this.props.addDocument(maxDoc, false)); let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2); this.collapseTargetsToPoint(scrpt, expandedDocs); + } else { + expandedDocs.forEach(maxDoc => (!this.props.addDocTab(maxDoc, undefined, "close") && this.props.addDocTab(maxDoc, undefined, maxLocation))); } } else if (linkedDocs.length) { @@ -277,7 +267,7 @@ export class DocumentView extends DocComponent(Docu let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionDoc) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined; DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, // 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 => this.props.focus(this.props.Document, true, 1, () => { this.props.addDocTab(doc, undefined, maxLocation); return true; }), + doc => this.props.focus(this.props.Document, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation)), linkedFwdPage[altKey ? 1 : 0], targetContext); } } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index faf11e9be..49fc2263d 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -39,7 +39,7 @@ export interface FieldViewProps { select: (isCtrlPressed: boolean) => void; renderDepth: number; addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; removeDocument?: (document: Doc) => boolean; moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index ee70942de..8fcd44f46 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -124,7 +124,7 @@ export class KeyValueBox extends React.Component { let i = 0; const self = this; for (let key of Object.keys(ids).slice().sort()) { - rows.push( { if (oldEl) self.rows.splice(self.rows.indexOf(oldEl), 1); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index c7e0f51d7..1fed4c8bb 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,7 +1,7 @@ import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { Doc, Field } from '../../../new_fields/Doc'; +import { Doc, Field, Opt } from '../../../new_fields/Doc'; import { emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { Transform } from '../../util/Transform'; @@ -22,6 +22,7 @@ export interface KeyValuePairProps { keyName: string; doc: Doc; keyWidth: number; + addDocTab: (doc: Doc, data: Opt, where: string) => boolean; } @observer export class KeyValuePair extends React.Component { @@ -45,7 +46,7 @@ export class KeyValuePair extends React.Component { if (value instanceof Doc) { e.stopPropagation(); e.preventDefault(); - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.Create.KVPDocument(value, { width: 300, height: 300 }); CollectionDockingView.Instance.AddRightSplit(kvp, undefined); }, icon: "layer-group" }); + 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.displayMenu(e.clientX, e.clientY); } } @@ -68,7 +69,7 @@ export class KeyValuePair extends React.Component { focus: emptyFunction, PanelWidth: returnZero, PanelHeight: returnZero, - addDocTab: returnZero, + addDocTab: returnFalse, pinToPres: returnZero, ContentScaling: returnOne }; diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 34e3b0931..a9fa883c8 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -1,20 +1,18 @@ import React = require("react"); import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc"; +import { Doc, DocListCast, HeightSym, WidthSym, Opt } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { DocumentManager } from "../../util/DocumentManager"; import PDFMenu from "./PDFMenu"; import "./Annotation.scss"; -import { scale } from "./PDFViewer"; -import { PresBox } from "../nodes/PresBox"; interface IAnnotationProps { anno: Doc; fieldExtensionDoc: Doc; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Opt, where: string) => boolean; pinToPres: (document: Doc) => void; } @@ -31,7 +29,7 @@ interface IRegionAnnotationProps { width: number; height: number; fieldExtensionDoc: Doc; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; document: Doc; } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index c508935f2..19ef713c2 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -35,7 +35,7 @@ interface IViewerProps { scrollTo: (y: number) => void; active: () => boolean; setPanY?: (n: number) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean; } diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index b2e886d95..96eefacc2 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -76,7 +76,7 @@ export class SelectorContextMenu extends React.Component { col.panX = newPanX; col.panY = newPanY; } - CollectionDockingView.Instance.AddRightSplit(col, undefined); + CollectionDockingView.AddRightSplit(col, undefined); }; } render() { @@ -110,7 +110,7 @@ export class LinkContextMenu extends React.Component { unHighlightDoc = (doc: Doc) => () => Doc.UnBrushDoc(doc); - getOnClick = (col: Doc) => () => CollectionDockingView.Instance.AddRightSplit(col, undefined); + getOnClick = (col: Doc) => () => CollectionDockingView.AddRightSplit(col, undefined); render() { return ( -- cgit v1.2.3-70-g09d2 From 9fbdb0088bb42235bb530602c5275e015f2609bd Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 23 Sep 2019 13:27:38 -0400 Subject: restructured link following to text regions --- src/client/documents/Documents.ts | 3 -- src/client/util/LinkManager.ts | 15 ------ src/client/util/RichTextSchema.tsx | 3 +- src/client/util/TooltipTextMenu.tsx | 25 ++++----- src/client/views/linking/LinkFollowBox.tsx | 8 ++- src/client/views/nodes/FormattedTextBox.tsx | 80 +++++++++++++---------------- 6 files changed, 53 insertions(+), 81 deletions(-) (limited to 'src/client/views/linking') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 079ff00db..4ae770e25 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -638,9 +638,6 @@ export namespace DocUtils { }); } export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", sourceContext?: Doc, id?: string, anchored1?: boolean) { - // if (LinkManager.Instance.doesLinkExist(source, target)) return undefined; - if (LinkManager.Instance.doesNormalLinkExist(source, target) && description !== "in-text link being created") return undefined; // normal describes the type of link attempting to be created - // if normal link already exists and !normal (in text link is not being created) then return let sv = DocumentManager.Instance.getDocumentView(source); if (sv && sv.props.ContainingCollectionDoc === target) return; if (target === CurrentUserUtils.UserDocument) return undefined; diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index b285b967b..8a668e8d8 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -238,21 +238,6 @@ export class LinkManager { return index !== -1; } - // checks if a normal link (i.e. no in-text link) exists with given anchors - public doesNormalLinkExist(anchor1: Doc, anchor2: Doc): boolean { - let allLinks = LinkManager.Instance.getAllLinks(); - let index = allLinks.findIndex(linkDoc => { - if ((Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor2)) || - (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor1))) { - console.log("guid: " + linkDoc.guid); - } - return (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor2) && linkDoc.guid === undefined) || - (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor1) && linkDoc.guid === undefined); - }); - return index !== -1; - } - - // finds the opposite anchor of a given anchor in a link //TODO This should probably return undefined if there isn't an opposite anchor //TODO This should also await the return value of the anchor so we don't filter out promises diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index ea31671ac..9d5ccffe9 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -253,8 +253,7 @@ export const marks: { [index: string]: MarkSpec } = { href: {}, location: { default: null }, title: { default: null }, - guid: { default: null }, - docref: { default: false } + docref: { default: false } // flags whether the linked text comes from a document within Dash. If so, an attribution label is appended after the text }, inclusive: false, parseDOM: [{ diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index c84d98df9..987bc4f58 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -302,16 +302,16 @@ export class TooltipTextMenu { { handlers: { dragComplete: action(() => { - let linkDoc = dragData.linkDocument; - let guid = Utils.GenerateGuid(); - let proto = Doc.GetProto(linkDoc); - if (proto && docView) { - proto.sourceContext = docView.props.ContainingCollectionDoc; - } - linkDoc.guid = guid; - let text = this.makeLink(Utils.prepend("/doc/" + linkDoc[Id]), ctrlKey ? "onRight" : "inTab", guid); - if (linkDoc instanceof Doc && linkDoc.anchor2 instanceof Doc) { - proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODODO open to more descriptive descriptions of following in text link + if (dragData.linkDocument) { + let linkDoc = dragData.linkDocument; + let proto = Doc.GetProto(linkDoc); + if (proto && docView) { + proto.sourceContext = docView.props.ContainingCollectionDoc; + } + let text = this.makeLink(linkDoc, ctrlKey ? "onRight" : "inTab"); + if (linkDoc instanceof Doc && linkDoc.anchor2 instanceof Doc) { + proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODODO open to more descriptive descriptions of following in text link + } } }), }, @@ -398,9 +398,10 @@ export class TooltipTextMenu { // let link = state.schema.mark(state.schema.marks.link, { href: target, location: location }); // } - makeLink = (target: string, location: string, guid?: string): string => { + makeLink = (targetDoc: Doc, location: string): string => { + let target = Utils.prepend("/doc/" + targetDoc[Id]); let node = this.view.state.selection.$from.nodeAfter; - let link = this.view.state.schema.mark(this.view.state.schema.marks.link, { href: target, location: location, guid: guid }); + let link = this.view.state.schema.mark(this.view.state.schema.marks.link, { href: target, location: location, guid: targetDoc[Id] }); this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link)); this.view.dispatch(this.view.state.tr.addMark(this.view.state.selection.from, this.view.state.selection.to, link)); node = this.view.state.selection.$from.nodeAfter; diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 1280ae28b..cad404d1f 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -243,7 +243,7 @@ export class LinkFollowBox extends React.Component { let proto = Doc.GetProto(LinkFollowBox.linkDoc); let targetContext = await Cast(proto.targetContext, Doc); let sourceContext = await Cast(proto.sourceContext, Doc); - let guid = StrCast(LinkFollowBox.linkDoc.guid); + let guid = StrCast(LinkFollowBox.linkDoc[Id]); const shouldZoom = options ? options.shouldZoom : false; let dockingFunc = (document: Doc) => { (this._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; @@ -255,12 +255,10 @@ export class LinkFollowBox extends React.Component { DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!)); if (LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc) { if (guid) { - LinkFollowBox.destinationDoc.guid = guid; + let views = DocumentManager.Instance.getDocumentViews(jumpToDoc); + views.length && (views[0].props.Document.scrollToLinkID = guid); } else { jumpToDoc.linkHref = Utils.prepend("/doc/" + StrCast(LinkFollowBox.linkDoc[Id])); - let newguid = Utils.GenerateGuid(); - LinkFollowBox.linkDoc.guid = newguid; - LinkFollowBox.destinationDoc.guid = newguid; } } } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 53f28ac00..0a8b841a9 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -80,6 +80,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe private _nodeClicked: any; private _undoTyping?: UndoManager.Batch; private _searchReactionDisposer?: Lambda; + private _guidReactionDisposer: Opt; private _reactionDisposer: Opt; private _textReactionDisposer: Opt; private _heightReactionDisposer: Opt; @@ -139,66 +140,50 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe DragManager.StartDragFunctions.push(() => FormattedTextBox.InputBoxOverlay = undefined); } - this.props.Document.guid = undefined; - this.props.Document.linkHref = undefined; - - reaction( - () => StrCast(this.props.Document.guid), - async (guid) => { - let start = -1; - let href = this.props.Document.linkHref; - - if (this._editorView && guid) { - let editor = this._editorView; - let ret = findLinkFrag(editor.state.doc.content, editor); - - if (ret.frag.size > 2) { - let tr; - if (ret.frag.firstChild) { - let between = TextSelection.between(editor.state.doc.resolve(ret.start + 2), editor.state.doc.resolve(ret.start + ret.frag.firstChild.nodeSize)); - tr = editor.state.tr.setSelection(between); - } else { - let near = TextSelection.near(editor.state.doc.resolve(ret.start)); - tr = editor.state.tr.setSelection(near); - } - - editor.focus(); - editor.dispatch(tr.scrollIntoView()); - editor.dispatch(tr.scrollIntoView()); // bcz: sometimes selection doesn't fully scroll into view on smaller text boxes <5 lines visibility -- hopefully avoidable by ppl just not using small boxes...? - - this.props.Document.guid = undefined; - this.props.Document.linkHref = undefined; - } - } - - function findLinkFrag(frag: Fragment, editor: EditorView) { + this._guidReactionDisposer = reaction( + () => StrCast(this.props.Document.scrollToLinkID), + async (scrollToLinkID) => { + let findLinkFrag = (frag: Fragment, editor: EditorView) => { const nodes: Node[] = []; frag.forEach((node, index) => { let examinedNode = findLinkNode(node, editor); - if (examinedNode && examinedNode.textContent !== "") { + if (examinedNode && examinedNode.textContent) { nodes.push(examinedNode); start += index; } }); return { frag: Fragment.fromArray(nodes), start: start }; } - function findLinkNode(node: Node, editor: EditorView) { + let findLinkNode = (node: Node, editor: EditorView) => { if (!node.isText) { const content = findLinkFrag(node.content, editor); return node.copy(content.frag); } const marks = [...node.marks]; - const linkIndex = marks.findIndex(mark => mark.type.name === "link"); - if (linkIndex !== -1) { - if (guid === marks[linkIndex].attrs.guid) { - return node; - } else if (href && href === marks[linkIndex].attrs.href) { // retroactively fixing old in-text links by adding guid - marks[linkIndex].attrs.guid = guid; - return node; + const linkIndex = marks.findIndex(mark => mark.type === editor.state.schema.marks.link); + return linkIndex !== -1 && scrollToLinkID === marks[linkIndex].attrs.href.replace(/.*\/doc\//, "") ? node : undefined; + } + + let start = -1; + + if (this._editorView && scrollToLinkID) { + let editor = this._editorView; + let ret = findLinkFrag(editor.state.doc.content, editor); + + if (ret.frag.size > 2 && ((!this.props.isOverlay && !this.props.isSelected()) || (this.props.isSelected() && this.props.isOverlay))) { + let selection = TextSelection.near(editor.state.doc.resolve(ret.start)); // default to near the start + if (ret.frag.firstChild) { + selection = TextSelection.between(editor.state.doc.resolve(ret.start + 2), editor.state.doc.resolve(ret.start + ret.frag.firstChild.nodeSize)); // bcz: looks better to not have the target selected } + editor.dispatch(editor.state.tr.setSelection(new TextSelection(selection.$from, selection.$from)).scrollIntoView()); + const mark = editor.state.schema.mark(this._editorView.state.schema.marks.search_highlight); + setTimeout(() => editor.dispatch(editor.state.tr.addMark(selection.from, selection.to, mark)), 0); + setTimeout(() => this.unhighlightSearchTerms(), 2000); + + this.props.Document.scrollToLinkID = undefined; } - return undefined; } + } ); } @@ -759,6 +744,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this._editorView && this._editorView.destroy(); this._editorView = new EditorView(this._proseRef, { state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), + handleScrollToSelection: (editorView) => { + let ref = editorView.domAtPos(editorView.state.selection.from); + let r1 = (ref.node as any).getBoundingClientRect(); + let r3 = self._ref.current!.getBoundingClientRect(); + self._ref.current!.scrollTop += (r1.top - r3.top) * self.props.ScreenToLocalTransform().Scale; + return true; + }, dispatchTransaction: this.dispatchTransaction, nodeViews: { image(node, view, getPos) { return new ImageResizeView(node, view, getPos, self.props.addDocTab); }, @@ -799,6 +791,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } componentWillUnmount() { + this._guidReactionDisposer && this._guidReactionDisposer(); this._rulesReactionDisposer && this._rulesReactionDisposer(); this._reactionDisposer && this._reactionDisposer(); this._proxyReactionDisposer && this._proxyReactionDisposer(); @@ -823,7 +816,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let ctrlKey = e.ctrlKey; if (e.button === 0 && ((!this.props.isSelected() && !e.ctrlKey) || (this.props.isSelected() && e.ctrlKey)) && !e.metaKey && e.target) { let href = (e.target as any).href; - let guid = (e.target as any).guid; let location: string; if ((e.target as any).attributes.location) { location = (e.target as any).attributes.location.value; -- cgit v1.2.3-70-g09d2