From 90bf9ea9e32ed695a36d0334e99fd859bbe51c15 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 10 Nov 2022 19:59:13 -0500 Subject: made alternate image use a field data-useAlt. added alt images to preselements. fixed removing TabDoc documentviews from document view list. added playing audio tags to preselements --- src/client/views/nodes/formattedText/DashDocView.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/nodes/formattedText/DashDocView.tsx') diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index 63ee7d1f3..722d0cc4f 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -45,6 +45,7 @@ export class DashDocView { ); } destroy() { + this.root.unmount(); // ReactDOM.unmountComponentAtNode(this.dom); } selectNode() {} -- cgit v1.2.3-70-g09d2 From 32f5040c44dc302e3dd53cecd9be4cd51a474d3f Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 14 Feb 2023 14:57:25 -0500 Subject: fixed pinning regions on pdf/web pages to allow proper pres following. added click on pres item# to select w/o navigation. fixed dashDocView to be selectable without losing selection to parent textbox. added BingMaps rudimentary option to googleMaps --- package-lock.json | 18 ++- package.json | 2 + src/client/views/nodes/MapBox/MapBox.tsx | 148 +++++++++++++-------- src/client/views/nodes/PDFBox.tsx | 1 + src/client/views/nodes/WebBox.tsx | 1 + .../views/nodes/formattedText/DashDocView.tsx | 5 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 3 + src/client/views/nodes/trails/PresBox.tsx | 20 +-- src/client/views/nodes/trails/PresElementBox.scss | 6 + src/client/views/nodes/trails/PresElementBox.tsx | 12 +- 10 files changed, 143 insertions(+), 73 deletions(-) (limited to 'src/client/views/nodes/formattedText/DashDocView.tsx') diff --git a/package-lock.json b/package-lock.json index 547a6e1d7..95a128419 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3675,6 +3675,11 @@ "file-uri-to-path": "1.0.0" } }, + "bingmaps-react": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/bingmaps-react/-/bingmaps-react-1.2.10.tgz", + "integrity": "sha512-fM887Sr6OIlo6ThmSpGfNEDssSytdnsMrbDTDs+YH/43etf0dlfcR4oaJvygy+fwn21hpP2lVvwTHUDZvGxZqA==" + }, "bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -4970,9 +4975,9 @@ } }, "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.28.0.tgz", + "integrity": "sha512-GiZn9D4Z/rSYvTeg1ljAIsEqFm0LaN9gVtwDCrKL80zHtS31p9BAjmTxVqTQDMpwlMolJZOFntUG2uwyj7DAqw==" }, "core-js-pure": { "version": "3.22.8", @@ -8260,6 +8265,13 @@ "promise": "^7.1.1", "setimmediate": "^1.0.5", "ua-parser-js": "^0.7.30" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==" + } } }, "fd-slicer": { diff --git a/package.json b/package.json index 712354355..00ce356f9 100644 --- a/package.json +++ b/package.json @@ -165,6 +165,7 @@ "bcrypt-nodejs": "0.0.3", "bezier-curve": "^1.0.0", "bezier-js": "^4.1.1", + "bingmaps-react": "^1.2.10", "bluebird": "^3.7.2", "body-parser": "^1.19.2", "bootstrap": "^4.6.1", @@ -181,6 +182,7 @@ "connect-mongo": "^2.0.3", "cookie-parser": "^1.4.6", "cookie-session": "^2.0.0", + "core-js": "^3.28.0", "cors": "^2.8.5", "depcheck": "^0.9.2", "equation-editor-react": "github:bobzel/equation-editor-react#useLocally", diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 5940fc075..039f11cd1 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -1,5 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Autocomplete, GoogleMap, GoogleMapProps, Marker } from '@react-google-maps/api'; +import BingMapsReact from 'bingmaps-react'; import { action, computed, IReactionDisposer, observable, ObservableMap, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; @@ -43,20 +44,22 @@ const mapContainerStyle = { }; const defaultCenter = { - lat: 38.685, - lng: -115.234, + lat: 42.360081, + lng: -71.058884, }; const mapOptions = { fullscreenControl: false, }; +const bingApiKey = process.env.BING_MAPS; // if you're running local, get a Bing Maps api key here: https://www.bingmapsportal.com/ and then add it to the .env file in the Dash-Web root directory as: _CLIENT_BING_MAPS= const apiKey = process.env.GOOGLE_MAPS; const script = document.createElement('script'); script.defer = true; script.async = true; script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places,drawing`; +console.log(script.src); document.head.appendChild(script); /** @@ -84,6 +87,7 @@ const options = { @observer export class MapBox extends ViewBoxAnnotatableComponent>() { + static UseBing = true; private _dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; private _annotationLayer: React.RefObject = React.createRef(); @@ -551,69 +555,99 @@ export class MapBox extends ViewBoxAnnotatableComponent this.props.PanelHeight() / 5; anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; savedAnnotations = () => this._savedAnnotations; + + _bingSearchManager: any; + _bingMap: any; + get MicrosoftMaps() { + return (window as any).Microsoft.Maps; + } + // uses Bing Search to retrieve lat/lng for a location. eg., + // const results = this.geocodeQuery(map.map, 'Philadelphia, PA'); + // to move the map to that location: + // const location = await this.geocodeQuery(this._bingMap, 'Philadelphia, PA'); + // this._bingMap.current.setView({ + // mapTypeId: this.MicrosoftMaps.MapTypeId.aerial, + // center: new this.MicrosoftMaps.Location(loc.latitude, loc.longitude), + // }); + // + bingGeocode = (map: any, query: string) => { + return new Promise<{ latitude: number; longitude: number }>((res, reject) => { + //If search manager is not defined, load the search module. + if (!this._bingSearchManager) { + //Create an instance of the search manager and call the geocodeQuery function again. + this.MicrosoftMaps.loadModule('Microsoft.Maps.Search', () => { + this._bingSearchManager = new this.MicrosoftMaps.Search.SearchManager(map.current); + res(this.bingGeocode(map, query)); + }); + } else { + this._bingSearchManager.geocode({ + where: query, + callback: action((r: any) => { + res(r.results[0].location); + }), + errorCallback: (e: any) => reject(), + }); + } + }); + }; + + bingViewOptions = { + center: { latitude: defaultCenter.lat, longitude: defaultCenter.lng }, + mapTypeId: 'grayscale', + }; + bingMapOptions = { + navigationBarMode: 'square', + }; + bingMapReady = (map: any) => (this._bingMap = map.map); render() { const renderAnnotations = (docFilters?: () => string[]) => null; - // bcz: commmented this out. Otherwise, any documents that are rendered with an InfoWindow of a marker - // will also be rendered as freeform annotations on the map. However, it doesn't seem that rendering - // freeform documents on the map does anything anyway, so getting rid of it for now. Also, since documents - // are rendered twice, adding a new note to the InfoWindow loses focus immediately on creation since it gets - // shifted to the non-visible view of the document in this freeform view. - // ; return (
- {/*console.log(apiKey)*/} - {/* */} -
e.stopPropagation()} onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()} style={{ width: `calc(100% - ${this.sidebarWidthPercent})` }}> +
e.stopPropagation()} + onPointerDown={async e => { + e.button === 0 && !e.ctrlKey && e.stopPropagation(); + // just a simple test of bing maps geocode api + // const loc = await this.bingGeocode(this._bingMap, 'Philadelphia, PA'); + // this._bingMap.current.setView({ + // mapTypeId: this.MicrosoftMaps.MapTypeId.aerial, + // center: new this.MicrosoftMaps.Location(loc.latitude, loc.longitude), + // zoom: 15, + // }); + }} + style={{ width: `calc(100% - ${this.sidebarWidthPercent})` }}>
{renderAnnotations(this.transparentFilter)}
{renderAnnotations(this.opaqueFilter)} {SnappingManager.GetIsDragging() ? null : renderAnnotations()} {this.annotationLayer} - - - e.stopPropagation()} placeholder="Enter location" /> - - - {this.renderMarkers()} - {this.allMapMarkers - .filter(marker => marker.infoWindowOpen) - .map(marker => ( - - ))} - {/* {this.handleMapCenter(this._map)} */} - + + {!MapBox.UseBing ? null : } +
+ + + e.stopPropagation()} placeholder="Enter location" /> + + + {this.renderMarkers()} + {this.allMapMarkers + .filter(marker => marker.infoWindowOpen) + .map(marker => ( + + ))} + {/* {this.handleMapCenter(this._map)} */} + +
{!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? null : ( { Document={this._finalLayout} DataDoc={this._resolvedDataDoc} addDocument={returnFalse} - rootSelected={this._textBox.props.isSelected} + rootSelected={returnFalse} //{this._textBox.props.isSelected} removeDocument={this.removeDoc} isDocumentActive={returnFalse} - isContentActive={this._textBox.props.isContentActive} + isContentActive={emptyFunction} styleProvider={this._textBox.props.styleProvider} docViewPath={this._textBox.props.docViewPath} ScreenToLocalTransform={this.getDocTransform} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 80b18b8b9..49acd8a57 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1487,6 +1487,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent node that wraps the hyerlink while (target && !target.dataset?.targethrefs) target = target.parentElement; FormattedTextBoxComment.update(this, editor, undefined, target?.dataset?.targethrefs, target?.dataset.linkdoc, target?.dataset.nopreview === 'true'); + if (pcords && pcords.inside > 0 && this._editorView.state.doc.nodeAt(pcords.inside)?.type === this._editorView.state.schema.nodes.dashDoc) { + return; + } } if (e.button === 0 && this.props.isSelected(true) && !e.altKey) { diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 0a96297b7..e07517113 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -14,7 +14,7 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Ty import { AudioField } from '../../../../fields/URLField'; import { emptyFunction, emptyPath, returnFalse, returnOne, setupMoveUpEvents, StopEvent } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; -import { Docs } from '../../../documents/Documents'; +import { Docs, DocumentOptions } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { DocumentManager } from '../../../util/DocumentManager'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; @@ -869,13 +869,13 @@ export class PresBox extends ViewBoxBaseComponent() { presDocView && SelectionManager.SelectView(presDocView, false); }; + focusElement = (doc: Doc, options: DocFocusOptions) => this.selectElement(doc); + //Regular click @action - selectElement = async (doc: Doc) => { + selectElement = async (doc: Doc, noNav = false) => { CollectionStackedTimeline.CurrentlyPlaying?.map((clip, i) => DocumentManager.Instance.getDocumentView(clip)?.ComponentView?.Pause?.()); - this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem); - // if (doc.presPinView) setTimeout(() => this.updateCurrentPresentation(DocCast(doc.context)), 0); - // else + !noNav && this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem); this.updateCurrentPresentation(DocCast(doc.context)); }; @@ -911,19 +911,19 @@ export class PresBox extends ViewBoxBaseComponent() { //regular click @action - regularSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, selectPres = true) => { + regularSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, selectPres = true, noNav = false) => { this.clearSelectedArray(); this.addToSelectedArray(doc); this._eleArray.splice(0, this._eleArray.length, ref); this._dragArray.splice(0, this._dragArray.length, drag); - focus && this.selectElement(doc); + focus && this.selectElement(doc, noNav); selectPres && this.selectPres(); }; - modifierSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, cmdClick: boolean, shiftClick: boolean) => { + modifierSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, cmdClick: boolean, shiftClick: boolean, noNav: boolean = false) => { if (cmdClick) this.multiSelect(doc, ref, drag); else if (shiftClick) this.shiftSelect(doc, ref, drag); - else this.regularSelect(doc, ref, drag, focus); + else this.regularSelect(doc, ref, drag, focus, noNav); }; static keyEventsWrapper = (e: KeyboardEvent) => PresBox.Instance?.keyEvents(e); @@ -2253,7 +2253,7 @@ export class PresBox extends ViewBoxBaseComponent() { filterAddDocument={this.addDocumentFilter} removeDocument={returnFalse} dontRegisterView={true} - focus={this.selectElement} + focus={this.focusElement} scriptContext={this} ScreenToLocalTransform={this.getTransform} AddToMap={this.AddToMap} diff --git a/src/client/views/nodes/trails/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss index 415253af1..4f95f0c1f 100644 --- a/src/client/views/nodes/trails/PresElementBox.scss +++ b/src/client/views/nodes/trails/PresElementBox.scss @@ -44,6 +44,12 @@ $slide-active: #5b9fdd; display: flex; align-items: center; + .presItem-number { + cursor: pointer; + &:hover { + background-color: $light-blue; + } + } .presItem-name { display: flex; min-width: 20px; diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 788900b46..f265c1315 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -592,7 +592,17 @@ export class PresElementBox extends ViewBoxBaseComponent() { width: `calc(100% ${this.rootDoc.presExpandInlineButton ? '- 50%' : ''} - ${this.presButtons.length * 22}px`, cursor: isSelected ? 'text' : 'grab', }}> -
{`${this.indexInPres + 1}. `}
+
{ + e.stopPropagation(); + if (this._itemRef.current && this._dragRef.current) { + this.presBoxView?.modifierSelect(activeItem, this._itemRef.current, this._dragRef.current, false, false, false, true); + } + }} + onClick={e => e.stopPropagation()}>{`${this.indexInPres + 1}. `}
StrCast(activeItem.title)} SetValue={this.onSetValue} />
{/*
{"Movement speed"}
}>
{this.transition}
*/} -- cgit v1.2.3-70-g09d2 From b25f333713706a7456ab418960082bcabe830f11 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 20 Mar 2023 20:48:38 -0400 Subject: fixed copying of docs with template layout docs. fixed clone to search through RTFs for referenced documents to clone. renamed nested documents docId instead of docid for consistency with other nested field ids. --- src/client/util/CurrentUserUtils.ts | 6 +-- src/client/views/GlobalKeyHandler.ts | 2 +- src/client/views/SidebarAnnos.tsx | 4 +- src/client/views/collections/CollectionSubView.tsx | 10 ++--- src/client/views/nodes/DocumentView.tsx | 6 +-- .../nodes/formattedText/DashDocCommentView.tsx | 16 ++++---- .../views/nodes/formattedText/DashDocView.tsx | 16 ++++---- .../views/nodes/formattedText/DashFieldView.tsx | 8 ++-- .../views/nodes/formattedText/FormattedTextBox.tsx | 8 ++-- .../views/nodes/formattedText/RichTextRules.ts | 26 ++++++------ src/client/views/nodes/formattedText/nodes_rts.ts | 8 ++-- src/fields/Doc.ts | 46 ++++++++++++++-------- src/fields/RichTextField.ts | 26 ++++++------ src/fields/RichTextUtils.ts | 10 ++--- 14 files changed, 103 insertions(+), 89 deletions(-) (limited to 'src/client/views/nodes/formattedText/DashDocView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2820c66ee..c038fd6ab 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -148,7 +148,7 @@ export class CurrentUserUtils { { noteType: "Idea", backgroundColor: "pink", icon: "lightbulb" }, { noteType: "Topic", backgroundColor: "lightblue", icon: "book-open" }]; const reqdNoteList = reqdTempOpts.map(opts => { - const reqdOpts = {...opts, title: "text", width:200, autoHeight: true, fitWidth: true, system: true}; + const reqdOpts = {...opts, title: "text", width:200, autoHeight: true, fitWidth: true}; const noteType = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.noteType === opts.noteType): undefined; return DocUtils.AssignOpts(noteType, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts), true, opts.noteType??"Note"); }); @@ -224,11 +224,11 @@ export class CurrentUserUtils { { type: "paragraph", attrs: {}, content: [{ type: "dashField", - attrs: { fieldKey: "author", docid: "", hideKey: false }, + attrs: { fieldKey: "author", docId: "", hideKey: false }, marks: [{ type: "strong" }] }, { type: "dashField", - attrs: { fieldKey: "creationDate", docid: "", hideKey: false }, + attrs: { fieldKey: "creationDate", docId: "", hideKey: false }, marks: [{ type: "strong" }] }] }] diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index f849b21e3..0f8b46dbe 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -372,7 +372,7 @@ export class KeyManager { list.push(doc); } if (count === docids.length) { - const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => (clone ? (await Doc.MakeClone(d, ['links'])).clone : d))); + const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => (clone ? (await Doc.MakeClone(d, true)).clone : d))); if (added.length) { added.map(doc => (doc.context = targetDataDoc)); undoBatch(() => { diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 7519cbb05..02dd15960 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -84,7 +84,7 @@ export class SidebarAnnos extends React.Component { Doc.GetProto(target)[key] = val; return { type: 'dashField', - attrs: { fieldKey: key, docid: '', hideKey: false, editable: true }, + attrs: { fieldKey: key, docId: '', hideKey: false, editable: true }, marks: [{ type: 'pFontSize', attrs: { fontSize: '12px' } }, { type: 'strong' }, { type: 'user_mark', attrs: { userid: Doc.CurrentUserEmail, modified: 0 } }], }; }); @@ -111,7 +111,7 @@ export class SidebarAnnos extends React.Component { { type: 'pFontSize', attrs: { fontSize: '8px' } }, { type: 'em' }, ], - attrs: { fieldKey: 'text', docid: anchor[Id], hideKey: true, editable: false }, + attrs: { fieldKey: 'text', docId: anchor[Id], hideKey: true, editable: false }, }, ], }, diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index e46220f02..bd74c9399 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -269,10 +269,10 @@ export function CollectionSubView(moreProps?: X) { if (FormattedTextBox.IsFragment(html)) { const href = FormattedTextBox.GetHref(html); if (href) { - const docid = FormattedTextBox.GetDocFromUrl(href); - if (docid) { + const docId = FormattedTextBox.GetDocFromUrl(href); + if (docId) { // prosemirror text containing link to dash document - DocServer.GetRefField(docid).then(f => { + DocServer.GetRefField(docId).then(f => { if (f instanceof Doc) { if (options.x || options.y) { f.x = options.x as number; @@ -311,8 +311,8 @@ export function CollectionSubView(moreProps?: X) { } else { const path = window.location.origin + '/doc/'; if (text.startsWith(path)) { - const docid = text.replace(Doc.globalServerPath(), '').split('?')[0]; - DocServer.GetRefField(docid).then(f => { + const docId = text.replace(Doc.globalServerPath(), '').split('?')[0]; + DocServer.GetRefField(docId).then(f => { if (f instanceof Doc) { if (options.x || options.y) { f.x = options.x as number; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 36e8facf5..edf508c95 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1578,8 +1578,8 @@ export class DocumentView extends React.Component { } public static showBackLinks(linkSource: Doc) { - const docid = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + '-pivotish'; - DocServer.GetRefField(docid).then(docx => { + const docId = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + '-pivotish'; + DocServer.GetRefField(docId).then(docx => { const rootAlias = () => { const rootAlias = Doc.MakeAlias(linkSource); rootAlias.x = rootAlias.y = 0; @@ -1592,7 +1592,7 @@ export class DocumentView extends React.Component { /*rootAlias()*/ ], { title: linkSource.title + '-pivot', _width: 500, _height: 500 }, - docid + docId ); linkCollection.linkSource = linkSource; if (!linkCollection.reactionScript) linkCollection.reactionScript = ScriptField.MakeScript('updateLinkCollection(self)'); diff --git a/src/client/views/nodes/formattedText/DashDocCommentView.tsx b/src/client/views/nodes/formattedText/DashDocCommentView.tsx index fcd6e0c55..aa269d8d6 100644 --- a/src/client/views/nodes/formattedText/DashDocCommentView.tsx +++ b/src/client/views/nodes/formattedText/DashDocCommentView.tsx @@ -32,7 +32,7 @@ export class DashDocCommentView { }; this.root = ReactDOM.createRoot(this.dom); - this.root.render(); + this.root.render(); (this as any).dom = this.dom; } @@ -48,7 +48,7 @@ export class DashDocCommentView { } interface IDashDocCommentViewInternal { - docid: string; + docId: string; view: any; getPos: any; } @@ -63,13 +63,13 @@ export class DashDocCommentViewInternal extends React.Component dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); + DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); e.preventDefault(); e.stopPropagation(); } onPointerEnterCollapsed(e: any) { - DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); + DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); e.preventDefault(); e.stopPropagation(); } @@ -82,7 +82,7 @@ export class DashDocCommentViewInternal extends React.Component { - expand && DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); + expand && DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); try { this.props.view.dispatch(this.props.view.state.tr.setSelection(TextSelection.create(this.props.view.state.tr.doc, this.props.getPos() + (expand ? 2 : 1)))); } catch (e) {} @@ -100,12 +100,12 @@ export class DashDocCommentViewInternal extends React.Component { try { @@ -119,7 +119,7 @@ export class DashDocCommentViewInternal extends React.Component
}>
(DocumentV (link.linkDisplay = !ScriptCast(this.props.views().lastElement()?.rootDoc.onClick)?.script.originalScript.includes('followLink('))} + linkCreated={link => (link.linkDisplay = !IsFollowLinkScript(this.props.views().lastElement()?.rootDoc.onClick))} linkCreateAnchor={() => this.props.views().lastElement()?.ComponentView?.getAnchor?.(true)} linkFrom={() => this.props.views().lastElement()?.rootDoc} /> diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 9bc583ce5..9ffbe083f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -32,6 +32,7 @@ import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { ImageBox } from './nodes/ImageBox'; import React = require('react'); import { RichTextField } from '../../fields/RichTextField'; +import { LinkFollower } from '../util/LinkFollower'; @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> { @@ -83,10 +84,9 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P ); } - @observable overrideBounds = false; @computed get Bounds() { - if (this.overrideBounds) return { x: 0, y: 0, r: 0, b: 0 }; + if (LinkFollower.IsFollowing) return { x: 0, y: 0, r: 0, b: 0 }; const views = SelectionManager.Views(); return views .filter(dv => dv.props.renderDepth > 0) @@ -908,7 +908,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P {this._isRotating ? null : ( tap to set rotate center, drag to rotate
}>
e.preventDefault()}> - } isCircle={true} hoverStyle={'lighten'} backgroundColor={Colors.DARK_GRAY} color={Colors.LIGHT_GRAY} /> + } color={Colors.LIGHT_GRAY} />
)} diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 6b4f8ad85..ede387927 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -15,6 +15,7 @@ import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { AnchorMenu } from './pdf/AnchorMenu'; import React = require('react'); import { ScriptField } from '../../fields/ScriptField'; +import { FollowLinkScript } from '../util/LinkFollower'; const _global = (window /* browser */ || global) /* node */ as any; export interface MarqueeAnnotatorProps { @@ -148,7 +149,7 @@ export class MarqueeAnnotator extends React.Component { const anno = savedAnnos[0]; const containerOffset = this.props.containerOffset?.() || [0, 0]; const marqueeAnno = Docs.Create.FreeformDocument([], { - onClick: isLinkButton ? ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }) : undefined, + onClick: isLinkButton ? FollowLinkScript() : undefined, backgroundColor: color, annotationOn: this.props.rootDoc, title: 'Annotation on ' + this.props.rootDoc.title, diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 0723966e1..031d501ad 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -21,6 +21,7 @@ import { DocumentView, OpenWhere } from './nodes/DocumentView'; import { pasteImageBitmap } from './nodes/WebBoxRenderer'; import './PropertiesButtons.scss'; import React = require('react'); +import { IsFollowLinkScript } from '../util/LinkFollower'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -289,7 +290,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { .filter(dv => dv.docView) .map(dv => dv.docView!) .forEach(docView => { - const linkButton = ScriptCast(docView.props.Document.onClick)?.script.originalScript.includes('followLink('); + const linkButton = IsFollowLinkScript(docView.props.Document.onClick); docView.noOnClick(); switch (onClick) { case 'enterPortal': @@ -327,7 +328,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { ]; const list = buttonList.map(value => { const click = () => this.handleOptionChange(value[0]); - const linkButton = BoolCast(ScriptCast(this.selectedDoc.onClick)?.script.originalScript.includes('followLink(')); + const linkButton = IsFollowLinkScript(this.selectedDoc.onClick); const followLoc = this.selectedDoc._followLinkLocation; const linkedToLightboxView = () => LinkManager.Links(this.selectedDoc).some(link => LinkManager.getOppositeAnchor(link, this.selectedDoc)?._isLightbox); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 8d67f0528..b950b4860 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -1,13 +1,15 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; import { Shadows } from 'browndash-components'; import { action, runInAction } from 'mobx'; import { extname } from 'path'; import { Doc, Opt, StrListCast } from '../../fields/Doc'; -import { BoolCast, Cast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; +import { BoolCast, Cast, ImageCast, NumCast, StrCast } from '../../fields/Types'; import { DashColor, lightOrDark, Utils } from '../../Utils'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocFocusOrOpen, DocumentManager } from '../util/DocumentManager'; +import { IsFollowLinkScript } from '../util/LinkFollower'; import { LinkManager } from '../util/LinkManager'; import { SelectionManager } from '../util/SelectionManager'; import { ColorScheme, SettingsManager } from '../util/SettingsManager'; @@ -18,13 +20,10 @@ import { InkingStroke } from './InkingStroke'; import { MainView } from './MainView'; import { DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; +import { KeyValueBox } from './nodes/KeyValueBox'; import { SliderBox } from './nodes/SliderBox'; import './StyleProvider.scss'; import React = require('react'); -import { KeyValueBox } from './nodes/KeyValueBox'; -import { listSpec } from '../../fields/Schema'; -import { AudioField } from '../../fields/URLField'; -import { Tooltip } from '@material-ui/core'; export enum StyleProp { TreeViewIcon = 'treeViewIcon', @@ -279,8 +278,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt { - if (ScriptCast(anchorDoc.onClick)?.script.originalScript.includes('followLink(')) { + if (IsFollowLinkScript(anchorDoc.onClick)) { LinkFollower.FollowLink(undefined, anchorDoc, false); } const seekTimeInSeconds = this.anchorStart(anchorDoc) - 0.05; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 2d12005fb..dbcfe43cf 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -146,7 +146,7 @@ export class DocumentContentsView extends React.Component< (this.props.LayoutTemplateString && this.props.Document) || (this.props.layoutKey && StrCast(this.props.Document[this.props.layoutKey]) && this.props.Document) || Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined); - return Doc.expandTemplateLayout(template, this.props.Document, this.props.layoutKey); + return Doc.expandTemplateLayout(template, this.props.Document); } CreateBindings(onClick: Opt, onInput: Opt): JsxBindings { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a39c3cf8f..f161a7b9b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -22,7 +22,7 @@ import { DictationManager } from '../../util/DictationManager'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; import { InteractionUtils } from '../../util/InteractionUtils'; -import { LinkFollower } from '../../util/LinkFollower'; +import { FollowLinkScript, LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; @@ -560,14 +560,14 @@ export class DocumentViewInternal extends DocComponent { const hadOnClick = this.rootDoc.onClick; this.noOnClick(); - this.Document.onClick = hadOnClick ? undefined : ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }); + this.Document.onClick = hadOnClick ? undefined : FollowLinkScript(); this.Document.waitForDoubleClickToClick = hadOnClick ? undefined : 'never'; }; @undoBatch @action followLinkOnClick = (): void => { this.Document.ignoreClick = false; - this.Document.onClick = ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }); + this.Document.onClick = FollowLinkScript(); this.Document.followLinkToggle = false; this.Document.followLinkZoom = false; this.Document.followLinkLocation = undefined; @@ -623,7 +623,7 @@ export class DocumentViewInternal extends DocComponent { diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 83ad5628c..b144c9318 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -34,6 +34,7 @@ import { RecordingBox } from './RecordingBox'; import { PinProps, PresBox } from './trails'; import './VideoBox.scss'; import { ScriptField } from '../../../fields/ScriptField'; +import { FollowLinkScript } from '../../util/LinkFollower'; const path = require('path'); /** @@ -325,7 +326,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { updateDoc = action((dashDoc: Doc) => { this._dashDoc = dashDoc; - this._finalLayout = this.props.docId ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc, this.props.fieldKey); + this._finalLayout = this.props.docId ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc); if (this._finalLayout) { if (!Doc.AreProtosEqual(this._finalLayout, dashDoc)) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 809315963..677c4662b 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -64,6 +64,7 @@ import { schema } from './schema_rts'; import { SummaryView } from './SummaryView'; import applyDevTools = require('prosemirror-dev-tools'); import React = require('react'); +import { IsFollowLinkScript } from '../../../util/LinkFollower'; const translateGoogleApi = require('translate-google-api'); export const GoogleRef = 'googleDocId'; @@ -1933,7 +1934,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 3a5ba4f75..662792ff0 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -906,57 +906,40 @@ export namespace Doc { saveAs(content, doc.title + '.zip'); // glr: Possibly change the name of the document to match the title? }); } - // - // Determines whether the layout needs to be expanded (as a template). - // template expansion is rquired when the layout is a template doc/field and there's a datadoc which isn't equal to the layout template - // - export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) { - return (layoutDoc.isTemplateForField || layoutDoc.isTemplateDoc) && dataDoc && layoutDoc !== dataDoc; - } const _pendingMap: Map = new Map(); // // Returns an expanded template layout for a target data document if there is a template relationship // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties // of the original layout while allowing for individual layout properties to be overridden in the expanded layout. - // templateArgs should be equivalent to the layout key that generates the template since that's where the template parameters are stored in ()'s at the end of the key. - // NOTE: the template will have references to "@params" -- the template arguments will be assigned to the '@params' field - // so that when the @params key is accessed, it will be rewritten as the key that is stored in the 'params' field and - // the derefence will then occur on the rootDocument (the original document). - // in the future, field references could be written as @ and then arguments would be passed in the layout key as: - // layout_mytemplate(somparam=somearg). - // then any references to @someparam would be rewritten as accesses to 'somearg' on the rootDocument - export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc, templateArgs?: string) { - const args = templateArgs?.match(/\(([a-zA-Z0-9._\-]*)\)/)?.[1].replace('()', '') || ''; - if ((!args && !WillExpandTemplateLayout(templateLayoutDoc, targetDoc)) || !targetDoc) return templateLayoutDoc; - - const templateField = StrCast(templateLayoutDoc.isTemplateForField); // the field that the template renders + export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc) { + // nothing to do if the layout isn't a template or we don't have a target that's different than the template + if (!targetDoc || templateLayoutDoc === targetDoc || (!templateLayoutDoc.isTemplateForField && !templateLayoutDoc.isTemplateDoc)) { + return templateLayoutDoc; + } + + const templateField = StrCast(templateLayoutDoc.isTemplateForField, Doc.LayoutFieldKey(templateLayoutDoc)); // the field that the template renders // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc // using the template layout doc's id as the field key. // If it doesn't find the expanded layout, then it makes a delegate of the template layout and // saves it on the data doc indexed by the template layout's id. // - const params = args.split('=').length > 1 ? args.split('=')[0] : ''; - const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc); - const expandedLayoutFieldKey = (templateField || layoutFielddKey) + '-layout[' + templateLayoutDoc[Id] + (args ? `(${args})` : '') + ']'; + const expandedLayoutFieldKey = templateField + '-layout[' + templateLayoutDoc[Id] + ']'; let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey]; if (templateLayoutDoc.resolvedDataDoc instanceof Promise) { expandedTemplateLayout = undefined; _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true); - } else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey + args)) { + } else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey)) { if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc))) { expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params } else { templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = Cast(templateLayoutDoc.proto, Doc, null) || templateLayoutDoc); // if the template has already been applied (ie, a nested template), then use the template's prototype if (!targetDoc[expandedLayoutFieldKey]) { - _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey + args, true); + _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true); setTimeout( action(() => { const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, '[' + templateLayoutDoc.title + ']'); - // the template's arguments are stored in params which is derefenced to find - // the actual field key where the parameterized template data is stored. - newLayoutDoc[params] = args !== '...' ? args : ''; // ... signifies the layout has sub template(s) -- so we have to expand the layout for them so that they can get the correct 'rootDocument' field, but we don't need to reassign their params. it would be better if the 'rootDocument' field could be passed dynamically to avoid have to create instances newLayoutDoc.rootDocument = targetDoc; const dataDoc = Doc.GetProto(targetDoc); newLayoutDoc.resolvedDataDoc = dataDoc; @@ -965,7 +948,7 @@ export namespace Doc { } targetDoc[expandedLayoutFieldKey] = newLayoutDoc; - _pendingMap.delete(targetDoc[Id] + expandedLayoutFieldKey + args); + _pendingMap.delete(targetDoc[Id] + expandedLayoutFieldKey); }) ); } @@ -982,7 +965,7 @@ export namespace Doc { return { layout: childDoc, data: childDoc }; } const resolvedDataDoc = Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc; - return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc, '()'), data: resolvedDataDoc }; + return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc }; } export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc { -- cgit v1.2.3-70-g09d2 From 5cd64622f14ede408d3baca4a10d155b60392e46 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 13 Apr 2023 22:22:07 -0400 Subject: lots of changes to get rid of ContainingCollectionDoc and ContainingCollectionView props. --- src/client/documents/Documents.ts | 8 +-- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/DocumentManager.ts | 83 ++++++++++------------ src/client/util/DragManager.ts | 4 +- .../util/Import & Export/DirectoryImportBox.tsx | 6 +- src/client/util/ReplayMovements.ts | 64 ++++++----------- src/client/util/SelectionManager.ts | 6 +- src/client/util/SharingManager.tsx | 5 +- src/client/util/TrackMovements.ts | 36 +++++----- src/client/views/DashboardView.tsx | 17 ++--- src/client/views/DocComponent.tsx | 1 - src/client/views/DocumentDecorations.tsx | 8 +-- src/client/views/GestureOverlay.tsx | 4 +- src/client/views/InkStrokeProperties.ts | 3 +- src/client/views/LightboxView.tsx | 4 +- src/client/views/MainView.tsx | 20 ++---- src/client/views/OverlayView.tsx | 10 +-- src/client/views/Palette.tsx | 31 ++++---- src/client/views/PropertiesDocContextSelector.tsx | 22 ++++-- src/client/views/PropertiesView.tsx | 2 - src/client/views/StyleProvider.tsx | 11 ++- src/client/views/TemplateMenu.tsx | 2 - .../views/collections/CollectionCarouselView.tsx | 1 - src/client/views/collections/CollectionMenu.tsx | 6 +- .../views/collections/CollectionNoteTakingView.tsx | 4 -- .../views/collections/CollectionPileView.tsx | 2 +- .../collections/CollectionStackedTimeline.tsx | 2 - .../views/collections/CollectionStackingView.tsx | 4 -- .../views/collections/CollectionTreeView.tsx | 10 +-- src/client/views/collections/CollectionView.tsx | 5 +- src/client/views/collections/TabDocView.tsx | 6 +- src/client/views/collections/TreeView.tsx | 54 ++++++-------- .../collectionFreeForm/CollectionFreeFormView.tsx | 31 ++++---- .../collectionLinear/CollectionLinearView.tsx | 5 +- .../CollectionMulticolumnView.tsx | 2 - .../CollectionMultirowView.tsx | 2 - .../collectionSchema/CollectionSchemaView.tsx | 6 +- .../collections/collectionSchema/SchemaRowBox.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 2 - src/client/views/linking/LinkMenuItem.tsx | 21 +----- src/client/views/linking/LinkPopup.tsx | 4 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 7 +- src/client/views/nodes/DocumentContentsView.tsx | 1 - src/client/views/nodes/DocumentLinksButton.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 12 ++-- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/KeyValuePair.tsx | 2 - src/client/views/nodes/LinkDocPreview.tsx | 4 +- src/client/views/nodes/ScreenshotBox.tsx | 5 +- src/client/views/nodes/button/FontIconBox.tsx | 4 +- .../views/nodes/formattedText/DashDocView.tsx | 7 +- .../views/nodes/formattedText/DashFieldView.tsx | 5 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 20 ++++-- src/client/views/nodes/trails/PresBox.tsx | 1 - src/client/views/nodes/trails/PresElementBox.tsx | 27 ++++--- src/client/views/topbar/TopBar.tsx | 51 ++----------- src/mobile/AudioUpload.tsx | 76 ++++++++++---------- src/mobile/MobileInterface.tsx | 4 +- 58 files changed, 291 insertions(+), 456 deletions(-) (limited to 'src/client/views/nodes/formattedText/DashDocView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8d97ce5af..09b45a481 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1285,10 +1285,6 @@ export namespace DocUtils { return rangeFilteredDocs; } - export function DefaultFocus(doc: Doc, options: DocFocusOptions) { - return undefined; - } - export let ActiveRecordings: { props: FieldViewProps; getAnchor: (addAsAnnotation: boolean) => Doc }[] = []; export function MakeLinkToActiveAudio(getSourceDoc: () => Doc | undefined, broadcastEvent = true) { @@ -1299,10 +1295,9 @@ export namespace DocUtils { }); } - export function MakeLink(source: Doc, target: Doc, linkSettings: { linkRelationship?: string; description?: string; linkDisplay?: boolean }, id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) { + export function MakeLink(source: Doc, target: Doc, linkSettings: { linkRelationship?: string; description?: string; linkDisplay?: boolean }, id?: string, showPopup?: number[]) { if (!linkSettings.linkRelationship) linkSettings.linkRelationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; const sv = DocumentManager.Instance.getDocumentView(source); - if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target) return; if (target.doc === Doc.UserDoc()) return undefined; const makeLink = action((linkDoc: Doc, showPopup?: number[]) => { @@ -1371,7 +1366,6 @@ export namespace DocUtils { value: 'any', _readOnly_: 'boolean', scriptContext: 'any', - thisContainer: Doc.name, documentView: Doc.name, heading: Doc.name, checked: 'boolean', diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 76ea3e3ea..abf7313a4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -110,7 +110,7 @@ export class CurrentUserUtils { const tempClicks = DocCast(doc[field]); const reqdClickOpts:DocumentOptions = {_width: 300, _height:200, system: true}; const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [ - { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self])))"}, + { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCast(documentView?.props.docViewPath().lastElement()?.rootDoc.target).then((target) => target && (target.proto.data = new List([self])))"}, { opts: { title: "Open Detail On Right", targetScriptKey: "onChildDoubleClick"}, script: `openDoc(self.doubleClickView.${OpenWhere.addRight})`}]; const reqdClickList = reqdTempOpts.map(opts => { const allOpts = {...reqdClickOpts, ...opts.opts}; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index ccf370662..ad89e8653 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,15 +1,11 @@ -import { loadAsync } from 'jszip'; -import { action, observable, ObservableSet, runInAction } from 'mobx'; +import { action, observable, ObservableSet } from 'mobx'; import { AnimationSym, Doc, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { listSpec } from '../../fields/Schema'; import { Cast, DocCast, StrCast } from '../../fields/Types'; import { AudioField } from '../../fields/URLField'; -import { emptyFunction } from '../../Utils'; import { CollectionViewType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; -import { CollectionFreeFormView } from '../views/collections/collectionFreeForm'; -import { CollectionView } from '../views/collections/CollectionView'; import { TabDocView } from '../views/collections/TabDocView'; import { LightboxView } from '../views/LightboxView'; import { MainView } from '../views/MainView'; @@ -39,7 +35,7 @@ export class DocumentManager { private _viewRenderedCbs: { doc: Doc; func: (dv: DocumentView) => any }[] = []; public AddViewRenderedCb = (doc: Opt, func: (dv: DocumentView) => any) => { if (doc) { - const dv = this.getDocumentViewById(doc[Id]); + const dv = this.getDocumentView(doc); this._viewRenderedCbs.push({ doc, func }); if (dv) { this.callAddViewFuncs(dv); @@ -129,42 +125,24 @@ export class DocumentManager { return this.getDocumentViewsById(doc[Id]); } - public getDocumentViewById(id: string, preferredCollection?: CollectionView): DocumentView | undefined { - if (!id) return undefined; - let toReturn: DocumentView | undefined; - const passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; - - for (const pass of passes) { - Array.from(DocumentManager.Instance.DocumentViews).map(view => { - if (view.rootDoc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { - toReturn = view; - return; - } - }); - if (!toReturn) { - Array.from(DocumentManager.Instance.DocumentViews).map(view => { - const doc = view.rootDoc.proto; - if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { - toReturn = view; - } - }); - } else { - break; - } - } - - return toReturn; - } - - public getDocumentView(toFind: Doc, preferredCollection?: CollectionView): DocumentView | undefined { - const found = + public getDocumentView(toFind: Doc | undefined, preferredCollection?: DocumentView): DocumentView | undefined { + const doc = + // bcz: this was temporary code used to match documents by data url instead of by id. intended only for repairing the DB // Array.from(DocumentManager.Instance.DocumentViews).find( // dv => // ((dv.rootDoc.data as any)?.url?.href && (dv.rootDoc.data as any)?.url?.href === (toFind.data as any)?.url?.href) || // ((DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href && (DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href === (DocCast(toFind.annotationOn)?.data as any)?.url?.href) // )?.rootDoc ?? toFind; - return this.getDocumentViewById(found[Id], preferredCollection); + const docViewArray = Array.from(DocumentManager.Instance.DocumentViews); + const passes = !doc ? [] : preferredCollection ? [preferredCollection, undefined] : [undefined]; + return passes.reduce( + (pass, toReturn) => + toReturn ?? + docViewArray.filter(view => view.rootDoc === doc).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection) ?? + docViewArray.filter(view => Doc.GetProto(view.rootDoc) === doc).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection), + undefined as Opt + ); } public getLightboxDocumentView = (toFind: Doc, originatingDoc: Opt = undefined): DocumentView | undefined => { @@ -247,7 +225,8 @@ export class DocumentManager { public showDocumentView = async (targetDocView: DocumentView, options: DocFocusOptions) => { const docViewPath = targetDocView.docViewPath.slice(); let rootContextView = docViewPath.shift(); - return rootContextView && this.focusViewsInPath(rootContextView, options, async () => ({ childDocView: docViewPath.shift(), viewSpec: undefined })); + await (rootContextView && this.focusViewsInPath(rootContextView, options, async () => ({ childDocView: docViewPath.shift(), viewSpec: undefined }))); + if (options.toggleTarget && (!options.didMove || targetDocView.rootDoc.hidden)) targetDocView.rootDoc.hidden = !targetDocView.rootDoc.hidden; }; // shows a document by first: @@ -318,15 +297,25 @@ export class DocumentManager { } } } -export function DocFocusOrOpen(doc: Doc, collectionDoc?: Doc) { - const cv = collectionDoc && DocumentManager.Instance.getDocumentView(collectionDoc); - const dv = DocumentManager.Instance.getDocumentView(doc, (cv?.ComponentView as CollectionFreeFormView)?.props.CollectionView); - if (dv) { - DocumentManager.Instance.showDocumentView(dv, { willZoomCentered: true }); - } else { - const context = doc.context !== Doc.MyFilesystem && Cast(doc.context, Doc, null); - const showDoc = context || doc; - DocumentManager.Instance.showDocument(Doc.BestAlias(showDoc), { openLocation: OpenWhere.addRight }, () => DocumentManager.Instance.showDocument(doc, { willZoomCentered: true })); - } +export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCentered: true, openLocation: OpenWhere.addRight }, containingDoc?: Doc) { + const func = () => { + const cv = DocumentManager.Instance.getDocumentView(containingDoc); + const dv = DocumentManager.Instance.getDocumentView(doc, cv); + if (dv && (!containingDoc || dv.props.docViewPath().lastElement()?.Document === containingDoc)) { + DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.rootDoc)); + } else { + const showDoc = Doc.BestAlias(DocCast((containingDoc ?? doc.context) !== Doc.MyFilesystem ? containingDoc ?? doc.context : undefined, doc)); + DocumentManager.Instance.showDocument(showDoc, { ...options, toggleTarget: undefined }, () => DocumentManager.Instance.showDocument(doc, options)).then(() => { + const cv = DocumentManager.Instance.getDocumentView(containingDoc); + const dv = DocumentManager.Instance.getDocumentView(doc, cv); + dv && Doc.linkFollowHighlight(dv.rootDoc); + }); + } + }; + if (doc.hidden) { + doc.hidden = false; + options.toggleTarget = false; + setTimeout(func); + } else func(); } ScriptingGlobals.add(DocFocusOrOpen); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 7d2aa813f..7e6de5e67 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -3,10 +3,8 @@ import { DateField } from '../../fields/DateField'; import { Doc, Field, Opt, StrListCast } from '../../fields/Doc'; import { List } from '../../fields/List'; import { PrefetchProxy } from '../../fields/Proxy'; -import { listSpec } from '../../fields/Schema'; -import { SchemaHeaderField } from '../../fields/SchemaHeaderField'; import { ScriptField } from '../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; +import { BoolCast, ScriptCast, StrCast } from '../../fields/Types'; import { emptyFunction, Utils } from '../../Utils'; import { Docs, DocUtils } from '../documents/Documents'; import * as globalCssVariables from '../views/global/globalCssVariables.scss'; diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 559958c2b..76b1323c4 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -14,12 +14,14 @@ import { AcceptableMedia, Upload } from '../../../server/SharedMediaTypes'; import { Utils } from '../../../Utils'; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents'; +import { DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; import { FieldView, FieldViewProps } from '../../views/nodes/FieldView'; import { DocumentManager } from '../DocumentManager'; import './DirectoryImportBox.scss'; import ImportMetadataEntry, { keyPlaceholder, valuePlaceholder } from './ImportMetadataEntry'; import React = require('react'); +import _ = require('lodash'); const unsupported = ['text/html', 'text/plain']; @@ -155,8 +157,8 @@ export class DirectoryImportBox extends React.Component { x: NumCast(doc.x), y: NumCast(doc.y) + offset, }; - const parent = this.props.ContainingCollectionView; - if (parent) { + const parent = _.nth(this.props.docViewPath(), -2); // last element of path is this box's document view, 2nd to last is any collection or other document that may contain it. + if (parent?.rootDoc.type === DocumentType.COL) { let importContainer: Doc; if (docs.length < 50) { importContainer = Docs.Create.MasonryDocument(docs, options); diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts index d5bffc5e2..40261985a 100644 --- a/src/client/util/ReplayMovements.ts +++ b/src/client/util/ReplayMovements.ts @@ -7,6 +7,7 @@ import { CollectionDockingView } from '../views/collections/CollectionDockingVie import { DocServer } from '../DocServer'; import { Movement, Presentation } from './TrackMovements'; import { OpenWhereMod } from '../views/nodes/DocumentView'; +import { returnTransparent } from '../../Utils'; export class ReplayMovements { private timers: NodeJS.Timeout[] | null; @@ -60,17 +61,11 @@ export class ReplayMovements { return; } - let docIdtoDoc: Map = new Map(); - try { - docIdtoDoc = await this.loadPresentation(presentation); - } catch { - console.error('[recordingApi.ts] setVideoBox(): error loading presentation - no replay movements'); - throw 'error loading docs from server'; - } + const docIdtoDoc = this.loadPresentation(presentation); this.videoBoxDisposeFunc = reaction( () => ({ playing: videoBox._playing, timeViewed: videoBox.player?.currentTime || 0 }), - ({ playing, timeViewed }) => (playing ? this.playMovements(presentation, docIdtoDoc, timeViewed) : this.pauseMovements()) + ({ playing, timeViewed }) => (playing ? this.playMovements(presentation, timeViewed) : this.pauseMovements()) ); this.videoBox = videoBox; }; @@ -93,45 +88,33 @@ export class ReplayMovements { this.pauseMovements(); }; - loadPresentation = async (presentation: Presentation) => { + loadPresentation = (presentation: Presentation) => { const { movements } = presentation; if (movements === null) { throw '[recordingApi.ts] followMovements() failed: no presentation data'; } // generate a set of all unique docIds - const docIds = new Set(); - for (const { docId } of movements) { - if (!docIds.has(docId)) docIds.add(docId); - } - - const docIdtoDoc = new Map(); - - let refFields = await DocServer.GetRefFields([...docIds.keys()]); - for (const docId in refFields) { - if (!refFields[docId]) { - throw `one field was undefined`; - } - docIdtoDoc.set(docId, refFields[docId] as Doc); + const docs = new Set(); + for (const { doc } of movements) { + if (!docs.has(doc)) docs.add(doc); } - // console.info('loadPresentation refFields', refFields, docIdtoDoc); - return docIdtoDoc; + return docs; }; // returns undefined if the docView isn't open on the screen - getCollectionFFView = (docId: string) => { - const isInView = DocumentManager.Instance.getDocumentViewById(docId); + getCollectionFFView = (doc: Doc) => { + const isInView = DocumentManager.Instance.getDocumentView(doc); if (isInView) { return isInView.ComponentView as CollectionFreeFormView; } }; // will open the doc in a tab then return the CollectionFFView that holds it - openTab = (docId: string, docIdtoDoc: Map) => { - const doc = docIdtoDoc.get(docId); - if (doc == undefined) { - console.error(`docIdtoDoc did not contain docId ${docId}`); + openTab = (doc: Doc) => { + if (doc === undefined) { + console.error(`doc undefined`); return undefined; } // console.log('openTab', docId, doc); @@ -149,13 +132,12 @@ export class ReplayMovements { document.Document._panY = panY; }; - getFirstMovements = (movements: Movement[]): Map => { + getFirstMovements = (movements: Movement[]): Map => { if (movements === null) return new Map(); // generate a set of all unique docIds - const docIdtoFirstMove = new Map(); + const docIdtoFirstMove = new Map(); for (const move of movements) { - const { docId } = move; - if (!docIdtoFirstMove.has(docId)) docIdtoFirstMove.set(docId, move); + if (!docIdtoFirstMove.has(move.doc)) docIdtoFirstMove.set(move.doc, move); } return docIdtoFirstMove; }; @@ -165,7 +147,7 @@ export class ReplayMovements { Doc.UserDoc().presentationMode = 'none'; }; - public playMovements = (presentation: Presentation, docIdtoDoc: Map, timeViewed: number = 0) => { + public playMovements = (presentation: Presentation, timeViewed: number = 0) => { // console.info('playMovements', presentation, timeViewed, docIdtoDoc); if (presentation.movements === null || presentation.movements.length === 0) { @@ -183,13 +165,13 @@ export class ReplayMovements { const handleFirstMovements = () => { // if the first movement is a closed tab, open it const firstMovement = filteredMovements[0]; - const isClosed = this.getCollectionFFView(firstMovement.docId) === undefined; - if (isClosed) this.openTab(firstMovement.docId, docIdtoDoc); + const isClosed = this.getCollectionFFView(firstMovement.doc) === undefined; + if (isClosed) this.openTab(firstMovement.doc); // for the open tabs, set it to the first move const docIdtoFirstMove = this.getFirstMovements(filteredMovements); - for (const [docId, firstMove] of docIdtoFirstMove) { - const colFFView = this.getCollectionFFView(docId); + for (const [doc, firstMove] of docIdtoFirstMove) { + const colFFView = this.getCollectionFFView(doc); if (colFFView) this.zoomAndPan(firstMove, colFFView); } }; @@ -200,12 +182,12 @@ export class ReplayMovements { const timeDiff = movement.time - timeViewed * 1000; return setTimeout(() => { - const collectionFFView = this.getCollectionFFView(movement.docId); + const collectionFFView = this.getCollectionFFView(movement.doc); if (collectionFFView) { this.zoomAndPan(movement, collectionFFView); } else { // tab wasn't open - open it and play the movement - const openedColFFView = this.openTab(movement.docId, docIdtoDoc); + const openedColFFView = this.openTab(movement.doc); console.log('openedColFFView', openedColFFView); openedColFFView && this.zoomAndPan(movement, openedColFFView); } diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 313c255a0..bfad93334 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,4 +1,3 @@ -import { ModalManager } from '@material-ui/core'; import { action, observable, ObservableMap } from 'mobx'; import { computedFn } from 'mobx-utils'; import { Doc, Opt } from '../../fields/Doc'; @@ -64,8 +63,9 @@ export namespace SelectionManager { export function DeselectView(docView?: DocumentView): void { manager.DeselectView(docView); } - export function SelectView(docView: DocumentView, ctrlPressed: boolean): void { - manager.SelectView(docView, ctrlPressed); + export function SelectView(docView: DocumentView | undefined, ctrlPressed: boolean): void { + if (!docView) DeselectAll(); + else manager.SelectView(docView, ctrlPressed); } export function SelectSchemaViewDoc(document: Opt, deselectAllFirst?: boolean): void { if (deselectAllFirst) manager.DeselectAll(); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 3c05af4bb..a73eda04c 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -370,11 +370,10 @@ export class SharingManager extends React.Component<{}> { const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc]; return ( { - let context: Opt; - if (this.targetDoc && this.targetDocView && docs.length === 1 && (context = this.targetDocView.props.ContainingCollectionView)) { + if (this.targetDoc && this.targetDocView && docs.length === 1) { DocumentManager.Instance.showDocument(this.targetDoc, { willZoomCentered: true }); } }} diff --git a/src/client/util/TrackMovements.ts b/src/client/util/TrackMovements.ts index 4a2ccd706..2f16307b3 100644 --- a/src/client/util/TrackMovements.ts +++ b/src/client/util/TrackMovements.ts @@ -9,7 +9,7 @@ export type Movement = { panX: number; panY: number; scale: number; - docId: string; + doc: Doc; }; export type Presentation = { @@ -28,7 +28,7 @@ export class TrackMovements { private tracking: boolean; private absoluteStart: number; // instance variable for holding the FFViews and their disposers - private recordingFFViews: Map | null; + private recordingFFViews: Map | null; private tabChangeDisposeFunc: IReactionDisposer | null; // create static instance and getter for global use @@ -55,33 +55,33 @@ export class TrackMovements { return this.currentPresentation.movements === null; } - private addRecordingFFView(doc: Doc, key: string = doc[Id]): void { + private addRecordingFFView(doc: Doc): void { // console.info('adding dispose func : docId', key, 'doc', doc); if (this.recordingFFViews === null) { console.warn('addFFView on null RecordingApi'); return; } - if (this.recordingFFViews.has(key)) { - console.warn('addFFView : key already in map'); + if (this.recordingFFViews.has(doc)) { + console.warn('addFFView : doc already in map'); return; } const disposeFunc = reaction( () => ({ x: NumCast(doc.panX, -1), y: NumCast(doc.panY, -1), scale: NumCast(doc.viewScale, 0) }), - res => res.x !== -1 && res.y !== -1 && this.tracking && this.trackMovement(res.x, res.y, key, res.scale) + res => res.x !== -1 && res.y !== -1 && this.tracking && this.trackMovement(res.x, res.y, doc, res.scale) ); - this.recordingFFViews?.set(key, disposeFunc); + this.recordingFFViews?.set(doc, disposeFunc); } - private removeRecordingFFView = (key: string) => { + private removeRecordingFFView = (doc: Doc) => { // console.info('removing dispose func : docId', key); if (this.recordingFFViews === null) { console.warn('removeFFView on null RecordingApi'); return; } - this.recordingFFViews.get(key)?.(); - this.recordingFFViews.delete(key); + this.recordingFFViews.get(doc)?.(); + this.recordingFFViews.delete(doc); }; // in the case where only one tab was changed (updates not across dashboards), set only one to true @@ -90,15 +90,15 @@ export class TrackMovements { // so that the size comparisons are correct, we must filter to only the FFViews const isFFView = (doc: Doc) => doc && 'viewType' in doc && doc.viewType === 'freeform'; - const tabbedFFViews = new Set(); + const tabbedFFViews = new Set(); for (const DashDoc of tabbedDocs) { - if (isFFView(DashDoc)) tabbedFFViews.add(DashDoc[Id]); + if (isFFView(DashDoc)) tabbedFFViews.add(DashDoc); } // new tab was added - need to add it if (tabbedFFViews.size > this.recordingFFViews.size) { for (const DashDoc of tabbedDocs) { - if (!this.recordingFFViews.has(DashDoc[Id])) { + if (!this.recordingFFViews.has(DashDoc)) { if (isFFView(DashDoc)) { this.addRecordingFFView(DashDoc); @@ -110,9 +110,9 @@ export class TrackMovements { } // tab was removed - need to remove it from recordingFFViews else if (tabbedFFViews.size < this.recordingFFViews.size) { - for (const [key] of this.recordingFFViews) { - if (!tabbedFFViews.has(key)) { - this.removeRecordingFFView(key); + for (const [doc] of this.recordingFFViews) { + if (!tabbedFFViews.has(doc)) { + this.removeRecordingFFView(doc); if (onlyOne) return; } } @@ -214,7 +214,7 @@ export class TrackMovements { } }; - private trackMovement = (panX: number, panY: number, docId: string, scale: number = 0) => { + private trackMovement = (panX: number, panY: number, doc: Doc, scale: number = 0) => { // ensure we are recording to track if (!this.tracking) { console.error('[recordingApi.ts] trackMovements(): tracking is false'); @@ -231,7 +231,7 @@ export class TrackMovements { // get the time const time = new Date().getTime() - this.absoluteStart; // make new movement object - const movement: Movement = { time, panX, panY, scale, docId }; + const movement: Movement = { time, panX, panY, scale, doc }; // add that movement to the current presentation data's movement array this.currentPresentation.movements && this.currentPresentation.movements.push(movement); diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 2b586b0e2..dee161931 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -109,17 +109,8 @@ export class DashboardView extends React.Component { />
-
); @@ -163,7 +154,7 @@ export class DashboardView extends React.Component {
-
this.selectDashboardGroup(DashboardGroup.MyDashboards)}> My Dashboards @@ -196,7 +187,7 @@ export class DashboardView extends React.Component { e.stopPropagation(); this.onContextMenu(dashboard, e); }}> - } /> +
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 9fc1487a0..a59189fd2 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -52,7 +52,6 @@ export function DocComponent

() { interface ViewBoxBaseProps { Document: Doc; DataDoc?: Doc; - ContainingCollectionDoc: Opt; DocumentView?: () => DocumentView; fieldKey: string; isSelected: (outsideReaction?: boolean) => boolean; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 9ffbe083f..9a4aaf00e 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -33,6 +33,7 @@ import { ImageBox } from './nodes/ImageBox'; import React = require('react'); import { RichTextField } from '../../fields/RichTextField'; import { LinkFollower } from '../util/LinkFollower'; +import _ = require('lodash'); @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> { @@ -303,8 +304,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P SelectionManager.DeselectAll(); }; - onSelectorClick = () => SelectionManager.Views()?.[0]?.props.ContainingCollectionView?.props.select(false); - + onSelectorClick = () => SelectionManager.Views()?.[0]?.props.docViewPath?.().lastElement()?.select(false); /** * Handles setting up events when user clicks on the border radius editor * @param e PointerEvent @@ -744,7 +744,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P seldocview.props.hideDeleteButton || seldocview.rootDoc.hideDeleteButton || SelectionManager.Views().some(docView => { - const collectionAcl = docView.props.ContainingCollectionView ? GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]) : AclEdit; + const collectionAcl = docView.props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView.props.docViewPath().lastElement().rootDoc[DataSym]) : AclEdit; return docView.rootDoc.stayInCollection || (collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); }); @@ -865,7 +865,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P

e.preventDefault()} />
e.preventDefault()} /> - {seldocview.props.renderDepth <= 1 || !seldocview.props.ContainingCollectionView ? null : topBtn('selector', 'arrow-alt-circle-up', undefined, this.onSelectorClick, 'tap to select containing document')} + {seldocview.props.renderDepth <= 1 || !seldocview.props.docViewPath().lastElement() ? null : topBtn('selector', 'arrow-alt-circle-up', undefined, this.onSelectorClick, 'tap to select containing document')} )} {useRounding && ( diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 0feccb742..13faae783 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -1010,14 +1010,12 @@ export class GestureOverlay extends Touchable { renderDepth={0} styleProvider={returnEmptyString} docViewPath={returnEmptyDoclist} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docRangeFilters={returnEmptyFilter} docFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> ); }; diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index e6df0801c..156825f41 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -373,10 +373,11 @@ export class InkStrokeProperties { snapToAllCurves = (screenDragPt: { X: number; Y: number }, inkView: DocumentView, snapData: { nearestPt: { X: number; Y: number }; distance: number }, ink: InkData, controlIndex: number) => { const containingCollection = inkView.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView; + const containingDocView = inkView.props.CollectionFreeFormDocumentView?.().props.DocumentView?.(); containingCollection?.childDocs .filter(doc => doc.type === DocumentType.INK) .forEach(doc => { - const testInkView = DocumentManager.Instance.getDocumentView(doc, containingCollection?.props.CollectionView); + const testInkView = DocumentManager.Instance.getDocumentView(doc, containingDocView); const snapped = testInkView?.ComponentView?.snapPt?.(screenDragPt, doc === inkView.rootDoc ? this.excludeSelfSnapSegs(ink, controlIndex) : []); if (snapped && snapped.distance < snapData.distance) { const snappedInkPt = doc === inkView.rootDoc ? snapped.nearestPt : inkView.ComponentView?.ptFromScreen?.(testInkView?.ComponentView?.ptToScreen?.(snapped.nearestPt) ?? { X: 0, Y: 0 }); // convert from snapped ink coordinate system to dragged ink coordinate system by converting to/from screen space diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 976c8763e..69eec8456 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -266,8 +266,6 @@ export class LightboxView extends React.Component { docFilters={this.docFilters} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} addDocument={undefined} removeDocument={undefined} whenChildContentsActiveChanged={emptyFunction} @@ -275,7 +273,7 @@ export class LightboxView extends React.Component { pinToPres={TabDocView.PinDoc} bringToFront={emptyFunction} onBrowseClick={MainView.Instance.exploreMode} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 60459cf30..0384d925e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -595,14 +595,12 @@ export class MainView extends React.Component { PanelWidth={this.headerBarDocWidth} PanelHeight={this.headerBarDocHeight} renderDepth={0} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} />
); @@ -626,14 +624,12 @@ export class MainView extends React.Component { ScreenToLocalTransform={this._hideUI ? this.mainScreenToLocalXf : Transform.Identity} PanelWidth={this.mainDocViewWidth} PanelHeight={this.mainDocViewHeight} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} suppressSetHeight={true} renderDepth={this._hideUI ? 0 : -1} /> @@ -727,14 +723,12 @@ export class MainView extends React.Component { renderDepth={0} isContentActive={returnTrue} scriptContext={CollectionDockingView.Instance?.props.Document} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> {this.docButtons} @@ -758,7 +752,7 @@ export class MainView extends React.Component { PanelHeight={this.leftMenuHeight} renderDepth={0} docViewPath={returnEmptyDoclist} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} styleProvider={DefaultStyleProvider} isContentActive={returnTrue} whenChildContentsActiveChanged={emptyFunction} @@ -766,8 +760,6 @@ export class MainView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} scriptContext={this} /> @@ -900,13 +892,11 @@ export class MainView extends React.Component { PanelWidth={this.leftMenuFlyoutWidth} PanelHeight={this.leftMenuFlyoutHeight} renderDepth={0} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ?
{StrCast(this.userDoc?.presentationMode)}
: <>} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index ec22128d4..bdc48d03a 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -1,4 +1,4 @@ -import { action, computed, observable, trace } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; @@ -10,15 +10,13 @@ import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, retu import { DocUtils } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; -import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { Transform } from '../util/Transform'; import { CollectionFreeFormLinksView } from './collections/collectionFreeForm/CollectionFreeFormLinksView'; import { LightboxView } from './LightboxView'; import { MainView } from './MainView'; import { DocumentView } from './nodes/DocumentView'; import './OverlayView.scss'; -import { ScriptingRepl } from './ScriptingRepl'; -import { DefaultStyleProvider, testDocProps } from './StyleProvider'; +import { DefaultStyleProvider } from './StyleProvider'; export type OverlayDisposer = () => void; @@ -223,7 +221,7 @@ export class OverlayView extends React.Component { isDocumentActive={returnTrue} isContentActive={returnTrue} whenChildContentsActiveChanged={emptyFunction} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} styleProvider={DefaultStyleProvider} docViewPath={returnEmptyDoclist} addDocTab={d.type === DocumentType.PRES ? MainView.addDocTabFunc : returnFalse} @@ -231,8 +229,6 @@ export class OverlayView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> ); diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx index 954529bc9..3ad28c418 100644 --- a/src/client/views/Palette.tsx +++ b/src/client/views/Palette.tsx @@ -1,12 +1,12 @@ -import { IReactionDisposer, observable, reaction } from "mobx"; -import { observer } from "mobx-react"; -import * as React from "react"; -import { Doc } from "../../fields/Doc"; -import { NumCast } from "../../fields/Types"; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, emptyPath } from "../../Utils"; -import { Transform } from "../util/Transform"; -import { DocumentView } from "./nodes/DocumentView"; -import "./Palette.scss"; +import { IReactionDisposer, observable, reaction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Doc } from '../../fields/Doc'; +import { NumCast } from '../../fields/Types'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, emptyPath } from '../../Utils'; +import { Transform } from '../util/Transform'; +import { DocumentView } from './nodes/DocumentView'; +import './Palette.scss'; export interface PaletteProps { x: number; @@ -23,20 +23,20 @@ export default class Palette extends React.Component { componentDidMount = () => { this._selectedDisposer = reaction( () => NumCast(this.props.thumbDoc.selectedIndex), - (i) => this._selectedIndex = i, + i => (this._selectedIndex = i), { fireImmediately: true } ); - } + }; componentWillUnmount = () => { this._selectedDisposer?.(); - } + }; render() { return (
-
+
{ docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> + />
); } -} \ No newline at end of file +} diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index 2c7da5931..93eec61f3 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -22,9 +22,9 @@ export class PropertiesDocContextSelector extends React.Component alias.context && alias.context instanceof Doc && Cast(alias.context, Doc, null) !== targetContext).reduce((set, alias) => set.add(Cast(alias.context, Doc, null)), new Set()); + const containerProtos = aliases.filter(alias => alias.context && alias.context instanceof Doc).reduce((set, alias) => set.add(Cast(alias.context, Doc, null)), new Set()); const containerSets = Array.from(containerProtos.keys()).map(container => DocListCast(container.aliases)); const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); @@ -42,6 +42,7 @@ export class PropertiesDocContextSelector extends React.Component !Doc.AreProtosEqual(doc, CollectionDockingView.Instance?.props.Document)) .filter(doc => !Doc.IsSystem(doc)) + .filter(doc => doc !== targetContext) .map(doc => ({ col: doc, target })); } @@ -53,8 +54,21 @@ export class PropertiesDocContextSelector extends React.Component DocFocusOrOpen(Doc.GetProto(this.props.DocView!.props.Document), col), 100); + //this.props.addDocTab(col, (OpenWhere.toggle + ':' + OpenWhereMod.right) as OpenWhere); + setTimeout( + () => + this.props.DocView && + DocFocusOrOpen( + Doc.GetProto(this.props.DocView.props.Document), + { + // + willZoomCentered: true, + openLocation: (OpenWhere.toggle + ':' + OpenWhereMod.right) as OpenWhere, + }, + col + ), + 100 + ); }; render() { diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index fbc7d7696..6582c3f2a 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -341,8 +341,6 @@ export class PropertiesView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={undefined} - ContainingCollectionView={undefined} addDocument={returnFalse} moveDocument={undefined} removeDocument={returnFalse} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index b950b4860..739d6d819 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -18,7 +18,7 @@ import { TreeSort } from './collections/TreeView'; import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; import { MainView } from './MainView'; -import { DocumentViewProps } from './nodes/DocumentView'; +import { DocumentViewProps, OpenWhere } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; import { SliderBox } from './nodes/SliderBox'; @@ -295,7 +295,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt { - if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform) { + if (props?.docViewPath().lastElement()?.rootDoc?._viewType === CollectionViewType.Freeform) { return doc?.pointerEvents !== 'none' ? null : (
toggleLockedPosition(doc)}> @@ -383,10 +383,7 @@ export function DashboardStyleProvider(doc: Opt, props: Opt {DashboardToggleButton(doc, 'hidden', 'eye-slash', 'eye', () => { - doc.hidden = doc.hidden ? undefined : true; - if (!doc.hidden) { - DocFocusOrOpen(doc, props?.ContainingCollectionDoc); - } + DocFocusOrOpen(doc, { toggleTarget: true, willPan: true, openLocation: OpenWhere.addRight }, props?.docViewPath().lastElement()?.rootDoc); })} ); diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 45db240a9..c5a501aa6 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -114,8 +114,6 @@ export class TemplateMenu extends React.Component { { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} />
); @@ -642,8 +640,8 @@ export class CollectionViewBaseChrome extends React.Component this.props.docView.props.CollectionFreeFormDocumentView?.().float())}> diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index aec0734b4..80e81bc1c 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -255,8 +255,6 @@ export class CollectionNoteTakingView extends CollectionSubView() { hideTitle={this.props.childHideTitle?.()} docRangeFilters={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} addDocument={this.props.addDocument} moveDocument={this.props.moveDocument} removeDocument={this.props.removeDocument} @@ -632,8 +630,6 @@ export class CollectionNoteTakingView extends CollectionSubView() { docFilters={this.props.docFilters} docRangeFilters={this.props.docRangeFilters} searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} />
); diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index ba90ed8cd..fd9b0c0ce 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -30,7 +30,7 @@ export class CollectionPileView extends CollectionSubView() { // pileups are designed to go away when they are empty. this._disposers.selected = reaction( () => this.childDocs.length, - num => !num && this.props.ContainingCollectionView?.removeDocument(this.props.Document) + num => !num && this.props.CollectionFreeFormDocumentView?.().props.removeDocument?.(this.props.Document) ); } componentWillUnmount() { diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index bbd81d06d..22a575989 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -815,8 +815,6 @@ class StackedTimelineAnchor extends React.Component whenChildContentsActiveChanged={emptyFunction} focus={focusFunc} isContentActive={returnFalse} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} searchFilterDocs={returnEmptyDoclist} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index a85ee0e02..67f5dc9f4 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -346,8 +346,6 @@ export class CollectionStackingView extends CollectionSubView ); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 4a11e8f0b..92932fb61 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -164,7 +164,7 @@ export class CollectionTreeView extends CollectionSubView 0) { FormattedTextBox.SelectOnLoad = prev[Id]; - DocumentManager.Instance.getDocumentView(prev, this.props.CollectionView)?.select(false); + DocumentManager.Instance.getDocumentView(prev, this.props.DocumentView?.())?.select(false); } return true; } @@ -242,8 +242,6 @@ export class CollectionTreeView extends CollectionSubView ); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index bc25ad43a..53fbcc3cc 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -279,7 +279,10 @@ export class CollectionView extends ViewBoxAnnotatableComponent +
{this.showIsTagged()} {this.renderSubView(this.collectionViewType, props)}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 458712999..ef8f395c5 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -425,8 +425,6 @@ export class TabDocView extends React.Component { hideTitle={this.props.keyValue} Document={this._document} DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} onBrowseClick={MainView.Instance.exploreMode} waitForDoubleClickToClick={MainView.Instance.waitForDoubleClick} isContentActive={returnTrue} @@ -580,8 +578,6 @@ export class TabMinimapView extends React.Component { { ScreenToLocalTransform={Transform.Identity} renderDepth={0} whenChildContentsActiveChanged={emptyFunction} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} styleProvider={TabMinimapView.miniStyleProvider} addDocTab={this.props.addDocTab} pinToPres={TabDocView.PinDoc} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 75e76019e..8b1dfc767 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -42,7 +42,7 @@ export interface TreeViewProps { prevSibling?: Doc; document: Doc; dataDoc?: Doc; - containerCollection: Doc; + treeViewParent: Doc; renderDepth: number; dropAction: dropActionType; addDocTab: (doc: Doc, where: OpenWhere) => boolean; @@ -143,7 +143,7 @@ export class TreeView extends React.Component { return this.validExpandViewTypes.includes(StrCast(this.doc.treeViewExpandedView)) ? StrCast(this.doc.treeViewExpandedView) : this.defaultExpandedView; } @computed get MAX_EMBED_HEIGHT() { - return NumCast(this.props.containerCollection.maxEmbedHeight, 200); + return NumCast(this.props.treeViewParent.maxEmbedHeight, 200); } @computed get dataDoc() { return this.props.document.treeViewChildrenOnRoot ? this.doc : this.doc[DataSym]; @@ -194,7 +194,7 @@ export class TreeView extends React.Component { const ind = this.dataDoc[key].indexOf(doc); const res = (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true); - res && ind > 0 && DocumentManager.Instance.getDocumentView(this.dataDoc[key][ind - 1], this.props.treeView.props.CollectionView)?.select(false); + res && ind > 0 && DocumentManager.Instance.getDocumentView(this.dataDoc[key][ind - 1], this.props.treeView.props.DocumentView?.())?.select(false); return res; }; @@ -385,7 +385,7 @@ export class TreeView extends React.Component { }; const addDoc = inside ? localAdd : parentAddDoc; const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same') && moveDocument; - const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes('add')) || forceAdd; + const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.treeViewParent)?.freezeChildren).includes('add')) || forceAdd; if (canAdd) { this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = true); const res = UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false)); @@ -406,7 +406,7 @@ export class TreeView extends React.Component { getTransform = () => this.refTransform(this._tref.current); embeddedPanelWidth = () => this.props.panelWidth() / (this.props.treeView.props.NativeDimScaling?.() || 1); embeddedPanelHeight = () => { - const layoutDoc = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc; + const layoutDoc = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc; return Math.min( layoutDoc[HeightSym](), this.MAX_EMBED_HEIGHT, @@ -416,7 +416,7 @@ export class TreeView extends React.Component { return layoutDoc._fitWidth ? !Doc.NativeHeight(layoutDoc) ? NumCast(layoutDoc._height) - : Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containerCollection._height))) + : Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.treeViewParent._height))) : (this.embeddedPanelWidth() * layoutDoc[HeightSym]()) / layoutDoc[WidthSym](); })() ); @@ -452,7 +452,7 @@ export class TreeView extends React.Component { this, doc, undefined, - this.props.containerCollection, + this.props.treeViewParent, this.props.prevSibling, addDoc, remDoc, @@ -596,7 +596,7 @@ export class TreeView extends React.Component { this, this.layoutDoc, this.dataDoc, - this.props.containerCollection, + this.props.treeViewParent, this.props.prevSibling, addDoc, remDoc, @@ -656,7 +656,7 @@ export class TreeView extends React.Component { this.onCheckedClick?.script.run( { this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc, - heading: this.props.containerCollection.title, + heading: this.props.treeViewParent.title, checked: this.doc.treeViewChecked === 'check' ? 'x' : this.doc.treeViewChecked === 'x' ? 'remove' : 'check', containingTreeView: this.props.treeView.props.Document, }, @@ -724,9 +724,11 @@ export class TreeView extends React.Component { }; @observable headerEleWidth = 0; - @computed get headerElements() { + @computed get titleButtons() { + const customHeaderButtons = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations); return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? null : ( <> + {customHeaderButtons} {/* e.g.,. hide button is set by dashboardStyleProvider */} {this.doc.hideContextMenu ? null : ( { return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label })); }; - onChildClick = () => { - return this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!); - }; + onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!); onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeViewChildDoubleClick, !this.props.treeView.outlineMode ? this._openScript?.() : null); @@ -906,7 +906,7 @@ export class TreeView extends React.Component { styleProvider={this.titleStyleProvider} enableDragWhenActive={true} onClickScriptDisable="never" // tree docViews have a script to show fields, etc. - docViewPath={returnEmptyDoclist} + docViewPath={this.props.treeView.props.docViewPath} treeViewDoc={this.props.treeView.props.Document} addDocument={undefined} addDocTab={this.props.addDocTab} @@ -937,12 +937,8 @@ export class TreeView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={this.props.treeView.props.CollectionView} - ContainingCollectionDoc={this.props.treeView.props.Document} /> ); - - const buttons = this.props.styleProvider?.(this.doc, { ...this.props.treeView.props, ContainingCollectionDoc: this.props.parentTreeView?.doc }, StyleProp.Decorations + (Doc.IsSystem(this.props.containerCollection) ? ':afterHeader' : '')); return ( <>
{ {view}
r && (this.headerEleWidth = r.getBoundingClientRect().width))}> - {buttons} {/* hide and lock buttons */} - {this.headerElements} + {this.titleButtons}
); @@ -1017,8 +1012,6 @@ export class TreeView extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={this.props.containerCollection} - ContainingCollectionView={undefined} addDocument={this.props.addDocument} moveDocument={this.move} removeDocument={this.props.removeDoc} @@ -1131,7 +1124,7 @@ export class TreeView extends React.Component { childDocs: Doc[], treeView: CollectionTreeView, parentTreeView: CollectionTreeView | TreeView | undefined, - containerCollection: Doc, + treeViewParent: Doc, dataDoc: Doc | undefined, parentCollectionDoc: Doc | undefined, containerPrevSibling: Doc | undefined, @@ -1162,19 +1155,19 @@ export class TreeView extends React.Component { hierarchyIndex?: number[], renderCount?: number ) { - const viewSpecScript = Cast(containerCollection.viewSpecScript, ScriptField); + const viewSpecScript = Cast(treeViewParent.viewSpecScript, ScriptField); if (viewSpecScript) { childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result); } - const docs = TreeView.sortDocs(childDocs, StrCast(containerCollection.treeViewSortCriterion, TreeSort.None)); + const docs = TreeView.sortDocs(childDocs, StrCast(treeViewParent.treeViewSortCriterion, TreeSort.None)); const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView.props.NativeDimScaling?.() || 1); const treeViewRefs = new Map(); return docs .filter(child => child instanceof Doc) .map((child, i) => { if (renderCount && i > renderCount) return null; - const pair = Doc.GetLayoutDataDocPair(containerCollection, dataDoc, child); + const pair = Doc.GetLayoutDataDocPair(treeViewParent, dataDoc, child); if (!pair.layout || pair.data instanceof Promise) { return null; } @@ -1192,10 +1185,7 @@ export class TreeView extends React.Component { } }; const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1])); - const outdent = - parentCollectionDoc?._viewType !== CollectionViewType.Tree - ? undefined - : (editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined); + const outdent = !parentCollectionDoc ? undefined : (editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined); const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false); const childLayout = Doc.Layout(pair.layout); const rowHeight = () => { @@ -1208,7 +1198,7 @@ export class TreeView extends React.Component { ref={r => treeViewRefs.set(child, r ? r : undefined)} document={pair.layout} dataDoc={pair.data} - containerCollection={containerCollection} + treeViewParent={treeViewParent} prevSibling={docs[i]} // TODO: [AL] add these hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined} @@ -1220,7 +1210,7 @@ export class TreeView extends React.Component { onCheckedClick={onCheckedClick} onChildClick={onChildClick} renderDepth={renderDepth} - removeDoc={StrCast(containerCollection.freezeChildren).includes('remove') ? undefined : remove} + removeDoc={StrCast(treeViewParent.freezeChildren).includes('remove') ? undefined : remove} addDocument={addDocument} styleProvider={styleProvider} panelWidth={rowWidth} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7ae7be3c8..a3f5e73fb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -262,7 +262,7 @@ export class CollectionFreeFormView extends CollectionSubView { SelectionManager.DeselectAll(); - docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)).map(dv => dv && SelectionManager.SelectView(dv, true)); + docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.DocumentView?.())).map(dv => dv && SelectionManager.SelectView(dv, true)); }; addDocument = (newBox: Doc | Doc[]) => { let retVal = false; @@ -319,7 +319,7 @@ export class CollectionFreeFormView extends CollectionSubView 1 ? NumCast(refDoc.y) - (NumCast(sorted[0].layout.y) + (topIndexed ? 0 : NumCast(sorted[0].layout._height))) : 0; const deltax = sorted.length > 1 ? NumCast(refDoc.x) - NumCast(sorted[0].layout.x) : 0; let lastx = NumCast(refDoc.x); let lasty = NumCast(refDoc.y) + (topIndexed ? 0 : NumCast(refDoc._height)); - setTimeout( - action(() => - sorted.slice(1).forEach((pair, i) => { - lastx = pair.layout.x = lastx + deltax; - lasty = (pair.layout.y = lasty + deltay) + (topIndexed ? 0 : NumCast(pair.layout._height)); - }) - ) + runInAction(() => + sorted.slice(1).forEach((pair, i) => { + lastx = pair.layout.x = lastx + deltax; + lasty = (pair.layout.y = lasty + deltay) + (topIndexed ? 0 : NumCast(pair.layout._height)); + }) ); } } @@ -464,7 +462,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).filter(cd => (this.props.Document._useClusters ? NumCast(cd.cluster) : NumCast(cd.group, -1)) === cluster); - const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.CollectionView)!); + const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.DocumentView?.())!); const { left, top } = clusterDocs[0].getBounds() || { left: 0, top: 0 }; const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'alias' : undefined); de.moveDocument = this.props.moveDocument; @@ -872,7 +870,7 @@ export class CollectionFreeFormView extends CollectionSubView DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)) + .map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.DocumentView?.())) .filter(inkView => inkView?.ComponentView instanceof InkingStroke) .map(inkView => ({ inkViewBounds: inkView!.getBounds(), inkStroke: inkView!.ComponentView as InkingStroke, inkView: inkView! })) .filter( @@ -966,7 +964,7 @@ export class CollectionFreeFormView extends CollectionSubView doc.type === DocumentType.INK && !doc.dontIntersect) .forEach(doc => { - const otherInk = DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)?.ComponentView as InkingStroke; + const otherInk = DocumentManager.Instance.getDocumentView(doc, this.props.DocumentView?.())?.ComponentView as InkingStroke; const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] }; const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point)); const otherCtrlPts = otherScreenPts.map(spt => (ink.ComponentView as InkingStroke).ptFromScreen(spt)); @@ -1121,7 +1119,8 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform || this.props.ContainingCollectionDoc._panX !== undefined) { + const collectionDoc = this.props.docViewPath().lastElement().rootDoc; + if (collectionDoc?._viewType !== CollectionViewType.Freeform || collectionDoc._panX !== undefined) { this.setPan( NumCast(this.layoutDoc[this.panXFieldKey]) + ((this.props.PanelWidth() / 2) * x) / this.zoomScaling(), // nudge x,y as a function of panel dimension and scale NumCast(this.layoutDoc[this.panYFieldKey]) + ((this.props.PanelHeight() / 2) * -y) / this.zoomScaling(), @@ -1256,8 +1255,6 @@ export class CollectionFreeFormView extends CollectionSubView @@ -251,8 +249,7 @@ export class CollectionLinearView extends CollectionSubView() { self: this.rootDoc, _readOnly_: false, scriptContext: this.props.scriptContext, - thisContainer: this.props.ContainingCollectionDoc, - documentView: this.props.docViewPath().lastElement(), + documentView: this.props.DocumentView?.(), }); this.layoutDoc.linearViewIsExpanded = this.addMenuToggle.current!.checked; })} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index b73b1d779..78d3d1b6e 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -262,8 +262,6 @@ export class CollectionMulticolumnView extends CollectionSubView() { docFilters={this.childDocFilters} docRangeFilters={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} dontRegisterView={this.props.dontRegisterView} addDocument={this.props.addDocument} moveDocument={this.props.moveDocument} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 0cca83803..4d61dc272 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -261,8 +261,6 @@ export class CollectionMultirowView extends CollectionSubView() { docFilters={this.childDocFilters} docRangeFilters={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} dontRegisterView={this.props.dontRegisterView} addDocument={this.props.addDocument} moveDocument={this.props.moveDocument} diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index fd9bcf681..6d5a73e55 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -793,7 +793,7 @@ export class CollectionSchemaView extends CollectionSubView() { fitContentsToBox={returnTrue} dontCenter={'y'} onClickScriptDisable="always" - focus={DocUtils.DefaultFocus} + focus={emptyFunction} renderDepth={this.props.renderDepth + 1} rootSelected={this.rootSelected} PanelWidth={this.previewWidthFunc} @@ -806,8 +806,6 @@ export class CollectionSchemaView extends CollectionSubView() { searchFilterDocs={this.searchFilterDocs} styleProvider={DefaultStyleProvider} docViewPath={returnEmptyDoclist} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} moveDocument={this.props.moveDocument} addDocument={this.addRow} removeDocument={this.props.removeDocument} @@ -849,8 +847,6 @@ class CollectionSchemaViewDocs extends React.Component() { } @computed get schemaDoc() { - return this.props.ContainingCollectionDoc!; + return this.props.DocumentView?.().props.docViewPath().lastElement()?.rootDoc; } @computed get rowIndex() { diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 13e45963e..5f8ffe8b0 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -28,8 +28,6 @@ export class SchemaTableCell extends React.Component { searchFilterDocs: returnEmptyDoclist, styleProvider: DefaultStyleProvider, docViewPath: returnEmptyDoclist, - ContainingCollectionView: undefined, - ContainingCollectionDoc: undefined, fieldKey: this.props.fieldKey, rootSelected: returnFalse, isSelected: returnFalse, diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 29e7cd3ad..d703c9595 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -44,25 +44,10 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume } const dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); - dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { - docView.props.removeDocument?.(doc); - addDocument(doc); - return true; - }; - const containingView = docView.props.ContainingCollectionView; - const finishDrag = (e: DragManager.DragCompleteEvent) => - e.docDragData && - (e.docDragData.droppedDocuments = dragData.draggedDocuments.reduce((droppedDocs, d) => { - const dvs = DocumentManager.Instance.getDocumentViews(d).filter(dv => dv.props.ContainingCollectionView === containingView); - if (dvs.length) { - dvs.forEach(dv => droppedDocs.push(dv.props.Document)); - } else { - droppedDocs.push(Doc.MakeAlias(d)); - } - return droppedDocs; - }, [] as Doc[])); + dragData.canEmbed = true; + dragData.moveDocument = (docView.props.docViewPath().lastElement()?.ComponentView as any)?.props.CollectionView?.moveDocument; // this is equal to docView.props.moveDocument, but moveDocument is not a defined prop of a DocumentView .. but maybe it should be? - DragManager.StartDrag([dragEle], dragData, downX, downY, undefined, finishDrag); + DragManager.StartDocumentDrag([dragEle], dragData, downX, downY, undefined); } } diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx index 7bdace2b6..5f2d4a7b6 100644 --- a/src/client/views/linking/LinkPopup.tsx +++ b/src/client/views/linking/LinkPopup.tsx @@ -85,15 +85,13 @@ export class LinkPopup extends React.Component { PanelWidth={this.getPWidth} PanelHeight={this.getPHeight} renderDepth={0} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} docViewPath={returnEmptyDoclist} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 9bdb2cee7..24b9f3b25 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -160,8 +160,9 @@ export class CollectionFreeFormDocumentView extends DocComponent { - const { Document: topDoc, ContainingCollectionView: container } = this.props; - const screenXf = container?.screenToLocalTransform(); + const topDoc = this.rootDoc; + const containerDocView = this.props.docViewPath().lastElement(); + const screenXf = containerDocView?.screenToLocalTransform(); if (screenXf) { SelectionManager.DeselectAll(); if (topDoc.z) { @@ -178,7 +179,7 @@ export class CollectionFreeFormDocumentView extends DocComponent SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0); + setTimeout(() => SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, containerDocView), false), 0); } }; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index dbcfe43cf..76a5ce7b3 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -154,7 +154,6 @@ export class DocumentContentsView extends React.Component< // these are the properties in DocumentViewProps that need to be removed to pass on only DocumentSharedViewProps to the FieldViews 'hideResizeHandles', 'hideTitle', - 'treeViewDoc', 'contentPointerEvents', 'radialMenu', 'LayoutTemplateString', diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index df3299eef..47705d53d 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -142,7 +142,7 @@ export class DocumentLinksButton extends React.Component undefined | { x: number; y: number; r: number; b: number }; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _fitContentsToBox property on a Document - ContainingCollectionView: Opt; - ContainingCollectionDoc: Opt; suppressSetHeight?: boolean; thumbShown?: () => boolean; setContentView?: (view: DocComponentView) => any; @@ -179,6 +177,7 @@ export interface DocumentViewSharedProps { ScreenToLocalTransform: () => Transform; bringToFront: (doc: Doc, sendToBack?: boolean) => void; canEmbedOnDrag?: boolean; + treeViewDoc?: Doc; xPadding?: number; yPadding?: number; dropAction?: dropActionType; @@ -210,7 +209,6 @@ export interface DocumentViewProps extends DocumentViewSharedProps { hideOpenButton?: boolean; hideDeleteButton?: boolean; hideLinkAnchors?: boolean; - treeViewDoc?: Doc; isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events isContentActive: () => boolean | undefined; // whether document contents should handle pointer events contentPointerEvents?: string; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents @@ -429,7 +427,6 @@ export class DocumentViewInternal extends DocComponent this.props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); !appearance && appearanceItems.length && cm.addItem({ description: 'UI Controls...', subitems: appearanceItems, icon: 'compass' }); - if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) { + if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && this.props.docViewPath().lastElement()?.rootDoc?._viewType !== CollectionViewType.Tree) { const existingOnClick = cm.findByDescription('OnClick...'); const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : []; @@ -1446,7 +1442,7 @@ export class DocumentView extends React.Component { scaleToScreenSpace = () => (1 / (this.props.NativeDimScaling?.() || 1)) * this.screenToLocalTransform().Scale; docViewPathFunc = () => this.docViewPath; isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction); - select = (extendSelection: boolean) => SelectionManager.SelectView(this, !SelectionManager.Views().some(v => v.props.Document === this.props.ContainingCollectionDoc) && extendSelection); + select = (extendSelection: boolean) => SelectionManager.SelectView(this, extendSelection); NativeWidth = () => this.effectiveNativeWidth; NativeHeight = () => this.effectiveNativeHeight; PanelWidth = () => this.panelWidth; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 8d3534a5c..86779e0dd 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -32,6 +32,7 @@ export interface FieldViewProps extends DocumentViewSharedProps { // See currentUserUtils headerTemplate for examples of creating text boxes from html which set some of these fields // Also, see InkingStroke for examples of creating text boxes from render() methods which set some of these fields backgroundColor?: string; + treeViewDoc?: Doc; color?: string; fontSize?: number; height?: number; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 94434dce7..7ea6d42ff 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -61,8 +61,6 @@ export class KeyValuePair extends React.Component { searchFilterDocs: returnEmptyDoclist, styleProvider: DefaultStyleProvider, docViewPath: returnEmptyDoclist, - ContainingCollectionView: undefined, - ContainingCollectionDoc: undefined, fieldKey: this.props.keyName, rootSelected: returnFalse, isSelected: returnFalse, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index fcc5b6975..c58b5dd8c 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -271,14 +271,12 @@ export class LinkDocPreview extends React.Component { docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={undefined} - ContainingCollectionView={undefined} renderDepth={0} suppressSetHeight={true} PanelWidth={this.width} PanelHeight={this.height} pointerEvents={returnNone} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={returnFalse} ignoreAutoHeight={true} // need to ignore autoHeight otherwise autoHeight text boxes will expand beyond the preview panel size. bringToFront={returnFalse} diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index db11a7776..e015024fd 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -305,8 +305,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent + renderDepth={this.props.renderDepth + 1}> <> {this.threed} {this.content} @@ -330,7 +329,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent + /> )} diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 8eacfbc51..1a75a7e76 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -568,12 +568,12 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b if (selectedViews.length) { if (checkResult) { const selView = selectedViews.lastElement(); - const layoutFrameNumber = Cast(selView.props.ContainingCollectionDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values + const layoutFrameNumber = Cast(selView.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values const contentFrameNumber = Cast(selView.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber).backgroundColor ?? 'transparent'; } selectedViews.forEach(dv => { - const layoutFrameNumber = Cast(dv.props.ContainingCollectionDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values + const layoutFrameNumber = Cast(dv.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values const contentFrameNumber = Cast(dv.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed if (contentFrameNumber !== undefined) { CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { backgroundColor: color }); diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index c00ab6a7e..b31fc01ff 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -9,10 +9,9 @@ import { DocServer } from '../../../DocServer'; import { Docs, DocUtils } from '../../../documents/Documents'; import { ColorScheme } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; -import { DocumentView } from '../DocumentView'; +import { DocFocusOptions, DocumentView } from '../DocumentView'; import { FormattedTextBox } from './FormattedTextBox'; import React = require('react'); -import { SelectionManager } from '../../../util/SelectionManager'; export class DashDocView { dom: HTMLSpanElement; // container for label and value @@ -151,7 +150,7 @@ export class DashDocViewInternal extends React.Component { const { scale, translateX, translateY } = Utils.GetScreenTransform(this._spanRef.current); return new Transform(-translateX, -translateY, 1).scale(1 / scale); }; - outerFocus = (target: Doc) => this._textBox.props.focus(this._textBox.props.Document, {}); // ideally, this would scroll to show the focus target + outerFocus = (target: Doc, options: DocFocusOptions) => this._textBox.focus(target, options); // ideally, this would scroll to show the focus target onKeyDown = (e: any) => { e.stopPropagation(); @@ -212,8 +211,6 @@ export class DashDocViewInternal extends React.Component { docFilters={this.props.tbox?.props.docFilters} docRangeFilters={this.props.tbox?.props.docRangeFilters} searchFilterDocs={this.props.tbox?.props.searchFilterDocs} - ContainingCollectionView={this._textBox.props.ContainingCollectionView} - ContainingCollectionDoc={this._textBox.props.ContainingCollectionDoc} /> ); diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index f23426bb3..c43206629 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -235,10 +235,7 @@ export class DashFieldViewInternal extends React.Component { - let container = this.props.tbox.props.ContainingCollectionView; - while (container?.props.Document.isTemplateForField || container?.props.Document.isTemplateDoc) { - container = container.props.ContainingCollectionView; - } + let container = this.props.tbox.props.DocumentView?.().props.docViewPath().lastElement(); if (container) { const alias = Doc.MakeAlias(container.props.Document); alias._viewType = CollectionViewType.Time; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 677c4662b..bc2a5d797 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -541,7 +541,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - const tanch = Docs.Create.TextanchorDocument({ title: 'dictation anchor' }); + const tanch = Docs.Create.TextanchorDocument({ title: 'dictation anchor', unrendered: true }); return this.addDocument(tanch) ? tanch : undefined; }; const link = DocUtils.MakeLinkToActiveAudio(textanchorFunc, false).lastElement(); @@ -956,7 +957,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { const examinedNode = findAnchorNode(node, editor); - if (examinedNode?.node && (examinedNode.node.textContent || examinedNode.node.type === this._editorView?.state.schema.nodes.audiotag)) { + if (examinedNode?.node && (examinedNode.node.textContent || examinedNode.node.type === this._editorView?.state.schema.nodes.dashDoc || examinedNode.node.type === this._editorView?.state.schema.nodes.audiotag)) { nodes.push(examinedNode.node); !hadStart && (start = index + examinedNode.start); hadStart = true; @@ -971,9 +972,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent mark.type === editor.state.schema.marks.linkAnchor); @@ -987,7 +994,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent 2 || (content?.length && content[0].type === this._editorView.state.schema.nodes.audiotag)) && ret.start >= 0) { + if ((ret.frag.size || (content?.length && content[0].type === this._editorView.state.schema.nodes.dashDoc) || (content?.length && content[0].type === this._editorView.state.schema.nodes.audiotag)) && ret.start >= 0) { !options.instant && (this._focusSpeed = focusSpeed); let selection = TextSelection.near(editor.state.doc.resolve(ret.start)); // default to near the start if (ret.frag.firstChild) { @@ -998,6 +1005,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (this._focusSpeed = undefined), this._focusSpeed); setTimeout(() => clearStyleSheetRules(FormattedTextBox._highlightStyleSheet), Math.max(this._focusSpeed || 0, 3000)); + return focusSpeed; + } else { + return this.props.focus(this.rootDoc, options); } } }; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 3589a9065..807a19771 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -2457,7 +2457,6 @@ export class PresBox extends ViewBoxBaseComponent() { {mode !== CollectionViewType.Invalid ? ( () { // Idea: this boolean will determine whether to automatically show the video when this preselement is selected. // @observable static showVideo: boolean = false; @computed get indexInPres() { - return DocListCast(this.presBox[StrCast(this.presBox.presFieldKey, 'data')]).indexOf(this.rootDoc); + return DocListCast(this.presBox?.[StrCast(this.presBox.presFieldKey, 'data')]).indexOf(this.rootDoc); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements) @computed get expandViewHeight() { return 100; @@ -51,11 +51,10 @@ export class PresElementBox extends ViewBoxBaseComponent() { return this.presBoxView?.selectedArray; } @computed get presBoxView() { - const vpath = this.props.docViewPath(); - return vpath.length > 1 ? (vpath[vpath.length - 2].ComponentView as PresBox) : undefined; + return this.props.DocumentView?.()?.props.docViewPath().lastElement()?.ComponentView as PresBox; } @computed get presBox() { - return this.props.ContainingCollectionDoc!; + return this.props.DocumentView?.().props.docViewPath().lastElement()?.rootDoc; } @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; @@ -110,14 +109,12 @@ export class PresElementBox extends ViewBoxBaseComponent() { docFilters={this.props.docFilters} docRangeFilters={this.props.docRangeFilters} searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} rootSelected={returnTrue} addDocument={returnFalse} removeDocument={returnFalse} fitContentsToBox={returnTrue} moveDocument={this.props.moveDocument!} - focus={DocUtils.DefaultFocus} + focus={emptyFunction} whenChildContentsActiveChanged={returnFalse} addDocTab={returnFalse} pinToPres={returnFalse} @@ -195,7 +192,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { const dragData = new DragManager.DocumentDragData(this.presBoxView?.sortArray() ?? []); if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.rootDoc); dragData.dropAction = 'move'; - dragData.treeViewDoc = this.presBox._viewType === CollectionViewType.Tree ? this.props.ContainingCollectionDoc : undefined; // this.props.DocumentView?.()?.props.treeViewDoc; + dragData.treeViewDoc = this.presBox?._viewType === CollectionViewType.Tree ? this.presBox : undefined; // this.props.DocumentView?.()?.props.treeViewDoc; dragData.moveDocument = this.props.moveDocument; const dragItem: HTMLElement[] = []; if (dragArray.length === 1) { @@ -269,7 +266,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { @undoBatch removeItem = action((e: React.MouseEvent) => { e.stopPropagation(); - if (this.indexInPres < (this.presBoxView?.itemIndex || 0)) { + if (this.presBox && this.indexInPres < (this.presBoxView?.itemIndex || 0)) { this.presBox.itemIndex = (this.presBoxView?.itemIndex || 0) - 1; } this.props.removeDocument?.(this.rootDoc); @@ -406,15 +403,15 @@ export class PresElementBox extends ViewBoxBaseComponent() { @computed get toolbarWidth(): number { const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox); - let width: number = NumCast(this.presBox._width); + let width: number = NumCast(this.presBox?._width); if (presBoxDocView) width = presBoxDocView.props.PanelWidth(); if (width === 0) width = 300; return width; } @computed get presButtons() { - const presBox: Doc = this.presBox; //presBox - const presBoxColor: string = StrCast(presBox._backgroundColor); + const presBox = this.presBox; //presBox + const presBoxColor: string = StrCast(presBox?._backgroundColor); const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; const targetDoc: Doc = this.targetDoc; const activeItem: Doc = this.rootDoc; @@ -494,10 +491,10 @@ export class PresElementBox extends ViewBoxBaseComponent() { @computed get mainItem() { const isSelected: boolean = this.selectedArray?.has(this.rootDoc) ? true : false; - const isCurrent: boolean = this.presBox._itemIndex === this.indexInPres; + const isCurrent: boolean = this.presBox?._itemIndex === this.indexInPres; const miniView: boolean = this.toolbarWidth <= 110; - const presBox: Doc = this.presBox; //presBox - const presBoxColor: string = StrCast(presBox._backgroundColor); + const presBox = this.presBox; //presBox + const presBoxColor: string = StrCast(presBox?._backgroundColor); const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; const activeItem: Doc = this.rootDoc; diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index f2e9be61d..d63c25dbe 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -46,7 +46,7 @@ export class TopBar extends React.Component { return (
{Doc.ActiveDashboard ? ( - } isCircle={true} hoverStyle="gray" color={this.textColor} /> + } color={this.textColor} /> ) : (
dash logo @@ -55,18 +55,7 @@ export class TopBar extends React.Component {
)} {Doc.ActiveDashboard && ( -
); @@ -94,13 +83,8 @@ export class TopBar extends React.Component { @@ -657,7 +657,7 @@ export class CollectionViewBaseChrome extends React.Component {this.notACollection || this.props.type === CollectionViewType.Invalid ? null : this.viewModes}
- {this.aliasButton} + {this.embedButton} {/* {this.pinButton} */} {this.toggleOverlayButton}
@@ -691,7 +691,7 @@ export class CollectionFreeFormViewChrome extends React.Component key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); + const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); return keys.filter(key => key.toLowerCase().indexOf(val) > -1); - } else { - const keys = new Set(); - docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); - const noviceKeys = Array.from(keys).filter( - key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_') - ); - return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1); } + const keys = new Set(); + docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); + const noviceKeys = Array.from(keys).filter( + key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_') + ); + return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1); } if (docs instanceof Doc) { @@ -1125,13 +1124,13 @@ export class CollectionNoteTakingViewChrome extends React.Component key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); + const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); return keys.filter(key => key.toLowerCase().indexOf(val) > -1); } else { const keys = new Set(); docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); const noviceKeys = Array.from(keys).filter( - key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_') + key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_') ); return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1); } @@ -1235,9 +1234,9 @@ export class CollectionSchemaViewChrome extends React.Component 0; return ( diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 99d4d0bee..a65e23911 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -49,12 +49,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { return BoolCast(this.layoutDoc.chromeHidden); } // columnHeaders returns the list of SchemaHeaderFields currently being used by the layout doc to render the columns - @computed get columnHeaders() { - const columnHeaders = Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null); - const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset')); - if (needsUnsetCategory || columnHeaders === undefined || columnHeaders.length === 0) { + @computed get colHeaderData() { + const colHeaderData = Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null); + const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !colHeaderData?.find(sh => sh.heading === 'unset')); + if (needsUnsetCategory || colHeaderData === undefined || colHeaderData.length === 0) { setTimeout(() => { - const columnHeaders = Array.from(Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null) ?? []); + const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null) ?? []); const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset')); if (needsUnsetCategory || columnHeaders.length === 0) { columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1)); @@ -62,7 +62,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } }); } - return columnHeaders ?? ([] as SchemaHeaderField[]); + return colHeaderData ?? ([] as SchemaHeaderField[]); } @computed get headerMargin() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin); @@ -78,7 +78,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } // numGroupColumns returns the number of columns @computed get numGroupColumns() { - return this.columnHeaders.length; + return this.colHeaderData.length; } // PanelWidth returns the size of the total available space the view occupies @computed get PanelWidth() { @@ -117,7 +117,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { // (2) documentView gets unmounted as you remove it from the list @computed get Sections() { TraceMobx(); - const columnHeaders = this.columnHeaders; + const columnHeaders = this.colHeaderData; // filter out the currently dragged docs from the child docs, since we will insert them later const docs = this.childDocs.filter(d => !DragManager.docsBeingDragged.includes(d)); const sections = new Map(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); @@ -149,9 +149,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { componentDidMount() { super.componentDidMount?.(); document.addEventListener('pointerup', this.removeDocDragHighlight, true); - this._disposers.autoHeight = reaction( - () => this.layoutDoc._autoHeight, - autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))))) + this._disposers.layout_autoHeight = reaction( + () => this.layoutDoc._layout_autoHeight, + layout_autoHeight => + layout_autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))))) ); } @@ -230,7 +231,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { PanelHeight={height} styleProvider={this.styleProvider} docViewPath={this.props.docViewPath} - fitWidth={this.props.childFitWidth} + layout_fitWidth={this.props.childLayoutFitWidth} isContentActive={emptyFunction} onKey={this.onKeyDown} //TODO: change this from a prop to a parameter passed into a function @@ -238,12 +239,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { isDocumentActive={this.isContentActive} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} - NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox - NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeHeight(doc)) ? height : undefined} + NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childLayoutFitWidth?.(doc) || (doc._layout_fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox + NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childLayoutFitWidth?.(doc) || (doc._layout_fitWidth && !Doc.NativeHeight(doc)) ? height : undefined} dontCenter={this.props.childIgnoreNativeSize ? 'xy' : undefined} dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)} rootSelected={this.rootSelected} - showTitle={this.props.childShowTitle} + layout_showTitle={this.props.childlayout_showTitle} dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType} onClick={this.onChildClickHandler} onDoubleClick={this.onChildDoubleClickHandler} @@ -280,10 +281,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...) getDocWidth(d: Doc) { const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field); - const existingHeader = this.columnHeaders.find(sh => sh.heading === heading); + const existingHeader = this.colHeaderData.find(sh => sh.heading === heading); const existingWidth = existingHeader?.width ? existingHeader.width : 0; const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth; - const width = d.fitWidth ? maxWidth : d[WidthSym](); + const width = d.layout_fitWidth ? maxWidth : d[WidthSym](); return Math.min(maxWidth - CollectionNoteTakingViewColumn.ColumnMargin, width < maxWidth ? width : maxWidth); } @@ -293,14 +294,14 @@ export class CollectionNoteTakingView extends CollectionSubView() { const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField ? undefined : this.props.DataDoc; const maxHeight = (lim => (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); - const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); - const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); + const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[WidthSym]() : 0); + const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[HeightSym]() : 0); if (nw && nh) { const docWid = this.getDocWidth(d); return Math.min(maxHeight, (docWid * nh) / nw); } const childHeight = NumCast(childLayoutDoc._height); - const panelHeight = childLayoutDoc._fitWidth || this.props.childFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; + const panelHeight = childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; return Math.min(childHeight, maxHeight, panelHeight); } @@ -318,7 +319,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { const n = headers.length; const curWidths = headers.reduce((sum, hdr) => sum + Math.abs(hdr.width), 0); const scaleFactor = 1 / curWidths; - this.dataDoc.columnHeaders = new List( + this.dataDoc[this.fieldKey + '_columnHeaders'] = new List( headers.map(h => { h.setWidth(Math.abs(h.width) * scaleFactor); return h; @@ -352,7 +353,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { }); // we alter the pivot fields of the docs in case they are moved to a new column. const colIndex = this.getColumnFromXCoord(xCoord); - const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading); + const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading); DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader)); // used to notify sections to re-render this.docsDraggedRowCol.length = 0; @@ -365,12 +366,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { // This function is used to know which document a column SHOULD be in while it is being dragged. getColumnFromXCoord = (xCoord: number): number | undefined => { let colIndex: number | undefined = undefined; - const numColumns = this.columnHeaders.length; + const numColumns = this.colHeaderData.length; const coords = []; let colStartXCoord = 0; for (let i = 0; i < numColumns; i++) { coords.push(colStartXCoord); - colStartXCoord += this.columnHeaders[i].width * this.availableWidth + this.DividerWidth; + colStartXCoord += this.colHeaderData[i].width * this.availableWidth + this.DividerWidth; } coords.push(this.PanelWidth); for (let i = 0; i < numColumns; i++) { @@ -386,7 +387,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { getDocsFromXCoord = (xCoord: number): Doc[] => { const docsMatchingHeader: Doc[] = []; const colIndex = this.getColumnFromXCoord(xCoord); - const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading); + const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading); this.childDocs?.map(d => { if (d instanceof Promise) return; const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset'; @@ -401,7 +402,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { @action onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => { const docView = fieldProps.DocumentView?.(); - if (docView && (e.ctrlKey || docView.rootDoc._singleLine) && ['Enter'].includes(e.key)) { + if (docView && (e.ctrlKey || docView.rootDoc._createDocOnCR) && ['Enter'].includes(e.key)) { e.stopPropagation?.(); const newDoc = Doc.MakeCopy(docView.rootDoc, true); Doc.GetProto(newDoc).text = undefined; @@ -436,10 +437,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { } } } - } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { - const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' }); + } else if (de.complete.linkDragData?.dragDocument.embedContainer === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { + const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _layout_fitWidth: true, title: 'dropped annotation' }); this.props.addDocument?.(source); - de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { linkRelationship: 'doc annotation' }); // TODODO this is where in text links get passed + de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { link_relationship: 'doc annotation' }); // TODODO this is where in text links get passed e.stopPropagation(); } else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData); return false; @@ -468,7 +469,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { this.onPointerMove(true, e.clientX, e.clientY); docus?.map((doc: Doc) => this.addDocument(doc)); const newDoc = this.childDocs.lastElement(); - const colHeader = colInd === undefined ? 'unset' : StrCast(this.columnHeaders[colInd].heading); + const colHeader = colInd === undefined ? 'unset' : StrCast(this.colHeaderData[colInd].heading); newDoc[this.notetakingCategoryField] = colHeader; const docs = this.childDocList; if (docs && targInd !== -1) { @@ -502,7 +503,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { this.refList.push(ref); this.observer = new _global.ResizeObserver( action((entries: any) => { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { this.props.setHeight?.(height); @@ -516,7 +517,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { select={this.props.select} addDocument={this.addDocument} chromeHidden={this.chromeHidden} - columnHeaders={this.columnHeaders} + colHeaderData={this.colHeaderData} Document={this.props.Document} DataDoc={this.props.DataDoc} resizeColumns={this.resizeColumns} @@ -524,6 +525,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { numGroupColumns={this.numGroupColumns} gridGap={this.gridGap} pivotField={this.notetakingCategoryField} + fieldKey={this.fieldKey} dividerWidth={this.DividerWidth} maxColWidth={this.maxColWidth} availableWidth={this.availableWidth} @@ -546,15 +548,15 @@ export class CollectionNoteTakingView extends CollectionSubView() { @undoBatch @action addGroup = (value: string) => { - if (this.columnHeaders) { - for (const header of this.columnHeaders) { + if (this.colHeaderData) { + for (const header of this.colHeaderData) { if (header.heading === value) { alert('You cannot use an existing column name. Please try a new column name'); return value; } } } - const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null)); + const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); const newColWidth = 1 / (this.numGroupColumns + 1); columnHeaders.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)); value && this.resizeColumns(columnHeaders); @@ -566,7 +568,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { if (!e.isPropagationStopped()) { const subItems: ContextMenuProps[] = []; subItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); - subItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); + subItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' }); subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' }); ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' }); } @@ -576,8 +578,8 @@ export class CollectionNoteTakingView extends CollectionSubView() { @action setColumnStartXCoords = (movementXScreen: number, colIndex: number) => { const movementX = this.props.ScreenToLocalTransform().transformDirection(movementXScreen, 0)[0]; - const leftHeader = this.columnHeaders[colIndex]; - const rightHeader = this.columnHeaders[colIndex + 1]; + const leftHeader = this.colHeaderData[colIndex]; + const rightHeader = this.colHeaderData[colIndex + 1]; leftHeader.setWidth(leftHeader.width + movementX / this.availableWidth); rightHeader.setWidth(rightHeader.width - movementX / this.availableWidth); }; diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index 28bdd0cb9..63becac1e 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -29,8 +29,9 @@ interface CSVFieldColumnProps { docList: Doc[]; heading: string; pivotField: string; + fieldKey: string | undefined; chromeHidden?: boolean; - columnHeaders: SchemaHeaderField[] | undefined; + colHeaderData: SchemaHeaderField[] | undefined; headingObject: SchemaHeaderField | undefined; yMargin: number; numGroupColumns: number; @@ -61,9 +62,9 @@ export class CollectionNoteTakingViewColumn extends React.Component { const castedValue = this.getValue(value); if (castedValue) { - if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { + if (this.props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { return false; } this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue)); @@ -127,7 +128,7 @@ export class CollectionNoteTakingViewColumn extends React.Component { if (!value && !forceEmptyNote) return false; const key = this.props.pivotField; - const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _fitWidth: true, title: value, _autoHeight: true }); + const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true }); const colValue = this.getValue(this.props.heading); newDoc[key] = colValue; FormattedTextBox.SelectOnLoad = newDoc[Id]; @@ -141,11 +142,11 @@ export class CollectionNoteTakingViewColumn extends React.Component { - const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null)); + const colHdrData = Array.from(Cast(this.props.Document[this.props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); if (this.props.headingObject) { this.props.docList.forEach(d => (d[this.props.pivotField] = undefined)); - columnHeaders.splice(columnHeaders.indexOf(this.props.headingObject), 1); - this.props.resizeColumns(columnHeaders); + colHdrData.splice(colHdrData.indexOf(this.props.headingObject), 1); + this.props.resizeColumns(colHdrData); } }; @@ -211,7 +212,7 @@ export class CollectionNoteTakingViewColumn extends React.Component { Doc.GetProto(this.props.Document)[name] = ''; - const created = Docs.Create.TextDocument('', { title: name, _width: 250, _autoHeight: true }); + const created = Docs.Create.TextDocument('', { title: name, _width: 250, _layout_autoHeight: true }); if (created) { if (this.props.Document.isTemplateDoc) { Doc.MakeMetadataFieldTemplate(created, this.props.Document); @@ -243,7 +244,7 @@ export class CollectionNoteTakingViewColumn extends React.Component evContents} isEditingCallback={isEditing => isEditing && this.props.select(false)} SetValue={this.headingChanged} contents={evContents} oneLine={true} /> - {(this.props.columnHeaders?.length ?? 0) > 1 && ( + {(this.props.colHeaderData?.length ?? 0) > 1 && ( diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index 5b96a8682..ea0fbbc54 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -82,8 +82,8 @@ export class CollectionPileView extends CollectionSubView() { this.layoutDoc._width = NumCast(this.layoutDoc._starburstPileWidth, defaultSize); this.layoutDoc._height = NumCast(this.layoutDoc._starburstPileHeight, defaultSize); DocUtils.pileup(this.childDocs, undefined, undefined, NumCast(this.layoutDoc._width) / 2, false); - this.layoutDoc._panX = 0; - this.layoutDoc._panY = -10; + this.layoutDoc._freeform_panX = 0; + this.layoutDoc._freeform_panY = -10; this.props.Document._pileLayoutEngine = computePassLayout.name; } else { const defaultSize = NumCast(this.rootDoc._starburstDiameter, 500); @@ -91,7 +91,7 @@ export class CollectionPileView extends CollectionSubView() { this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[HeightSym]() / 2 - defaultSize / 2; this.layoutDoc._starburstPileWidth = this.layoutDoc[WidthSym](); this.layoutDoc._starburstPileHeight = this.layoutDoc[HeightSym](); - this.layoutDoc._panX = this.layoutDoc._panY = 0; + this.layoutDoc._freeform_panX = this.layoutDoc._freeform_panY = 0; this.layoutDoc._width = this.layoutDoc._height = defaultSize; this.props.Document._pileLayoutEngine = computeStarburstLayout.name; } diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 22a575989..6b4c8a3e9 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -24,7 +24,7 @@ import { undoBatch, UndoManager } from '../../util/UndoManager'; import { AudioWaveform } from '../AudioWaveform'; import { CollectionSubView } from '../collections/CollectionSubView'; import { LightboxView } from '../LightboxView'; -import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView'; +import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from '../nodes/DocumentView'; import { LabelBox } from '../nodes/LabelBox'; import { VideoBox } from '../nodes/VideoBox'; import './CollectionStackedTimeline.scss'; @@ -41,7 +41,9 @@ export type CollectionStackedTimelineProps = { mediaPath: string; dictationKey: string; rawDuration: number; + dataFieldKey: string; fieldKey: string; + thumbnails?: () => string[]; }; // trimming state: shows full clip, current trim bounds, or not trimming @@ -80,6 +82,9 @@ export class CollectionStackedTimeline extends CollectionSubView 0 ? new ImageField(thumbnails[nearest]) : undefined; + const imgField = this.thumbnails.length > 0 ? new ImageField(this.thumbnails[nearest]) : undefined; this._thumbnail = imgField?.url?.href ? imgField.url.href.replace('.png', '_m.png') : undefined; } } @@ -401,11 +405,9 @@ export class CollectionStackedTimeline extends CollectionSubView NumCast(this.layoutDoc._currentTimecode)) { + if (seekTimeInSeconds < NumCast(this.layoutDoc._layout_currentTimecode) && endTime > NumCast(this.layoutDoc._layout_currentTimecode)) { if (!this.layoutDoc.autoPlayAnchors && this.props.playing()) { this.props.Pause(); } else { @@ -455,7 +457,7 @@ export class CollectionStackedTimeline extends CollectionSubView NumCast(this.layoutDoc._currentTimecode) - 1e-4) { + if (seekTimeInSeconds < NumCast(this.layoutDoc._layout_currentTimecode) + 1e-4 && endTime > NumCast(this.layoutDoc._layout_currentTimecode) - 1e-4) { if (this.props.playing()) this.props.Pause(); else if (this.layoutDoc.autoPlayAnchors) this.props.Play(); else if (!this.layoutDoc.autoPlayAnchors) { @@ -596,6 +598,7 @@ export class CollectionStackedTimeline extends CollectionSubView void; + addDocTab: (doc: Doc, where: OpenWhere) => boolean; rangeClickScript: () => ScriptField; rangePlayScript: () => ScriptField; left: number; @@ -709,7 +714,7 @@ class StackedTimelineAnchor extends React.Component () => this.props.currentTimecode(), time => { const dictationDoc = Cast(this.props.layoutDoc['data-dictation'], Doc, null); - const isDictation = dictationDoc && LinkManager.Links(this.props.mark).some(link => Cast(link.anchor1, Doc, null)?.annotationOn === dictationDoc); + const isDictation = dictationDoc && LinkManager.Links(this.props.mark).some(link => Cast(link.link_anchor_1, Doc, null)?.annotationOn === dictationDoc); if ( !LightboxView.LightboxDoc && // bcz: when should links be followed? we don't want to move away from the video to follow a link but we can open it in a sidebar/etc. But we don't know that upfront. @@ -808,11 +813,9 @@ class StackedTimelineAnchor extends React.Component isDocumentActive={this.props.isDocumentActive} PanelWidth={width} PanelHeight={height} - fitWidth={returnTrue} + layout_fitWidth={returnTrue} ScreenToLocalTransform={screenXf} - addDocTab={returnFalse} pinToPres={emptyFunction} - whenChildContentsActiveChanged={emptyFunction} focus={focusFunc} isContentActive={returnFalse} searchFilterDocs={returnEmptyDoclist} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index eedf639aa..404ca5d65 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -49,7 +49,7 @@ export class CollectionStackingView extends CollectionSubView number; width: () => number; stackedDocTransform: () => Transform }[] = []; // Doesn't look like this field is being used anywhere. Obsolete? @@ -65,8 +65,8 @@ export class CollectionStackingView extends CollectionSubView(); + this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List(); } } @@ -154,14 +154,14 @@ export class CollectionStackingView extends CollectionSubView(); + if (!this.pivotField || this.colHeaderData instanceof Promise) return new Map(); - if (this.columnHeaders === undefined) { - setTimeout(() => (this.layoutDoc._columnHeaders = new List()), 0); + if (this.colHeaderData === undefined) { + setTimeout(() => (this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List()), 0); return new Map(); } - const columnHeaders = Array.from(this.columnHeaders); - const fields = new Map(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); + const colHeaderData = Array.from(this.colHeaderData); + const fields = new Map(colHeaderData.map(sh => [sh, []] as [SchemaHeaderField, []])); let changed = false; this.filteredChildren.map(d => { const sectionValue = (d[this.pivotField] ? d[this.pivotField] : `NO ${this.pivotField.toUpperCase()} VALUE`) as object; @@ -170,13 +170,13 @@ export class CollectionStackingView extends CollectionSubView sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`)); + const existingHeader = colHeaderData.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`)); if (existingHeader) { fields.get(existingHeader)!.push(d); } else { const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`); fields.set(newSchemaHeader, [d]); - columnHeaders.push(newSchemaHeader); + colHeaderData.push(newSchemaHeader); changed = true; } }); @@ -187,13 +187,13 @@ export class CollectionStackingView extends CollectionSubView !fields.get(key)!.length) .map(header => { fields.delete(header); - columnHeaders.splice(columnHeaders.indexOf(header), 1); + colHeaderData.splice(colHeaderData.indexOf(header), 1); changed = true; }); } changed && setTimeout( - action(() => this.columnHeaders?.splice(0, this.columnHeaders.length, ...columnHeaders)), + action(() => this.colHeaderData?.splice(0, this.colHeaderData.length, ...colHeaderData)), 0 ); return fields; @@ -206,12 +206,12 @@ export class CollectionStackingView extends CollectionSubView this.pivotField, - () => (this.layoutDoc._columnHeaders = new List()) + () => (this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List()) ); - this._autoHeightDisposer = reaction( - () => this.layoutDoc._autoHeight, - autoHeight => - autoHeight && + this._layout_autoHeightDisposer = reaction( + () => this.layoutDoc._layout_autoHeight, + layout_autoHeight => + layout_autoHeight && this.props.setHeight?.( Math.min( NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), @@ -224,7 +224,7 @@ export class CollectionStackingView extends CollectionSubView this.props.isAnyChildContentActive(); @@ -282,12 +282,12 @@ export class CollectionStackingView extends CollectionSubView([]) : undefined; - if (layoutKey !== 'layout' && docView.rootDoc[layoutKey] instanceof Doc) { - newDoc[layoutKey] = docView.rootDoc[layoutKey]; + if (layout_fieldKey !== 'layout' && docView.rootDoc[layout_fieldKey] instanceof Doc) { + newDoc[layout_fieldKey] = docView.rootDoc[layout_fieldKey]; } Doc.GetProto(newDoc).text = undefined; FormattedTextBox.SelectOnLoad = newDoc[Id]; @@ -327,19 +327,19 @@ export class CollectionStackingView extends CollectionSubView (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); - const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); - const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); + const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[WidthSym]() : 0); + const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[HeightSym]() : 0); if (nw && nh) { const colWid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); const docWid = this.layoutDoc._columnsFill ? colWid : Math.min(this.getDocWidth(d), colWid); return Math.min(maxHeight, (docWid * nh) / nw); } const childHeight = NumCast(childLayoutDoc._height); - const panelHeight = childLayoutDoc._fitWidth || this.props.childFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; + const panelHeight = childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; return Math.min(childHeight, maxHeight, panelHeight); } @@ -460,10 +460,10 @@ export class CollectionStackingView extends CollectionSubView { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { this.props.setHeight?.(height); @@ -539,7 +539,7 @@ export class CollectionStackingView extends CollectionSubView { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), 0); this.props.setHeight?.(this.headerMargin + height); } @@ -608,9 +608,9 @@ export class CollectionStackingView extends CollectionSubView { - if (value && this.columnHeaders) { + if (value && this.colHeaderData) { const schemaHdrField = new SchemaHeaderField(value); - this.columnHeaders.push(schemaHdrField); + this.colHeaderData.push(schemaHdrField); return true; } return false; @@ -630,7 +630,7 @@ export class CollectionStackingView extends CollectionSubView (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); - optionItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); + optionItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' }); optionItems.push({ description: 'Clear All', event: () => (this.dataDoc[this.fieldKey ?? 'data'] = new List([])), icon: 'times' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' }); } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index d62c4dc62..243550c0b 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -34,7 +34,7 @@ interface CSVFieldColumnProps { heading: string; pivotField: string; chromeHidden?: boolean; - columnHeaders: SchemaHeaderField[] | undefined; + colHeaderData: SchemaHeaderField[] | undefined; headingObject: SchemaHeaderField | undefined; yMargin: number; columnWidth: number; @@ -93,7 +93,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { const drop = { docs: de.complete.docDragData?.droppedDocuments, val: this.getValue(this._heading) }; - drop.docs?.forEach(d => Doc.SetInPlace(d, this.props.pivotField, drop.val, false)); + this.props.pivotField && drop.docs?.forEach(d => Doc.SetInPlace(d, this.props.pivotField, drop.val, false)); }); getValue = (value: string): any => { const parsed = parseInt(value); @@ -107,7 +107,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { const castedValue = this.getValue(value); if (castedValue) { - if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { + if (this.props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { return false; } this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue)); @@ -134,7 +134,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { if (!value && !forceEmptyNote) return false; const key = this.props.pivotField; - const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _fitWidth: true, title: value, _autoHeight: true }); + const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true }); newDoc[key] = this.getValue(this.props.heading); const maxHeading = this.props.docList.reduce((maxHeading, doc) => (NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading), 0); const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; @@ -147,9 +147,9 @@ export class CollectionStackingViewFieldColumn extends React.Component { this.props.docList.forEach(d => (d[this.props.pivotField] = undefined)); - if (this.props.columnHeaders && this.props.headingObject) { - const index = this.props.columnHeaders.indexOf(this.props.headingObject); - this.props.columnHeaders.splice(index, 1); + if (this.props.colHeaderData && this.props.headingObject) { + const index = this.props.colHeaderData.indexOf(this.props.headingObject); + this.props.colHeaderData.splice(index, 1); } }; @@ -163,15 +163,15 @@ export class CollectionStackingViewFieldColumn extends React.Component { - // is MakeAlias a way to make a copy of a doc without rendering it? - const alias = Doc.MakeAlias(this.props.Document); - alias._width = this.props.columnWidth / (this.props.columnHeaders?.length || 1); - alias._pivotField = undefined; + // is MakeEmbedding a way to make a copy of a doc without rendering it? + const embedding = Doc.MakeEmbedding(this.props.Document); + embedding._width = this.props.columnWidth / (this.props.colHeaderData?.length || 1); + embedding._pivotField = undefined; let value = this.getValue(this._heading); value = typeof value === 'string' ? `"${value}"` : value; - alias.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name }); - if (alias.viewSpecScript) { - DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY); + embedding.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name }); + if (embedding.viewSpecScript) { + DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([embedding]), e.clientX, e.clientY); return true; } return false; @@ -266,7 +266,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { Doc.GetProto(this.props.Document)[name] = ''; - const created = Docs.Create.TextDocument('', { title: name, _width: 250, _autoHeight: true }); + const created = Docs.Create.TextDocument('', { title: name, _width: 250, _layout_autoHeight: true }); if (created) { if (this.props.Document.isTemplateDoc) { Doc.MakeMetadataFieldTemplate(created, this.props.Document); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5b9453666..008de1944 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -129,7 +129,7 @@ export function CollectionSubView(moreProps?: X) { notFiltered = (!searchDocs.length || searchDocs.includes(d)) && DocUtils.FilterDocs([d], childDocFilters, docRangeFilters, this.props.Document).length > 0; const fieldKey = Doc.LayoutFieldKey(d); const annos = !Field.toString(Doc.LayoutField(d) as Field).includes(CollectionView.name); - const data = d[annos ? fieldKey + '-annotations' : fieldKey]; + const data = d[annos ? fieldKey + '_annotations' : fieldKey]; if (data !== undefined) { let subDocs = DocListCast(data); if (subDocs.length > 0) { @@ -141,7 +141,7 @@ export function CollectionSubView(moreProps?: X) { const fieldKey = Doc.LayoutFieldKey(t); const annos = !Field.toString(Doc.LayoutField(t) as Field).includes(CollectionView.name); notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], childDocFilters, docRangeFilters, d).length)); - DocListCast(t[annos ? fieldKey + '-annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc)); + DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc)); }); subDocs = newarray; } @@ -188,9 +188,9 @@ export function CollectionSubView(moreProps?: X) { protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetAction: dropActionType) { if (de.complete.docDragData) { - // if targetDropAction is, say 'alias', but we're just dragging within a collection, we want to ignore the targetAction. + // if targetDropAction is, say 'embed', but we're just dragging within a collection, we want to ignore the targetAction. // otherwise, the targetAction should become the actual action (which can still be overridden by the userDropAction -eg, shift/ctrl keys) - if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) { + if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.embedContainer === this.props.Document && this.childDocs.includes(d))) { de.complete.docDragData.dropAction = targetAction; } e.stopPropagation(); @@ -282,7 +282,7 @@ export function CollectionSubView(moreProps?: X) { addDocument(Docs.Create.WebDocument(href, { ...options, title: href })); } } else if (text) { - addDocument(Docs.Create.TextDocument(text, { ...options, _showTitle: StrCast(Doc.UserDoc().showTitle), _width: 100, _height: 25 })); + addDocument(Docs.Create.TextDocument(text, { ...options, _layout_showTitle: StrCast(Doc.UserDoc().layout_showTitle), _width: 100, _height: 25 })); } return; } @@ -375,7 +375,7 @@ export function CollectionSubView(moreProps?: X) { _width: 400, _height: 512, _nativeWidth: 850, - useCors: true, + data_useCors: true, }) ); return; @@ -417,7 +417,7 @@ export function CollectionSubView(moreProps?: X) { proto._height = 20; return proto; }), - { _width: 150, _height: 600, title: 'across', backgroundColor: 'white', _singleLine: true } + { _width: 150, _height: 600, title: 'across', backgroundColor: 'white', _createDocOnCR: true } ) ); }); diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 3cdb460a3..6135154c3 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -35,7 +35,7 @@ export class CollectionTimeView extends CollectionSubView() { async componentDidMount() { this.props.setContentView?.(this); //const detailView = (await DocCastAsync(this.props.Document.childClickedOpenTemplateView)) || DocUtils.findTemplate("detailView", StrCast(this.rootDoc.type), ""); - ///const childText = "const alias = getAlias(self); switchView(alias, detailView); alias.dropAction='alias'; useRightSplit(alias, shiftKey); "; + ///const childText = "const embedding = getEmbedding(self); switchView(embedding, detailView); embedding.dropAction='embed'; useRightSplit(embedding, shiftKey); "; runInAction(() => { this._childClickedScript = ScriptField.MakeScript('openInLightbox(self)', { this: Doc.name }); this._viewDefDivClick = ScriptField.MakeScript('pivotColumnClick(this,payload)', { payload: 'any' }); @@ -55,10 +55,10 @@ export class CollectionTimeView extends CollectionSubView() { if (addAsAnnotation) { // when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered - if (Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), null) !== undefined) { - Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), []).push(anchor); + if (Cast(this.dataDoc[this.props.fieldKey + '_annotations'], listSpec(Doc), null) !== undefined) { + Cast(this.dataDoc[this.props.fieldKey + '_annotations'], listSpec(Doc), []).push(anchor); } else { - this.dataDoc[this.props.fieldKey + '-annotations'] = new List([anchor]); + this.dataDoc[this.props.fieldKey + '_annotations'] = new List([anchor]); } } return anchor; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f774781ab..095e34c39 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -104,7 +104,7 @@ export class CollectionTreeView extends CollectionSubView this.rootDoc.autoHeight, + () => this.rootDoc.layout_autoHeight, auto => auto && this.computeHeight(), { fireImmediately: true } ); @@ -114,25 +114,25 @@ export class CollectionTreeView extends CollectionSubView p + Number(getComputedStyle(r).height.replace('px', '')), this.marginBot()) + 6; - this.layoutDoc._autoHeightMargins = bodyHeight; + this.layoutDoc._layout_autoHeightMargins = bodyHeight; !this.props.dontRegisterView && this.props.setHeight?.(bodyHeight + titleHeight); } }; unobserveHeight = (ref: any) => { this.refList.delete(ref); - this.rootDoc.autoHeight && this.computeHeight(); + this.rootDoc.layout_autoHeight && this.computeHeight(); }; observeHeight = (ref: any) => { if (ref) { this.refList.add(ref); this.observer = new _global.ResizeObserver( action((entries: any) => { - if (this.rootDoc.autoHeight && ref && this.refList.size && !SnappingManager.GetIsDragging()) { + if (this.rootDoc.layout_autoHeight && ref && this.refList.size && !SnappingManager.GetIsDragging()) { this.computeHeight(); } }) ); - this.rootDoc.autoHeight && this.computeHeight(); + this.rootDoc.layout_autoHeight && this.computeHeight(); this.observer.observe(ref); } }; @@ -144,7 +144,7 @@ export class CollectionTreeView extends CollectionSubView { const dragData = de.complete.docDragData; if (dragData) { - const isInTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.props.Document) || dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d)); + const isInTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.props.Document) || dragData.draggedDocuments.some(d => d.embedContainer === this.doc && this.childDocs.includes(d)); dragData.dropAction = targetAction && !isInTree() ? targetAction : this.doc === dragData?.treeViewDoc ? 'same' : dragData.dropAction; } }; @@ -176,7 +176,7 @@ export class CollectionTreeView extends CollectionSubView (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => { const res = flg && Doc.AddDocToList(this.doc[DataSym], this.props.fieldKey, doc, relativeTo, before); - res && (doc.context = this.props.Document); + res && (doc.embedContainer = this.props.Document); return res; }, true); if (this.doc.resolvedDataDoc instanceof Promise) return false; @@ -234,7 +234,7 @@ export class CollectionTreeView extends CollectionSubView NumCast(this.doc._yMargin); marginBot = () => NumCast(this.doc._yMargin); documentTitleWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.panelWidth()); - documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins); + documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.layout_autoHeightMargins); truncateTitleWidth = () => this.treeViewtruncateTitleWidth; onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick); panelWidth = () => Math.max(0, this.props.PanelWidth() - 2 * this.marginX() * (this.props.NativeDimScaling?.() || 1)); - addAnnotationDocument = (doc: Doc | Doc[]) => this.addDocument(doc, `${this.props.fieldKey}-annotations`) || false; - remAnnotationDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false; + addAnnotationDocument = (doc: Doc | Doc[]) => this.addDocument(doc, `${this.props.fieldKey}_annotations`) || false; + remAnnotationDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, `${this.props.fieldKey}_annotations`) || false; moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) => - this.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}-annotations`) || false; + this.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}_annotations`) || false; @observable _headerHeight = 0; @computed get content() { @@ -430,7 +430,7 @@ export class CollectionTreeView extends CollectionSubView {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeViewHasOverlay ? ( @@ -443,7 +443,7 @@ export class CollectionTreeView extends CollectionSubView boolean | undefined; // whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode) childContentsActive?: () => boolean | undefined; - childFitWidth?: (child: Doc) => boolean; - childShowTitle?: () => string; + childLayoutFitWidth?: (child: Doc) => boolean; + childlayout_showTitle?: () => string; childOpacity?: () => number; childContextMenuItems?: () => { script: ScriptField; label: string }[]; childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children @@ -134,8 +134,8 @@ export class CollectionView extends ViewBoxAnnotatableComponent func(CollectionViewType.Freeform), icon: 'signature' }, { description: 'Schema', event: () => func(CollectionViewType.Schema), icon: 'th-list' }, { description: 'Tree', event: () => func(CollectionViewType.Tree), icon: 'tree' }, - { description: 'Stacking', event: () => (func(CollectionViewType.Stacking)._autoHeight = true), icon: 'ellipsis-v' }, - { description: 'Notetaking', event: () => (func(CollectionViewType.NoteTaking)._autoHeight = true), icon: 'ellipsis-v' }, + { description: 'Stacking', event: () => (func(CollectionViewType.Stacking)._layout_autoHeight = true), icon: 'ellipsis-v' }, + { description: 'Notetaking', event: () => (func(CollectionViewType.NoteTaking)._layout_autoHeight = true), icon: 'ellipsis-v' }, { description: 'Multicolumn', event: () => func(CollectionViewType.Multicolumn), icon: 'columns' }, { description: 'Multirow', event: () => func(CollectionViewType.Multirow), icon: 'columns' }, { description: 'Masonry', event: () => func(CollectionViewType.Masonry), icon: 'columns' }, @@ -159,7 +159,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent { - const newRendition = Doc.MakeAlias(this.rootDoc); + const newRendition = Doc.MakeEmbedding(this.rootDoc); newRendition._viewType = vtype; this.props.addDocTab(newRendition, OpenWhere.addRight); return newRendition; @@ -190,9 +190,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent { - const alias = Doc.MakeAlias(this.rootDoc); - DocUtils.makeCustomViewClicked(alias, undefined, func.key); - this.props.addDocTab(alias, OpenWhere.addRight); + const embedding = Doc.MakeEmbedding(this.rootDoc); + DocUtils.makeCustomViewClicked(embedding, undefined, func.key); + this.props.addDocTab(embedding, OpenWhere.addRight); }, }) ); diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 45604c1bf..69963736b 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -252,11 +252,11 @@ export class TabDocView extends React.Component { const pinDoc = Doc.MakeDelegate(anchorDoc && anchorDoc !== doc ? anchorDoc : doc); pinDoc.presentationTargetDoc = anchorDoc ?? doc; pinDoc.title = doc.title + ' - Slide'; - pinDoc.data = new List(); // the children of the alias' layout are the presentation slide children. the alias' data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data + pinDoc.data = new List(); // the children of the embedding's layout are the presentation slide children. the embedding's data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data pinDoc.presMovement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom; pinDoc.presDuration = pinDoc.presDuration ?? 1000; pinDoc.groupWithUp = false; - pinDoc.context = curPres; + pinDoc.embedContainer = curPres; // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area pinDoc.treeViewHeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling. @@ -264,7 +264,7 @@ export class TabDocView extends React.Component { pinDoc.treeViewFieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field pinDoc.treeViewExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header - const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null); + const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null); if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc); if (!pinProps?.audioRange && duration !== undefined) { @@ -283,7 +283,7 @@ export class TabDocView extends React.Component { pinDoc.title = doc.title + ' (move)'; pinDoc.presMovement = PresMovement.Pan; } - if (pinDoc.isInkMask) { + if (pinDoc.stroke_isInkMask) { pinDoc.presHideAfter = true; pinDoc.presHideBefore = true; pinDoc.presMovement = PresMovement.None; @@ -357,7 +357,7 @@ export class TabDocView extends React.Component { switch (whereFields[0]) { case undefined: case OpenWhere.lightbox: if (this.layoutDoc?._isLightbox) { - const lightboxView = !doc.annotationOn && DocCast(doc.context) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.context)) : undefined; + const lightboxView = !doc.annotationOn && DocCast(doc.embedContainer) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.embedContainer)) : undefined; const data = lightboxView?.dataDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)]; if (lightboxView && (!data || data instanceof List)) { lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)] = new List([doc]); @@ -409,7 +409,7 @@ export class TabDocView extends React.Component { miniMapColor = () => this.tabColor; tabView = () => this._view; disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform; - hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap); + hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.layout_hideMinimap); @computed get docView() { return !this._activated || !this._document ? null : ( @@ -449,19 +449,19 @@ export class TabDocView extends React.Component { pinToPres={TabDocView.PinDoc} /> - {this._document.hideMinimap ? 'Open minimap' : 'Close minimap'}}> + {this._document.layout_hideMinimap ? 'Open minimap' : 'Close minimap'}}>
e.stopPropagation()} onClick={action(e => { e.stopPropagation(); - this._document!.hideMinimap = !this._document!.hideMinimap; + this._document!.layout_hideMinimap = !this._document!.layout_hideMinimap; })}>
@@ -559,8 +559,8 @@ export class TabMinimapView extends React.Component { this, e, action((e: PointerEvent, down: number[], delta: number[]) => { - doc._panX = clamp(NumCast(doc._panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim); - doc._panY = clamp(NumCast(doc._panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim); + doc._freeform_panX = clamp(NumCast(doc._freeform_panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim); + doc._freeform_panY = clamp(NumCast(doc._freeform_panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim); return false; }), emptyFunction, @@ -569,10 +569,10 @@ export class TabMinimapView extends React.Component { }; render() { if (!this.renderBounds) return null; - const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100; - const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100; - const miniLeft = 50 + ((NumCast(this.props.document._panX) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2; - const miniTop = 50 + ((NumCast(this.props.document._panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2; + const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100; + const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100; + const miniLeft = 50 + ((NumCast(this.props.document._freeform_) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2; + const miniTop = 50 + ((NumCast(this.props.document._freeform_panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2; const miniSize = this.returnMiniSize(); return this.props.hideMinimap() ? null : (
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 4adf86683..92b70cb5a 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -102,7 +102,7 @@ export class TreeView extends React.Component { private _treedropDisposer?: DragManager.DragDropDisposer; get treeViewOpenIsTransient() { - return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsPrototype(this.doc); + return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsDocDataProto(this.doc); } set treeViewOpen(c: boolean) { if (this.treeViewOpenIsTransient) this._transientOpenState = c; @@ -125,7 +125,7 @@ export class TreeView extends React.Component { : this.props.treeView.fileSysMode ? this.doc.isFolder ? this.fieldKey - : 'aliases' // for displaying + : 'embeddings' // for displaying : this.props.treeView.outlineMode || this.childDocs ? this.fieldKey : Doc.noviceMode @@ -160,11 +160,11 @@ export class TreeView extends React.Component { @computed get childLinks() { return this.childDocList('links'); } - @computed get childAliases() { - return this.childDocList('aliases'); + @computed get childEmbeddings() { + return this.childDocList('proto_embeddings'); } @computed get childAnnos() { - return this.childDocList(this.fieldKey + '-annotations'); + return this.childDocList(this.fieldKey + '_annotations'); } @computed get selected() { return SelectionManager.IsSelected(this._docRef); @@ -219,11 +219,13 @@ export class TreeView extends React.Component { if (this.props.document.isFolder || Doc.IsSystem(this.props.document)) { this.treeViewOpen = !this.treeViewOpen; } else { - // choose an appropriate alias or make one. --- choose the first alias that (1) user owns, (2) has no context field ... otherwise make a new alias - const bestAlias = - docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsPrototype(docView.props.Document) ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail); - const nextBestAlias = DocListCast(this.props.document.aliases).find(doc => doc.author === Doc.CurrentUserEmail); - this.props.addDocTab(bestAlias ?? nextBestAlias ?? Doc.MakeAlias(this.props.document), OpenWhere.lightbox); + // choose an appropriate embedding or make one. --- choose the first embedding that (1) user owns, (2) has no context field ... otherwise make a new embedding + const bestEmbedding = + docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsDocDataProto(docView.props.Document) + ? docView.props.Document + : DocListCast(this.props.document.proto_embeddings).find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail); + const nextBestEmbedding = DocListCast(this.props.document.proto_embeddings).find(doc => doc.author === Doc.CurrentUserEmail); + this.props.addDocTab(bestEmbedding ?? nextBestEmbedding ?? Doc.MakeEmbedding(this.props.document), OpenWhere.lightbox); } }; @@ -311,16 +313,16 @@ export class TreeView extends React.Component { treeViewExpandedViewLock: true, treeViewExpandedView: 'data', _viewType: CollectionViewType.Tree, - hideLinkButton: true, - _showSidebar: true, - _fitWidth: true, + layout_hideLinkButton: true, + _layout_showSidebar: true, + _layout_fitWidth: true, treeViewType: TreeViewType.outline, x: 0, y: 0, _xMargin: 0, _yMargin: 0, - _autoHeight: true, - _singleLine: true, + _layout_autoHeight: true, + _createDocOnCR: true, _width: 1000, _height: 10, }); @@ -359,7 +361,7 @@ export class TreeView extends React.Component { if (de.complete.linkDragData) { const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor(); const destDoc = this.doc; - DocUtils.MakeLink(sourceDoc, destDoc, { linkRelationship: 'tree link' }); + DocUtils.MakeLink(sourceDoc, destDoc, { link_relationship: 'tree link' }); e.stopPropagation(); } const docDragData = de.complete.docDragData; @@ -378,7 +380,7 @@ export class TreeView extends React.Component { const innerAdd = (doc: Doc) => { const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[this.fieldKey])) instanceof ComputedField; const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, this.fieldKey, doc); - dataIsComputed && (doc.context = this.doc.context); + dataIsComputed && (doc.embedContainer = this.doc.embedContainer); return added; }; return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean); @@ -413,7 +415,7 @@ export class TreeView extends React.Component { (() => { const aspect = Doc.NativeAspect(layoutDoc); if (aspect) return this.embeddedPanelWidth() / (aspect || 1); - return layoutDoc._fitWidth + return layoutDoc._layout_fitWidth ? !Doc.NativeHeight(layoutDoc) ? NumCast(layoutDoc._height) : Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.treeViewParent._height))) @@ -441,7 +443,7 @@ export class TreeView extends React.Component { const innerAdd = (doc: Doc) => { const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField; const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); - dataIsComputed && (doc.context = this.doc.context); + dataIsComputed && (doc.embedContainer = this.doc.embedContainer); return added; }; return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean); @@ -527,7 +529,7 @@ export class TreeView extends React.Component { TraceMobx(); const expandKey = this.treeViewExpandedView; const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; label: string } }) ?? {}; - if (['links', 'annotations', 'aliases', this.fieldKey].includes(expandKey)) { + if (['links', 'annotations', 'embeddings', this.fieldKey].includes(expandKey)) { const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None); const sortKeys = Object.keys(sortings); const curSortIndex = Math.max( @@ -549,12 +551,12 @@ export class TreeView extends React.Component { } const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField; const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); - !dataIsComputed && added && (doc.context = this.doc.context); + !dataIsComputed && added && (doc.embedContainer = this.doc.embedContainer); return added; }; const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true); - const docs = expandKey === 'aliases' ? this.childAliases : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs; + const docs = expandKey === 'embeddings' ? this.childEmbeddings : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs; let downX = 0, downY = 0; if (docs?.length && this._renderCount < docs?.length) { @@ -706,13 +708,13 @@ export class TreeView extends React.Component { } @computed get validExpandViewTypes() { - const annos = () => (DocListCast(this.doc[this.fieldKey + '-annotations']).length && !this.props.treeView.dashboardMode ? 'annotations' : ''); + const annos = () => (DocListCast(this.doc[this.fieldKey + '_annotations']).length && !this.props.treeView.dashboardMode ? 'annotations' : ''); const links = () => (LinkManager.Links(this.doc).length && !this.props.treeView.dashboardMode ? 'links' : ''); const data = () => (this.childDocs || this.props.treeView.dashboardMode ? this.fieldKey : ''); - const aliases = () => (this.props.treeView.dashboardMode ? '' : 'aliases'); + const embeddings = () => (this.props.treeView.dashboardMode ? '' : 'embeddings'); const fields = () => (Doc.noviceMode ? '' : 'fields'); const layout = Doc.noviceMode || this.doc.viewType === CollectionViewType.Docking ? [] : ['layout']; - return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [aliases(), links(), annos()] : []), fields()].filter(m => m); + return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [embeddings(), links(), annos()] : []), fields()].filter(m => m); } @action expandNextviewType = () => { @@ -759,7 +761,7 @@ export class TreeView extends React.Component { const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'New Folder' }; const deleteItem = { script: ScriptField.MakeFunction(`scriptContext.deleteItem()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'Delete' }; const folderOp = this.childDocs?.length ? [makeFolder] : []; - const openAlias = { script: ScriptField.MakeFunction(`openDoc(getAlias(self), ${OpenWhere.addRight})`)!, icon: 'copy', label: 'Open Alias' }; + const openEmbedding = { script: ScriptField.MakeFunction(`openDoc(getEmbedding(self), ${OpenWhere.addRight})`)!, icon: 'copy', label: 'Open Embedding' }; const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, icon: 'eye', label: 'Focus or Open' }; return [ ...(this.props.contextMenuItems ?? []).filter(mi => (!mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result)), @@ -768,10 +770,10 @@ export class TreeView extends React.Component { : Doc.IsSystem(this.doc) ? [] : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) - ? [openAlias, makeFolder] + ? [openEmbedding, makeFolder] : this.doc.viewType === CollectionViewType.Docking ? [] - : [deleteItem, openAlias, focusDoc]), + : [deleteItem, openEmbedding, focusDoc]), ]; }; childContextMenuItems = () => { @@ -896,7 +898,7 @@ export class TreeView extends React.Component { } })} Document={this.doc} - fitWidth={returnTrue} + layout_fitWidth={returnTrue} DataDoc={undefined} scriptContext={this} hideDecorationTitle={this.props.treeView.outlineMode} @@ -985,7 +987,7 @@ export class TreeView extends React.Component { ref={action((r: DocumentView | null) => (this._dref = r))} Document={this.doc} DataDoc={undefined} - fitWidth={this.fitWidthFilter} + layout_fitWidth={this.fitWidthFilter} PanelWidth={this.embeddedPanelWidth} PanelHeight={this.embeddedPanelHeight} LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined} @@ -1179,7 +1181,7 @@ export class TreeView extends React.Component { TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined; Doc.AddDocToList(newParent, fieldKey, child, addAfter, false); newParent.treeViewOpen = true; - child.context = treeView.Document; + child.embedContainer = treeView.Document; } }; const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1])); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 0dfd119d7..68ba3d368 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -34,11 +34,11 @@ export class CollectionFreeFormLinkView extends React.Component [ this.props.A.props.ScreenToLocalTransform(), - Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor1, Doc, null)?.annotationOn, Doc, null)?.scrollTop, - Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor1, Doc, null)?.annotationOn, Doc, null)?.[CssSym], + Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop, + Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.[CssSym], this.props.B.props.ScreenToLocalTransform(), - Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor2, Doc, null)?.annotationOn, Doc, null)?.scrollTop, - Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor2, Doc, null)?.annotationOn, Doc, null)?.[CssSym], + Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop, + Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.[CssSym], ], action(() => { this._start = Date.now(); @@ -58,7 +58,7 @@ export class CollectionFreeFormLinkView extends React.Component (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), + action(() => (!LinkDocs.length || !linkDoc.layout_linkDisplay) && (this._opacity = 0.05)), 750 ); // this will unhighlight the link line. const a = A.ContentDiv.getBoundingClientRect(); @@ -72,36 +72,36 @@ export class CollectionFreeFormLinkView extends React.Component= 0 && mpx <= 1) linkDoc.anchor1_x = mpx * 100; - if (mpy >= 0 && mpy <= 1) linkDoc.anchor1_y = mpy * 100; + if (mpx >= 0 && mpx <= 1) linkDoc.link_anchor_1_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.link_anchor_1_y = mpy * 100; if (getComputedStyle(targetAhyperlink).fontSize === '0px') linkDoc.opacity = 0; else linkDoc.opacity = 1; } if (!targetBhyperlink) { - if (linkDoc.linkAutoMove) { - linkDoc.anchor2_x = ((bpt.point.x - bleft) / bwidth) * 100; - linkDoc.anchor2_y = ((bpt.point.y - btop) / bheight) * 100; + if (linkDoc.layout_autoMoveAnchors) { + linkDoc.link_anchor_2_x = ((bpt.point.x - bleft) / bwidth) * 100; + linkDoc.link_anchor_2_y = ((bpt.point.y - btop) / bheight) * 100; } } else { const m = targetBhyperlink.getBoundingClientRect(); const mp = B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); const mpx = mp[0] / B.props.PanelWidth(); const mpy = mp[1] / B.props.PanelHeight(); - if (mpx >= 0 && mpx <= 1) linkDoc.anchor2_x = mpx * 100; - if (mpy >= 0 && mpy <= 1) linkDoc.anchor2_y = mpy * 100; + if (mpx >= 0 && mpx <= 1) linkDoc.link_anchor_2_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.link_anchor_2_y = mpy * 100; if (getComputedStyle(targetBhyperlink).fontSize === '0px') linkDoc.opacity = 0; else linkDoc.opacity = 1; } @@ -112,8 +112,8 @@ export class CollectionFreeFormLinkView extends React.Component { - this.props.LinkDocs[0].linkOffsetX = NumCast(this.props.LinkDocs[0].linkOffsetX) + delta[0]; - this.props.LinkDocs[0].linkOffsetY = NumCast(this.props.LinkDocs[0].linkOffsetY) + delta[1]; + this.props.LinkDocs[0].link_relationship_OffsetX = NumCast(this.props.LinkDocs[0].link_relationship_OffsetX) + delta[0]; + this.props.LinkDocs[0].link_relationship_OffsetY = NumCast(this.props.LinkDocs[0].link_relationship_OffsetY) + delta[1]; return false; }, emptyFunction, @@ -205,8 +205,8 @@ export class CollectionFreeFormLinkView extends React.Component; + const linkRelationship = Field.toString(link?.link_relationship as any as Field); //get string representing relationship + const linkRelationshipList = Doc.UserDoc().link_relationshipList as List; const linkColorList = Doc.UserDoc().linkColorList as List; - const linkRelationshipSizes = Doc.UserDoc().linkRelationshipSizes as List; + const linkRelationshipSizes = Doc.UserDoc().link_relationshipSizes as List; const currRelationshipIndex = linkRelationshipList.indexOf(linkRelationship); - const linkDescription = Field.toString(link.description as any as Field); + const linkDescription = Field.toString(link.link_description as any as Field); const linkSize = currRelationshipIndex === -1 || currRelationshipIndex >= linkRelationshipSizes.length ? -1 : linkRelationshipSizes[currRelationshipIndex]; @@ -261,11 +261,11 @@ export class CollectionFreeFormLinkView extends React.Component @@ -294,7 +294,7 @@ export class CollectionFreeFormLinkView extends React.Component {textX === undefined || !linkDescription ? null : ( diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 08e3174d1..4d18ebeea 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -100,13 +100,13 @@ export class CollectionFreeFormView extends CollectionSubView { if (this.props.DocumentView?.().nativeWidth) return; const vals = this.fitToContentVals; - this.layoutDoc._panX = vals.bounds.cx; - this.layoutDoc._panY = vals.bounds.cy; - this.layoutDoc._viewScale = vals.scale; + this.layoutDoc._freeform_panX = vals.bounds.cx; + this.layoutDoc._freeform_panY = vals.bounds.cy; + this.layoutDoc._freeform_scale = vals.scale; }; freeformData = (force?: boolean) => (!this._firstRender && (this.fitContentsToBox || force) ? this.fitToContentVals : undefined); reverseNativeScaling = () => (this.fitContentsToBox ? true : false); - // panx, pany, zoomscale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document. + // freeform_panx, freeform_pany, freeform_scale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document. // this search order, for example, allows icons of cropped images to find the panx/pany/zoom on the cropped image's data doc instead of the usual layout doc because the zoom/panX/panY define the cropped image - panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.panX, 1)); - panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.panY, 1)); + panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1)); + panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panY, 1)); zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.[this.scaleFieldKey], 1)); contentTransform = () => this.props.isAnnotationOverlay && this.zoomScaling() === 1 ? `` : `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`; @@ -297,7 +297,7 @@ export class CollectionFreeFormView extends CollectionSubView= -1e-4 && curTime <= endTime); } @@ -348,7 +348,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout) .slice() .sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); - zsorted.forEach((doc, index) => (doc.zIndex = doc.isInkMask ? 5000 : index + 1)); + zsorted.forEach((doc, index) => (doc.zIndex = doc.stroke_isInkMask ? 5000 : index + 1)); const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000)); const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)]; @@ -366,7 +366,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout) .reduce((cluster, cd) => { - const grouping = this.props.Document._useClusters ? NumCast(cd.cluster, -1) : NumCast(cd.group, -1); + const grouping = this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster, -1) : NumCast(cd.group, -1); if (grouping !== -1) { const layoutDoc = Doc.Layout(cd); const cx = NumCast(cd.x) - this._clusterDistance / 2; @@ -463,10 +463,10 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).filter(cd => (this.props.Document._useClusters ? NumCast(cd.cluster) : NumCast(cd.group, -1)) === cluster); + const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === cluster); const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.DocumentView?.())!); const { left, top } = clusterDocs[0].getBounds() || { left: 0, top: 0 }; - const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'alias' : undefined); + const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'embed' : undefined); de.moveDocument = this.props.moveDocument; de.offset = this.getTransform().transformDirection(ptsParent.clientX - left, ptsParent.clientY - top); DragManager.StartDocumentDrag( @@ -485,8 +485,8 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).map(c => this.updateCluster(c)); } @@ -494,38 +494,43 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout); - if (this.props.Document._useClusters) { + if (this.props.Document._freeform_useClusters) { const docFirst = docs[0]; docs.map(doc => this._clusterSets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1))); - const preferredInd = NumCast(docFirst.cluster); - docs.map(doc => (doc.cluster = -1)); + const preferredInd = NumCast(docFirst.layout_cluster); + docs.map(doc => (doc.layout_cluster = -1)); docs.map(doc => this._clusterSets.map((set, i) => set.map(member => { - if (docFirst.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { - docFirst.cluster = i; + if (docFirst.layout_cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { + docFirst.layout_cluster = i; } }) ) ); - if (docFirst.cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) { - docFirst.cluster = preferredInd; + if ( + docFirst.layout_cluster === -1 && + preferredInd !== -1 && + this._clusterSets.length > preferredInd && + (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) + ) { + docFirst.layout_cluster = preferredInd; } this._clusterSets.map((set, i) => { - if (docFirst.cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { - docFirst.cluster = i; + if (docFirst.layout_cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { + docFirst.layout_cluster = i; } }); - if (docFirst.cluster === -1) { + if (docFirst.layout_cluster === -1) { docs.map(doc => { - doc.cluster = this._clusterSets.length; + doc.layout_cluster = this._clusterSets.length; this._clusterSets.push([doc]); }); } else if (this._clusterSets.length) { - for (let i = this._clusterSets.length; i <= NumCast(docFirst.cluster); i++) !this._clusterSets[i] && this._clusterSets.push([]); - docs.map(doc => this._clusterSets[(doc.cluster = NumCast(docFirst.cluster))].push(doc)); + for (let i = this._clusterSets.length; i <= NumCast(docFirst.layout_cluster); i++) !this._clusterSets[i] && this._clusterSets.push([]); + docs.map(doc => this._clusterSets[(doc.layout_cluster = NumCast(docFirst.layout_cluster))].push(doc)); } - childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.cluster === i) && this.updateCluster(child)); + childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.layout_cluster === i) && this.updateCluster(child)); } } @@ -533,31 +538,31 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout); - if (this.props.Document._useClusters) { + if (this.props.Document._freeform_useClusters) { this._clusterSets.forEach(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1)); - const preferredInd = NumCast(doc.cluster); - doc.cluster = -1; + const preferredInd = NumCast(doc.layout_cluster); + doc.layout_cluster = -1; this._clusterSets.forEach((set, i) => set.forEach(member => { - if (doc.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { - doc.cluster = i; + if (doc.layout_cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { + doc.layout_cluster = i; } }) ); - if (doc.cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) { - doc.cluster = preferredInd; + if (doc.layout_cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) { + doc.layout_cluster = preferredInd; } this._clusterSets.forEach((set, i) => { - if (doc.cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { - doc.cluster = i; + if (doc.layout_cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { + doc.layout_cluster = i; } }); - if (doc.cluster === -1) { - doc.cluster = this._clusterSets.length; + if (doc.layout_cluster === -1) { + doc.layout_cluster = this._clusterSets.length; this._clusterSets.push([doc]); } else if (this._clusterSets.length) { - for (let i = this._clusterSets.length; i <= doc.cluster; i++) !this._clusterSets[i] && this._clusterSets.push([]); - this._clusterSets[doc.cluster ?? 0].push(doc); + for (let i = this._clusterSets.length; i <= doc.layout_cluster; i++) !this._clusterSets[i] && this._clusterSets.push([]); + this._clusterSets[doc.layout_cluster ?? 0].push(doc); } } } @@ -566,8 +571,8 @@ export class CollectionFreeFormView extends CollectionSubView doc && this.updateCluster(doc)); } else { @@ -591,7 +596,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (this._hitCluster !== -1) { !addToSel && SelectionManager.DeselectAll(); - const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._useClusters ? NumCast(cd.cluster) : NumCast(cd.group, -1)) === this._hitCluster); + const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === this._hitCluster); this.selectDocuments(eles); return true; } @@ -678,7 +683,6 @@ export class CollectionFreeFormView extends CollectionSubView { if (!this._deleteList.includes(intersect.inkView)) { this._deleteList.push(intersect.inkView); - SetActiveInkWidth(StrCast(intersect.inkView.rootDoc.strokeWidth?.toString()) || '1'); + SetActiveInkWidth(StrCast(intersect.inkView.rootDoc.stroke_width?.toString()) || '1'); SetActiveInkColor(StrCast(intersect.inkView.rootDoc.color?.toString()) || 'black'); // create a new curve by appending all curves of the current segment together in order to render a single new stroke. if (!e.shiftKey) { @@ -1021,19 +1025,19 @@ export class CollectionFreeFormView extends CollectionSubView 20) { deltaScale = 20 / invTransform.Scale; } - if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._viewScaleMin, 1) && this.isAnnotationOverlay) { + if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._freeform_scaleMin, 1) && this.isAnnotationOverlay) { this.setPan(0, 0); return; } - if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._viewScaleMin, 1) && this.isAnnotationOverlay) { - deltaScale = NumCast(this.rootDoc._viewScaleMin, 1) / invTransform.Scale; + if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._freeform_scaleMin, 1) && this.isAnnotationOverlay) { + deltaScale = NumCast(this.rootDoc._freeform_scaleMin, 1) / invTransform.Scale; } const localTransform = invTransform.scaleAbout(deltaScale, x, y); if (localTransform.Scale >= 0.05 || localTransform.Scale > this.zoomScaling()) { const safeScale = Math.min(Math.max(0.05, localTransform.Scale), 20); this.props.Document[this.scaleFieldKey] = Math.abs(safeScale); - this.setPan(-localTransform.TranslateX / safeScale, (this.props.originTopLeft ? undefined : NumCast(this.props.Document.scrollTop) * safeScale) || -localTransform.TranslateY / safeScale); + this.setPan(-localTransform.TranslateX / safeScale, (this.props.originTopLeft ? undefined : NumCast(this.props.Document.layout_scrollTop) * safeScale) || -localTransform.TranslateY / safeScale); } }; @@ -1113,26 +1117,26 @@ export class CollectionFreeFormView extends CollectionSubView (this.rootDoc.scrollTop = relTop * maxScrollTop), 10); + setTimeout(() => (this.rootDoc.layout_scrollTop = relTop * maxScrollTop), 10); newPanY = minPanY; } !this.Document._verticalScroll && (this.Document[this.panXFieldKey] = this.isAnnotationOverlay ? newPanX : panX); @@ -1143,7 +1147,7 @@ export class CollectionFreeFormView extends CollectionSubView { const collectionDoc = this.props.docViewPath().lastElement().rootDoc; - if (collectionDoc?._viewType !== CollectionViewType.Freeform || collectionDoc._panX !== undefined) { + if (collectionDoc?._viewType !== CollectionViewType.Freeform || collectionDoc._freeform_ !== undefined) { this.setPan( NumCast(this.layoutDoc[this.panXFieldKey]) + ((this.props.PanelWidth() / 2) * x) / this.zoomScaling(), // nudge x,y as a function of panel dimension and scale NumCast(this.layoutDoc[this.panYFieldKey]) + ((this.props.PanelHeight() / 2) * -y) / this.zoomScaling(), @@ -1162,7 +1166,7 @@ export class CollectionFreeFormView extends CollectionSubView NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); let zfirst = docs.length ? NumCast(docs[0].zIndex) : 0; doc.zIndex = zfirst - 1; - } else if (doc.isInkMask) { + } else if (doc.stroke_isInkMask) { doc.zIndex = 5000; } else { const docs = this.childLayoutPairs.map(pair => pair.layout).slice(); @@ -1222,8 +1226,8 @@ export class CollectionFreeFormView extends CollectionSubView { const docView = fieldProps.DocumentView?.(); - if (docView && (e.metaKey || e.ctrlKey || e.altKey || docView.rootDoc._singleLine) && ['Tab', 'Enter'].includes(e.key)) { + if (docView && (e.metaKey || e.ctrlKey || e.altKey || docView.rootDoc._createDocOnCR) && ['Tab', 'Enter'].includes(e.key)) { e.stopPropagation?.(); const below = !e.altKey && e.key !== 'Tab'; - const layoutKey = StrCast(docView.LayoutFieldKey); + const layout_fieldKey = StrCast(docView.LayoutFieldKey); const newDoc = Doc.MakeCopy(docView.rootDoc, true); const dataField = docView.rootDoc[Doc.LayoutFieldKey(newDoc)]; newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List([]) : undefined; if (below) newDoc.y = NumCast(docView.rootDoc.y) + NumCast(docView.rootDoc._height) + 10; else newDoc.x = NumCast(docView.rootDoc.x) + NumCast(docView.rootDoc._width) + 10; - if (layoutKey !== 'layout' && docView.rootDoc[layoutKey] instanceof Doc) { - newDoc[layoutKey] = docView.rootDoc[layoutKey]; + if (layout_fieldKey !== 'layout' && docView.rootDoc[layout_fieldKey] instanceof Doc) { + newDoc[layout_fieldKey] = docView.rootDoc[layout_fieldKey]; } Doc.GetProto(newDoc).text = undefined; FormattedTextBox.SelectOnLoad = newDoc[Id]; @@ -1315,7 +1319,7 @@ export class CollectionFreeFormView extends CollectionSubView { @@ -1521,7 +1525,7 @@ export class CollectionFreeFormView extends CollectionSubView([anchor]); + this.dataDoc[this.props.fieldKey + '_annotations'] = new List([anchor]); } } return anchor; @@ -1644,8 +1648,8 @@ export class CollectionFreeFormView extends CollectionSubView { this.dataDoc.icon = new ImageField(iconFile); - this.dataDoc['icon-nativeWidth'] = nativeWidth; - this.dataDoc['icon-nativeHeight'] = nativeHeight; + this.dataDoc['icon_nativeWidth'] = nativeWidth; + this.dataDoc['icon_nativeHeight'] = nativeHeight; } ); @@ -1762,7 +1766,7 @@ export class CollectionFreeFormView extends CollectionSubView (Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards), icon: 'eye' }); appearanceItems.push({ description: `${this.fitContentsToBox ? 'Make Zoomable' : 'Scale to Window'}`, - event: () => (this.Document._fitContentsToBox = !this.fitContentsToBox), + event: () => (this.Document._freeform_fitContentsToBox = !this.fitContentsToBox), icon: !this.fitContentsToBox ? 'expand-arrows-alt' : 'compress-arrows-alt', }); appearanceItems.push({ description: `Pin View`, event: () => TabDocView.PinDoc(this.rootDoc, { pinViewport: MarqueeView.CurViewBounds(this.rootDoc, this.props.PanelWidth(), this.props.PanelHeight()) }), icon: 'map-pin' }); @@ -1781,7 +1785,7 @@ export class CollectionFreeFormView extends CollectionSubView SnappingManager.SetShowSnapLines(!SnappingManager.GetShowSnapLines()), icon: 'compress-arrows-alt' }) : null; - !Doc.noviceMode ? viewCtrlItems.push({ description: (this.Document._useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this.updateClusters(!this.Document._useClusters), icon: 'braille' }) : null; + !Doc.noviceMode ? viewCtrlItems.push({ description: (this.Document._freeform_useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this.updateClusters(!this.Document._freeform_useClusters), icon: 'braille' }) : null; !viewctrls && ContextMenu.Instance.addItem({ description: 'UI Controls...', subitems: viewCtrlItems, icon: 'eye' }); const options = ContextMenu.Instance.findByDescription('Options...'); @@ -1897,7 +1901,7 @@ export class CollectionFreeFormView extends CollectionSubView - {this.layoutDoc._backgroundGridShow ? ( + {this.layoutDoc._freeform_backgroundGrid ? (
this.nativeDimScaling; @@ -2310,7 +2314,7 @@ ScriptingGlobals.add(function sendToBack(doc: Doc) { }); ScriptingGlobals.add(function resetView() { SelectionManager.Docs().forEach(doc => { - doc._panX = doc._panY = 0; - doc._viewScale = 1; + doc._freeform_panX = doc._freeform_panY = 0; + doc._freeform_scale = 1; }); }); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 11d466b0f..fdff13b54 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -52,8 +52,8 @@ export interface MarqueeViewBounds { @observer export class MarqueeView extends React.Component { public static CurViewBounds(pinDoc: Doc, panelWidth: number, panelHeight: number) { - const ps = NumCast(pinDoc._viewScale, 1); - return { left: NumCast(pinDoc._panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps }; + const ps = NumCast(pinDoc._freeform_scale, 1); + return { left: NumCast(pinDoc._freeform_panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._freeform_panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps }; } private _commandExecuted = false; @@ -110,7 +110,7 @@ export class MarqueeView extends React.Component this.props.addDocTab(Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 400, x, y, _height: 512, _nativeWidth: 850, title: 'bing', useCors: true }), OpenWhere.addRight)); + cm.setDefaultItem('?', (str: string) => this.props.addDocTab(Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 400, x, y, _height: 512, _nativeWidth: 850, title: 'bing', data_useCors: true }), OpenWhere.addRight)); cm.displayMenu(this._downX, this._downY, undefined, true); e.stopPropagation(); @@ -196,7 +196,7 @@ export class MarqueeView extends React.Component 1) { @@ -204,7 +204,7 @@ export class MarqueeView extends React.Component (docDataProto[columns[i]] = values.length > i ? (values[i].indexOf(Number(values[i]).toString()) !== -1 ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { docDataProto._group = groupAttr; @@ -379,10 +379,10 @@ export class MarqueeView extends React.Component(selected); Doc.GetProto(doc).title = makeGroup ? 'grouping' : 'nested freeform'; !this.props.isAnnotationOverlay && Doc.AddFileOrphan(Doc.GetProto(doc)); - doc._panX = doc._panY = 0; + doc._freeform_panX = doc._freeform_panY = 0; return doc; })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true)); - newCollection.system = undefined; + newCollection.isSystem = undefined; newCollection._width = this.Bounds.width; newCollection._height = this.Bounds.height; newCollection._isGroup = makeGroup; @@ -390,8 +390,8 @@ export class MarqueeView extends React.Component (d.context = newCollection)); + newCollection.layout_fitWidth = true; + selected.forEach(d => (d.embedContainer = newCollection)); this.hideMarquee(); return newCollection; }); @@ -516,9 +516,19 @@ export class MarqueeView extends React.Component Doc.AreProtosEqual(DocCast(doc.context), this.rootDoc)); + return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.rootDoc)); } @computed get documentKeys() { @@ -87,7 +87,7 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get previewWidth() { - return NumCast(this.layoutDoc.schemaPreviewWidth); + return NumCast(this.layoutDoc.schema_previewWidth); } @computed get tableWidth() { @@ -95,12 +95,12 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get columnKeys() { - return Cast(this.layoutDoc.columnKeys, listSpec('string'), defaultColumnKeys); + return Cast(this.layoutDoc.schema_columnKeys, listSpec('string'), defaultColumnKeys); } @computed get storedColumnWidths() { const widths = NumListCast( - this.layoutDoc.columnWidths, + this.layoutDoc.schema_columnWidths, this.columnKeys.map(() => (this.tableWidth - CollectionSchemaView._rowMenuWidth) / this.columnKeys.length) ); @@ -243,7 +243,7 @@ export class CollectionSchemaView extends CollectionSubView() { let currKeys = [...this.columnKeys]; currKeys[index] = newKey; - this.layoutDoc.columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); }; @undoBatch @@ -257,11 +257,11 @@ export class CollectionSchemaView extends CollectionSubView() { const currWidths = this.storedColumnWidths.slice(); currWidths.splice(0, 0, newColWidth); const newDesiredTableWidth = currWidths.reduce((w, cw) => w + cw, 0); - this.layoutDoc.columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); + this.layoutDoc.schema_columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); let currKeys = this.columnKeys.slice(); currKeys.splice(0, 0, key); - this.layoutDoc.columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); }; @action @@ -274,11 +274,11 @@ export class CollectionSchemaView extends CollectionSubView() { const currWidths = this.storedColumnWidths.slice(); currWidths.splice(index, 1); const newDesiredTableWidth = currWidths.reduce((w, cw) => w + cw, 0); - this.layoutDoc.columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); + this.layoutDoc.schema_columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); let currKeys = this.columnKeys.slice(); currKeys.splice(index, 1); - this.layoutDoc.columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); }; @action @@ -317,7 +317,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action finishResize = () => { - this.layoutDoc.columnWidths = new List(this._displayColumnWidths); + this.layoutDoc.schema_columnWidths = new List(this._displayColumnWidths); this._displayColumnWidths = undefined; }; @@ -326,11 +326,11 @@ export class CollectionSchemaView extends CollectionSubView() { moveColumn = (fromIndex: number, toIndex: number) => { let currKeys = this.columnKeys.slice(); currKeys.splice(toIndex, 0, currKeys.splice(fromIndex, 1)[0]); - this.layoutDoc.columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); let currWidths = this.storedColumnWidths.slice(); currWidths.splice(toIndex, 0, currWidths.splice(fromIndex, 1)[0]); - this.layoutDoc.columnWidths = new List(currWidths); + this.layoutDoc.schema_columnWidths = new List(currWidths); }; @action @@ -480,14 +480,14 @@ export class CollectionSchemaView extends CollectionSubView() { const maxWidth = 1000; const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth; - this.layoutDoc.schemaPreviewWidth = width; + this.layoutDoc.schema_previewWidth = width; return false; }; @action addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { if (!value && !forceEmptyNote) return false; - const newDoc = Docs.Create.TextDocument(value, { title: value, _autoHeight: true }); + const newDoc = Docs.Create.TextDocument(value, { title: value, _layout_autoHeight: true }); FormattedTextBox.SelectOnLoad = newDoc[Id]; FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' '; return this.addRow(newDoc) || false; @@ -500,7 +500,7 @@ export class CollectionSchemaView extends CollectionSubView() { ContextMenu.Instance.setDefaultItem('::', (name: string): void => { Doc.GetProto(this.props.Document)[name] = ''; - this.addRow(Docs.Create.TextDocument('', { title: name, _autoHeight: true })); + this.addRow(Docs.Create.TextDocument('', { title: name, _layout_autoHeight: true })); }); ContextMenu.Instance.displayMenu(x, y, undefined, true); }; @@ -837,7 +837,7 @@ export class CollectionSchemaView extends CollectionSubView() { }); return { docs }; } - rowHeightFunc = () => (BoolCast(this.layoutDoc._singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); + rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); sortedDocsFunc = () => this.sortedDocs; isContentActive = () => this.props.isSelected() || this.props.isContentActive(); screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0); @@ -968,7 +968,7 @@ class CollectionSchemaViewDocs extends React.Component diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 34631e0b7..45bfe4f77 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -59,7 +59,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { onPointerMove = (e: any) => { if (!SnappingManager.GetIsDragging()) return; - const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.context === this.schemaDoc); // this.schemaView?._selectedDocs.has(doc) ?? false; + const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.embedContainer === this.schemaDoc); // this.schemaView?._selectedDocs.has(doc) ?? false; if (this._ref && dragIsRow) { const rect = this._ref.getBoundingClientRect(); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 9f659752a..42bf32475 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -73,7 +73,7 @@ export class SchemaTableCell extends React.Component { isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, - dropAction: 'alias' as dropActionType, + dropAction: 'embed', bringToFront: emptyFunction, renderDepth: 1, isContentActive: returnFalse, @@ -83,7 +83,7 @@ export class SchemaTableCell extends React.Component { addDocTab: SchemaTableCell.addFieldDoc, pinToPres: returnZero, Document, - fieldKey, + fieldKey: fieldKey, PanelWidth: columnWidth, PanelHeight: props.rowHeight, }; diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index d02a1c4eb..b9d56541a 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -24,12 +24,12 @@ export class LinkMenuGroup extends React.Component { private _menuRef = React.createRef(); getBackgroundColor = (): string => { - const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList); + const link_relationshipList = StrListCast(Doc.UserDoc().link_relationshipList); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); let color = 'white'; // if this link's relationship property is not default "link", set its color - if (linkRelationshipList) { - const relationshipIndex = linkRelationshipList.indexOf(this.props.groupType); + if (link_relationshipList) { + const relationshipIndex = link_relationshipList.indexOf(this.props.groupType); const RGBcolor: string = linkColorList[relationshipIndex]; if (RGBcolor) { //set opacity to 0.25 by modifiying the rgb string @@ -47,17 +47,18 @@ export class LinkMenuGroup extends React.Component { const sourceDoc = this.props.docView.anchorViewDoc ?? (this.props.docView.rootDoc.type === DocumentType.LINK // - ? this.props.docView.props.LayoutTemplateString?.includes('anchor1') - ? DocCast(linkDoc.anchor1) - : DocCast(linkDoc.anchor2) + ? this.props.docView.props.LayoutTemplateString?.includes('link_anchor_1') + ? DocCast(linkDoc.link_anchor_1) + : DocCast(linkDoc.link_anchor_2) : this.props.sourceDoc); const destDoc = !sourceDoc ? undefined : this.props.docView.rootDoc.type === DocumentType.LINK - ? this.props.docView.props.LayoutTemplateString?.includes('anchor1') - ? DocCast(linkDoc.anchor2) - : DocCast(linkDoc.anchor1) - : LinkManager.getOppositeAnchor(linkDoc, sourceDoc) || LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, null).annotationOn === sourceDoc ? Cast(linkDoc.anchor2, Doc, null) : Cast(linkDoc.anchor1, Doc, null)); + ? this.props.docView.props.LayoutTemplateString?.includes('link_anchor_1') + ? DocCast(linkDoc.link_anchor_2) + : DocCast(linkDoc.link_anchor_1) + : LinkManager.getOppositeAnchor(linkDoc, sourceDoc) || + LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.link_anchor_2, Doc, null).annotationOn === sourceDoc ? Cast(linkDoc.link_anchor_2, Doc, null) : Cast(linkDoc.link_anchor_1, Doc, null)); return !destDoc || !sourceDoc ? null : ( void; } -// drag links and drop link targets (aliasing them if needed) +// drag links and drop link targets (embedding them if needed) export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: DocumentView, downX: number, downY: number, sourceDoc: Doc, specificLinks?: Doc[]) { const draggedDocs = (specificLinks ? specificLinks : LinkManager.Links(sourceDoc)).map(link => LinkManager.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[]; @@ -45,7 +43,7 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume const dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); dragData.canEmbed = true; - dragData.dropAction = 'alias'; + dragData.dropAction = 'embed'; DragManager.StartDocumentDrag([dragEle], dragData, downX, downY, undefined); } @@ -65,9 +63,9 @@ export class LinkMenuItem extends React.Component { @computed get sourceAnchor() { const ldoc = this.props.linkDoc; - if (this.props.sourceDoc !== ldoc.anchor1 && this.props.sourceDoc !== ldoc.anchor2) { - if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.anchor1).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.anchor1); - if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.anchor2).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.anchor2); + if (this.props.sourceDoc !== ldoc.link_anchor_1 && this.props.sourceDoc !== ldoc.link_anchor_2) { + if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_1).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.link_anchor_1); + if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_2).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.link_anchor_2); } return this.props.sourceDoc; } @@ -79,7 +77,7 @@ export class LinkMenuItem extends React.Component { this, e, e => { - const dragData = new DragManager.DocumentDragData([this.props.linkDoc], 'alias'); + const dragData = new DragManager.DocumentDragData([this.props.linkDoc], 'embed'); dragData.removeDropProperties = ['hidden']; DragManager.StartDocumentDrag([this._editRef.current!], dragData, e.x, e.y); return true; @@ -89,7 +87,7 @@ export class LinkMenuItem extends React.Component { const trail = DocCast(this.props.docView.rootDoc.presTrail); if (trail) { Doc.ActivePresentation = trail; - MainView.addDocTabFunc(trail, OpenWhere.replaceRight); + DocumentViewInternal.addDocTabFunc(trail, OpenWhere.replaceRight); } else { SelectionManager.SelectView(this.props.docView, false); if ((SettingsManager.propertiesWidth ?? 0) < 100) { @@ -118,10 +116,10 @@ export class LinkMenuItem extends React.Component { this.props.itemHandler?.(this.props.linkDoc); } else { const focusDoc = - Cast(this.props.linkDoc.anchor1, Doc, null)?.annotationOn === this.props.sourceDoc - ? Cast(this.props.linkDoc.anchor1, Doc, null) - : Cast(this.props.linkDoc.anchor2, Doc, null)?.annotationOn === this.props.sourceDoc - ? Cast(this.props.linkDoc.anchor12, Doc, null) + Cast(this.props.linkDoc.link_anchor_1, Doc, null)?.annotationOn === this.props.sourceDoc + ? Cast(this.props.linkDoc.link_anchor_1, Doc, null) + : Cast(this.props.linkDoc.link_anchor_2, Doc, null)?.annotationOn === this.props.sourceDoc + ? Cast(this.props.linkDoc.link_anchor_12, Doc, null) : undefined; if (focusDoc) this.props.docView.props.focus(focusDoc, { instant: true }); @@ -149,7 +147,7 @@ export class LinkMenuItem extends React.Component { return (
-
+
{ {this.props.linkDoc.linksToAnnotation && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? 'Annotation in' : ''} {StrCast(title)}

- {!this.props.linkDoc.description ? null :

{StrCast(this.props.linkDoc.description)}

} + {!this.props.linkDoc.link_description ? null :

{StrCast(this.props.linkDoc.link_description)}

}
diff --git a/src/client/views/linking/LinkRelationshipSearch.tsx b/src/client/views/linking/LinkRelationshipSearch.tsx index 53da880e4..9662b2fea 100644 --- a/src/client/views/linking/LinkRelationshipSearch.tsx +++ b/src/client/views/linking/LinkRelationshipSearch.tsx @@ -1,8 +1,8 @@ -import { observer } from "mobx-react"; +import { observer } from 'mobx-react'; import './LinkEditor.scss'; -import React = require("react"); +import React = require('react'); -interface LinkRelationshipSearchProps { +interface link_relationshipSearchProps { results: string[] | undefined; display: string; //callback fn to set rel + hide dropdown upon setting @@ -10,48 +10,48 @@ interface LinkRelationshipSearchProps { toggleSearch: () => void; } @observer -export class LinkRelationshipSearch extends React.Component { - +export class link_relationshipSearch extends React.Component { handleResultClick = (e: React.MouseEvent) => { const relationship = (e.target as HTMLParagraphElement).textContent; if (relationship) { this.props.handleRelationshipSearchChange(relationship); } - } + }; handleMouseEnter = () => { this.props.toggleSearch(); - } + }; handleMouseLeave = () => { this.props.toggleSearch(); - } + }; /** - * Render an empty div to increase the height of LinkEditor to accommodate 2+ results - */ + * Render an empty div to increase the height of LinkEditor to accommodate 2+ results + */ emptyDiv = () => { - if (this.props.results && this.props.results.length > 2 && this.props.display === "block") { - return
; + if (this.props.results && this.props.results.length > 2 && this.props.display === 'block') { + return
; } - } + }; render() { return (
-
- { // return a dropdown of relationship results if there exist results - this.props.results - ? this.props.results.map(result => { - return

- {result} -

; +
+ { + // return a dropdown of relationship results if there exist results + this.props.results ? ( + this.props.results.map(result => { + return ( +

+ {result} +

+ ); }) - :

No matching relationships

+ ) : ( +

No matching relationships

+ ) }
@@ -60,4 +60,4 @@ export class LinkRelationshipSearch extends React.Component ); } -} \ No newline at end of file +} diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 68fb19208..8e83cf121 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -76,7 +76,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent this.getLinkData(l)) .forEach(({ la1, la2, linkTime }) => { - if (linkTime > NumCast(this.layoutDoc._currentTimecode) && linkTime < this._ele!.currentTime) { + if (linkTime > NumCast(this.layoutDoc._layout_currentTimecode) && linkTime < this._ele!.currentTime) { Doc.linkFollowHighlight(la1); } }); - this.layoutDoc._currentTimecode = this._ele.currentTime; - this.timeline?.scrollToTime(NumCast(this.layoutDoc._currentTimecode)); + this.layoutDoc._layout_currentTimecode = this._ele.currentTime; + this.timeline?.scrollToTime(NumCast(this.layoutDoc._layout_currentTimecode)); } }; @@ -221,7 +221,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent l.anchor1 === link || l.anchor2 === link) + .filter(l => l.link_anchor_1 === link || l.link_anchor_2 === link) .forEach(l => { const { la1, la2 } = this.getLinkData(l); const startTime = this.timeline?.anchorStart(la1) || this.timeline?.anchorStart(la2); @@ -435,7 +435,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent this.props.ScreenToLocalTransform().translate(0, -AudioBox.topControlsHeight); - setPlayheadTime = (time: number) => (this._ele!.currentTime = this.layoutDoc._currentTimecode = time); + setPlayheadTime = (time: number) => (this._ele!.currentTime = this.layoutDoc._layout_currentTimecode = time); playing = () => this.mediaState === media_state.Playing; @@ -547,7 +547,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent
-
{formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode)))}
+
{formatTime(Math.round(NumCast(this.layoutDoc._layout_currentTimecode)))}
) : (
@@ -623,7 +623,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent -
{this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this.timeline.clipStart)))}
+
{this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._layout_currentTimecode) - NumCast(this.timeline.clipStart)))}
{this.miniPlayer ? (
/
) : ( @@ -656,6 +656,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent (this._stackedTimeline = r))} {...this.props} CollectionFreeFormDocumentView={undefined} + dataFieldKey={this.fieldKey} fieldKey={this.annotationKey} dictationKey={this.fieldKey + '-dictation'} mediaPath={this.path} @@ -689,7 +690,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent this._ele?.duration && this._ele?.duration !== Infinity && (this.dataDoc[this.fieldKey + '-duration'] = this._ele.duration))}> + onLoadedData={action(e => this._ele?.duration && this._ele?.duration !== Infinity && (this.dataDoc[this.fieldKey + '_duration'] = this._ele.duration))}> Not supported. diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 862d0da8c..6710cee63 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -36,13 +36,13 @@ export class CollectionFreeFormDocumentView extends DocComponent (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames @@ -154,8 +154,8 @@ export class CollectionFreeFormDocumentView extends DocComponent (doc[val] = ComputedField.MakeInterpolatedString(val, 'activeFrame', doc, currTimecode))); CollectionFreeFormDocumentView.animDataFields(doc).forEach(val => (doc[val] = ComputedField.MakeInterpolatedDataField(val, 'activeFrame', doc, currTimecode))); const targetDoc = doc; // data fields, like rtf 'text' exist on the data doc, so - //doc !== targetDoc && (targetDoc.context = doc.context); // the computed fields don't see the layout doc -- need to copy the context to the data doc (HACK!!!) and set the activeFrame on the data doc (HACK!!!) - targetDoc.activeFrame = ComputedField.MakeFunction('self.context?._currentFrame||0'); + //doc !== targetDoc && (targetDoc.embedContainer = doc.embedContainer); // the computed fields don't see the layout doc -- need to copy the embedContainer to the data doc (HACK!!!) and set the activeFrame on the data doc (HACK!!!) + targetDoc.activeFrame = ComputedField.MakeFunction('self.embedContainer?._currentFrame||0'); targetDoc.dataTransition = 'inherit'; }); } @@ -202,7 +202,7 @@ export class CollectionFreeFormDocumentView extends DocComponent() { } render() { - const scaling = Math.min(this.layoutDoc.fitWidth ? 10000 : this.props.PanelHeight() / this.rootDoc[HeightSym](), this.props.PanelWidth() / this.rootDoc[WidthSym]()); + const scaling = Math.min(this.layoutDoc.layout_fitWidth ? 10000 : this.props.PanelHeight() / this.rootDoc[HeightSym](), this.props.PanelWidth() / this.rootDoc[WidthSym]()); return (
() { SetActiveInkWidth(e.target.value); SelectionManager.Views() .filter(i => StrCast(i.rootDoc.type) === DocumentType.INK) - .map(i => (i.rootDoc.strokeWidth = Number(e.target.value))); + .map(i => (i.rootDoc.stroke_width = Number(e.target.value))); }} />
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index ace388c57..3be2d9a77 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Opt } from '../../../fields/Doc'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; @@ -26,6 +26,13 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { // on click, animate slider movement to the targetWidth this._animating = 'all 200ms'; - this.layoutDoc._clipWidth = (targetWidth * 100) / this.props.PanelWidth(); + this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this.props.PanelWidth(); setTimeout( action(() => (this._animating = '')), 200 @@ -71,9 +78,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { - const width = movementX * this.props.ScreenToLocalTransform().Scale + (NumCast(this.layoutDoc._clipWidth) / 100) * this.props.PanelWidth(); + const width = movementX * this.props.ScreenToLocalTransform().Scale + (this.clipWidth / 100) * this.props.PanelWidth(); if (width && width > 5 && width < this.props.PanelWidth()) { - this.layoutDoc._clipWidth = (width * 100) / this.props.PanelWidth(); + this.layoutDoc[this.clipWidthKey] = (width * 100) / this.props.PanelWidth(); } return false; }; @@ -101,7 +108,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { return (
{ return ( -
this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}> +
this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}> {displayDoc(which)}
); @@ -151,16 +157,16 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent - {displayBox(this.fieldKey === 'data' ? 'compareBox-after' : `${this.fieldKey}2`, 1, this.props.PanelWidth() - 3)} -
- {displayBox(this.fieldKey === 'data' ? 'compareBox-before' : `${this.fieldKey}1`, 0, 0)} + {displayBox(`${this.fieldKey}_2`, 1, this.props.PanelWidth() - 3)} +
+ {displayBox(`${this.fieldKey}_1`, 0, 0)}
(this.props.PanelWidth() - 5) / this.props.PanelWidth() ? 'w-resize' : undefined, + left: `calc(${this.clipWidth + '%'} - 0.5px)`, + cursor: this.clipWidth < 5 ? 'e-resize' : this.clipWidth / 100 > (this.props.PanelWidth() - 5) / this.props.PanelWidth() ? 'w-resize' : undefined, }} onPointerDown={e => this.registerSliding(e, this.props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */ > diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index eb25d3264..5876efb01 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, StrListCast } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; -import { Cast, NumCast, StrCast } from '../../../../fields/Types'; +import { Cast, CsvCast, NumCast, StrCast } from '../../../../fields/Types'; import { CsvField } from '../../../../fields/URLField'; import { Docs } from '../../../documents/Documents'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; @@ -29,7 +29,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { // @observable private pairs: { [key: string]: FieldResult }[] = []; static pairSet = new ObservableMap(); @computed.struct get pairs() { - return DataVizBox.pairSet.get(StrCast(this.rootDoc.fileUpload)); + return DataVizBox.pairSet.get(CsvCast(this.rootDoc[this.fieldKey]).url.href); } private _chartRenderer: LineChart | undefined; // // another way would be store a schema that defines the type of data we are expecting from an imported doc @@ -61,7 +61,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @action restoreView = (data: Doc) => { const changedView = this.dataVizView !== data.presDataVizView && (this.layoutDoc._dataVizView = data.presDataVizView); - const changedAxes = this.axes.join('') !== StrListCast(data.presDataVizAxes).join('') && (this.layoutDoc._dataVizAxes = new List(StrListCast(data.presDataVizAxes))); + const changedAxes = this.axes.join('') !== StrListCast(data.presDataVizAxes).join('') && (this.layoutDoc._data_vizAxes = new List(StrListCast(data.presDataVizAxes))); const func = () => this._chartRenderer?.restoreView(data); if (changedView || changedAxes) { setTimeout(func, 100); @@ -88,14 +88,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { }; @computed.struct get axes() { - return StrListCast(this.layoutDoc.dataVizAxes); + return StrListCast(this.layoutDoc.data_vizAxes); } - selectAxes = (axes: string[]) => (this.layoutDoc.dataVizAxes = new List(axes)); + selectAxes = (axes: string[]) => (this.layoutDoc.data_vizAxes = new List(axes)); @computed get selectView() { const width = this.props.PanelWidth() * 0.9; const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9; - const margin = { top: 10, right: 25, bottom: 50, left:25}; + const margin = { top: 10, right: 25, bottom: 50, left: 25 }; if (!this.pairs) return 'no data'; // prettier-ignore switch (this.dataVizView) { @@ -113,10 +113,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } fetchData() { - if (DataVizBox.pairSet.has(StrCast(this.rootDoc.fileUpload))) return; - DataVizBox.pairSet.set(StrCast(this.rootDoc.fileUpload), []); + if (DataVizBox.pairSet.has(CsvCast(this.rootDoc[this.fieldKey]).url.href)) return; + DataVizBox.pairSet.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, []); fetch('/csvData?uri=' + this.dataUrl?.url.href) // - .then(res => res.json().then(action(res => !res.errno && DataVizBox.pairSet.set(StrCast(this.rootDoc.fileUpload), res)))); + .then(res => res.json().then(action(res => !res.errno && DataVizBox.pairSet.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, res)))); } // handle changing the view using a button diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 777bf2f66..11f62a61f 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -56,8 +56,8 @@ export class LineChart extends React.Component { } @computed get incomingLinks() { return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links - .filter(link => link.anchor1 !== this.props.rootDoc) // get links where this chart doc is the target of the link - .map(link => DocCast(link.anchor1)); // then return the source of the link + .filter(link => link.link_anchor_1 !== this.props.rootDoc) // get links where this chart doc is the target of the link + .map(link => DocCast(link.link_anchor_1)); // then return the source of the link } @computed get incomingSelected() { return this.incomingLinks // all links that are pointing to this node @@ -87,7 +87,7 @@ export class LineChart extends React.Component { { fireImmediately: true } ); this._disposers.annos = reaction( - () => DocListCast(this.props.dataDoc[this.props.fieldKey + '-annotations']), + () => DocListCast(this.props.dataDoc[this.props.fieldKey + '_annotations']), annotations => { // modify how d3 renders so that anything in this annotations list would be potentially highlighted in some way // could be blue colored to make it look like anchor @@ -123,7 +123,7 @@ export class LineChart extends React.Component { element.classList.remove('selected'); } }; - // gets called whenever the "data-annotations" fields gets updated + // gets called whenever the "data_annotations" fields gets updated drawAnnotations = (dataX: number, dataY: number, selected?: boolean) => { // TODO: nda - can optimize this by having some sort of mapping of the x and y values to the individual circle elements // loop through all html elements with class .circle-d1 and find the one that has "data-x" and "data-y" attributes that match the dataX and dataY @@ -228,15 +228,15 @@ export class LineChart extends React.Component { // creating the x and y scales const xScale = scaleCreatorNumerical(xMin, xMax, 0, width); - const yScale = scaleCreatorNumerical(0, yMax,height, 0); + const yScale = scaleCreatorNumerical(0, yMax, height, 0); // adding svg const margin = this.props.margin; const svg = (this._lineChartSvg = d3 .select(this._lineChartRef.current) .append('svg') - .attr('width', `${width +margin.left + margin.right}`) - .attr('height', `${height + margin.top + margin.bottom }`) + .attr('width', `${width + margin.left + margin.right}`) + .attr('height', `${height + margin.top + margin.bottom}`) .append('g') .attr('transform', `translate(${margin.left}, ${margin.top})`)); diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 0d69ac890..3816bddfa 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -47,17 +47,17 @@ export class TableBox extends React.Component { e => { const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!; const targetCreator = (annotationOn: Doc | undefined) => { - const alias = Doc.MakeAlias(this.props.docView?.()!.rootDoc!); - alias._dataVizView = DataVizView.LINECHART; - alias._dataVizAxes = new List([col, col]); - alias.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!; - return alias; + const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!); + embedding._dataVizView = DataVizView.LINECHART; + embedding._data_vizAxes = new List([col, col]); + embedding.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!; + return embedding; }; if (this.props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) { DragManager.StartAnchorAnnoDrag([header.current!], new DragManager.AnchorAnnoDragData(this.props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, { dragComplete: e => { if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) { - e.linkDocument.linkDisplay = true; + e.linkDocument.layout_linkDisplay = true; // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc; // e.annoDragData.linkSourceDoc.followLinkZoom = false; } diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 76a5ce7b3..348ef910a 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -120,15 +120,15 @@ export class DocumentContentsView extends React.Component< select: (ctrl: boolean) => void; NativeDimScaling?: () => number; setHeight?: (height: number) => void; - layoutKey: string; + layout_fieldKey: string; } > { @computed get layout(): string { TraceMobx(); if (this.props.LayoutTemplateString) return this.props.LayoutTemplateString; if (!this.layoutDoc) return '

awaiting layout

'; - if (this.props.layoutKey === 'layout_keyValue') return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString()); - const layout = Cast(this.layoutDoc[this.layoutDoc === this.props.Document && this.props.layoutKey ? this.props.layoutKey : StrCast(this.layoutDoc.layoutKey, 'layout')], 'string'); + if (this.props.layout_fieldKey === 'layout_keyValue') return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString()); + const layout = Cast(this.layoutDoc[this.layoutDoc === this.props.Document && this.props.layout_fieldKey ? this.props.layout_fieldKey : StrCast(this.layoutDoc.layout_fieldKey, 'layout')], 'string'); if (layout === undefined) return this.props.Document.data ? "" : KeyValueBox.LayoutString(); if (typeof layout === 'string') return layout; return '

Loading layout

'; @@ -140,12 +140,12 @@ export class DocumentContentsView extends React.Component< } get layoutDoc() { // bcz: replaced this with below : is it correct? change was made to accommodate passing fieldKey's from a layout script - // const template: Doc = this.props.LayoutTemplate?.() || Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined); + // const template: Doc = this.props.LayoutTemplate?.() || Doc.Layout(this.props.Document, this.props.layout_fieldKey ? Cast(this.props.Document[this.props.layout_fieldKey], Doc, null) : undefined); const template: Doc = this.props.LayoutTemplate?.() || (this.props.LayoutTemplateString && this.props.Document) || - (this.props.layoutKey && StrCast(this.props.Document[this.props.layoutKey]) && this.props.Document) || - Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined); + (this.props.layout_fieldKey && StrCast(this.props.Document[this.props.layout_fieldKey]) && this.props.Document) || + Doc.Layout(this.props.Document, this.props.layout_fieldKey ? Cast(this.props.Document[this.props.layout_fieldKey], Doc, null) : undefined); return Doc.expandTemplateLayout(template, this.props.Document); } diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 47705d53d..d5ca30957 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -52,7 +52,7 @@ export class DocumentLinksButton extends React.Component { if (this.props.View && dropEv.linkDocument) { // dropEv.linkDocument equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop - !dropEv.linkDocument.linkRelationship && (Doc.GetProto(dropEv.linkDocument).linkRelationship = 'hyperlink'); + !dropEv.linkDocument.link_relationship && (Doc.GetProto(dropEv.linkDocument).link_relationship = 'hyperlink'); } linkDrag?.end(); }, @@ -142,7 +142,7 @@ export class DocumentLinksButton extends React.Component(this.props.View.allLinks)).forEach(link => { - if (DocUtils.FilterDocs([link], filters, []).length || DocUtils.FilterDocs([link.anchor2 as Doc], filters, []).length || DocUtils.FilterDocs([link.anchor1 as Doc], filters, []).length) { + if (DocUtils.FilterDocs([link], filters, []).length || DocUtils.FilterDocs([link.link_anchor_2 as Doc], filters, []).length || DocUtils.FilterDocs([link.link_anchor_1 as Doc], filters, []).length) { results.push(link); } }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index ffbde18ca..d8494e58e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -131,7 +131,7 @@ export interface DocComponentView { setData?: (data: Field | Promise) => boolean; componentUI?: (boundsLeft: number, boundsTop: number) => JSX.Element | null; incrementalRendering?: () => void; - fitWidth?: () => boolean; // whether the component always fits width (eg, KeyValueBox) + layout_fitWidth?: () => boolean; // whether the component always fits width (eg, KeyValueBox) overridePointerEvents?: () => 'all' | 'none' | undefined; // if the conmponent overrides the pointer events for the document fieldKey?: string; annotationKey?: string; @@ -150,7 +150,7 @@ export interface DocumentViewSharedProps { Document: Doc; DataDoc?: Doc; contentBounds?: () => undefined | { x: number; y: number; r: number; b: number }; - fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _fitContentsToBox property on a Document + fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document suppressSetHeight?: boolean; thumbShown?: () => boolean; setContentView?: (view: DocComponentView) => any; @@ -164,11 +164,11 @@ export interface DocumentViewSharedProps { styleProvider: Opt; setTitleFocus?: () => void; focus: DocFocusFunc; - fitWidth?: (doc: Doc) => boolean | undefined; + layout_fitWidth?: (doc: Doc) => boolean | undefined; docFilters: () => string[]; docRangeFilters: () => string[]; searchFilterDocs: () => Doc[]; - showTitle?: () => string; + layout_showTitle?: () => string; whenChildContentsActiveChanged: (isActive: boolean) => void; rootSelected: (outsideReaction?: boolean) => boolean; // whether the root of a template has been selected addDocTab: (doc: Doc, where: OpenWhere) => boolean; @@ -275,8 +275,8 @@ export class DocumentViewInternal extends DocComponent; + @computed get layout_showTitle() { + return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.layout_showTitle) as Opt; } @computed get NativeDimScaling() { return this.props.NativeDimScaling?.() || 1; @@ -305,8 +305,8 @@ export class DocumentViewInternal extends DocComponent { - if (!StrCast(this.layoutDoc._showTitle)) this.layoutDoc._showTitle = 'title'; + if (!StrCast(this.layoutDoc._layout_showTitle)) this.layoutDoc._layout_showTitle = 'title'; setTimeout(() => this._titleRef.current?.setIsFocused(true)); // use timeout in case title wasn't shown to allow re-render so that titleref will be defined }; @@ -539,7 +539,7 @@ export class DocumentViewInternal extends DocComponent this.props.removeDocument?.(this.props.Document); @undoBatch setToggleDetail = () => (this.Document.onClick = ScriptField.MakeScript( - `toggleDetail(documentView, "${StrCast(this.Document.layoutKey) + `toggleDetail(documentView, "${StrCast(this.Document.layout_fieldKey) .replace('layout_', '') .replace(/^layout$/, 'detail')}")`, { documentView: 'any' } @@ -611,7 +611,7 @@ export class DocumentViewInternal extends DocComponent { - const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document && d.linkRelationship === 'portal to:portal from'); + const portalLink = this.allLinks.find(d => d.link_anchor_1 === this.props.Document && d.link_relationship === 'portal to:portal from'); if (!portalLink) { DocUtils.MakeLink( this.props.Document, - Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }), - { linkRelationship: 'portal to:portal from' } + Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _layout_fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }), + { link_relationship: 'portal to:portal from' } ); } this.Document.followLinkLocation = OpenWhere.lightbox; @@ -699,7 +699,7 @@ export class DocumentViewInternal extends DocComponent item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: item.icon as IconProp })); if (!this.props.Document.isFolder) { - const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); + const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layout_fieldKey)], Doc, null); const appearance = cm.findByDescription('UI Controls...'); const appearanceItems: ContextMenuProps[] = appearance && 'subitems' in appearance ? appearance.subitems : []; !Doc.noviceMode && templateDoc && appearanceItems.push({ description: 'Open Template ', event: () => this.props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); @@ -742,7 +742,7 @@ export class DocumentViewInternal extends DocComponent this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); + funcs.push({ description: 'Drag an Embedding', icon: 'edit', event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getEmbedding(this.dragFactory)')) }); funcs.push({ description: 'Drag a Copy', icon: 'edit', event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); funcs.push({ description: 'Drag Document', icon: 'edit', event: () => (this.layoutDoc.onDragStart = undefined) }); cm.addItem({ description: 'OnDrag...', noexpand: true, subitems: funcs, icon: 'asterisk' }); @@ -910,7 +910,7 @@ export class DocumentViewInternal extends DocComponent {this.layoutDoc.hideAllLinks ? null : this.allLinkEndpoints}
@@ -922,7 +922,7 @@ export class DocumentViewInternal extends DocComponent, props: Opt, property: string): any => { // prettier-ignore switch (property.split(':')[0]) { - case StyleProp.ShowTitle: return ''; + case StyleProp.layout_showTitle: return ''; case StyleProp.PointerEvents: return 'none'; case StyleProp.Highlighting: return undefined; } @@ -938,22 +938,22 @@ export class DocumentViewInternal extends DocComponent - Doc.AreProtosEqual(link.anchor1 as Doc, this.rootDoc) || - Doc.AreProtosEqual(link.anchor2 as Doc, this.rootDoc) || - ((link.anchor1 as Doc)?.unrendered && Doc.AreProtosEqual((link.anchor1 as Doc)?.annotationOn as Doc, this.rootDoc)) || - ((link.anchor2 as Doc)?.unrendered && Doc.AreProtosEqual((link.anchor2 as Doc)?.annotationOn as Doc, this.rootDoc)) + Doc.AreProtosEqual(link.link_anchor_1 as Doc, this.rootDoc) || + Doc.AreProtosEqual(link.link_anchor_2 as Doc, this.rootDoc) || + ((link.link_anchor_1 as Doc)?.unrendered && Doc.AreProtosEqual((link.link_anchor_1 as Doc)?.annotationOn as Doc, this.rootDoc)) || + ((link.link_anchor_2 as Doc)?.unrendered && Doc.AreProtosEqual((link.link_anchor_2 as Doc)?.annotationOn as Doc, this.rootDoc)) ); } @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); } - hideLink = computedFn((link: Doc) => () => (link.linkDisplay = false)); + hideLink = computedFn((link: Doc) => () => (link.layout_linkDisplay = false)); @computed get allLinkEndpoints() { // the small blue dots that mark the endpoints of links TraceMobx(); - if (this.props.hideLinkAnchors || this.layoutDoc.hideLinkAnchors || this.props.dontRegisterView || this.layoutDoc.unrendered) return null; - const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => d.linkDisplay); + if (this.props.hideLinkAnchors || this.layoutDoc.layout_hideLinkAnchors || this.props.dontRegisterView || this.layoutDoc.unrendered) return null; + const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => d.layout_linkDisplay); return filtered.map(link => (
)); @@ -1046,9 +1046,9 @@ export class DocumentViewInternal extends DocComponent this.props.DocumentView().props.CollectionFreeFormDocumentView?.().props.ScreenToLocalTransform().Scale || 1; - const showTitle = this.ShowTitle?.split(':')[0]; - const showTitleHover = this.ShowTitle?.includes(':hover'); - const captionView = !this.showCaption ? null : ( + const layout_showTitle = this.layout_showTitle?.split(':')[0]; + const layout_showTitleHover = this.layout_showTitle?.includes(':hover'); + const captionView = !this.layout_showCaption ? null : (
); - const targetDoc = showTitle?.startsWith('_') ? this.layoutDoc : this.rootDoc; + const targetDoc = layout_showTitle?.startsWith('_') ? this.layoutDoc : this.rootDoc; const background = StrCast( SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, - Doc.UserDoc().showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : 'rgba(0,0,0,0.4)' + Doc.UserDoc().layout_showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : 'rgba(0,0,0,0.4)' ); - const sidebarWidthPercent = +StrCast(this.layoutDoc.sidebarWidthPercent).replace('%', ''); - const titleView = !showTitle ? null : ( + const layout_sidebarWidthPercent = +StrCast(this.layoutDoc.layout_sidebarWidthPercent).replace('%', ''); + const titleView = !layout_showTitle ? null : (
field.trim()) .map(field => targetDoc[field]?.toString()) @@ -1100,27 +1100,27 @@ export class DocumentViewInternal extends DocComponent { this.props.select(false); - return showTitle.split(';').length === 1 ? showTitle + '=' + Field.toString(targetDoc[showTitle.split(';')[0]] as any as Field) : '#' + showTitle; + return layout_showTitle.split(';').length === 1 ? layout_showTitle + '=' + Field.toString(targetDoc[layout_showTitle.split(';')[0]] as any as Field) : '#' + layout_showTitle; }} SetValue={undoBatch((input: string) => { if (input?.startsWith('#')) { - if (this.props.showTitle) { - this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined; + if (this.props.layout_showTitle) { + this.rootDoc._layout_showTitle = input?.substring(1) ? input.substring(1) : undefined; } else { - Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : 'creationDate'; + Doc.UserDoc().layout_showTitle = input?.substring(1) ? input.substring(1) : 'creationDate'; } } else { - var value = input.replace(new RegExp(showTitle + '='), '') as string | number; - if (showTitle !== 'title' && Number(value).toString() === value) value = Number(value); - if (showTitle.includes('Date') || showTitle === 'author') return true; - Doc.SetInPlace(targetDoc, showTitle, value, true); + var value = input.replace(new RegExp(layout_showTitle + '='), '') as string | number; + if (layout_showTitle !== 'title' && Number(value).toString() === value) value = Number(value); + if (layout_showTitle.includes('Date') || layout_showTitle === 'author') return true; + Doc.SetInPlace(targetDoc, layout_showTitle, value, true); } return true; })} />
); - return this.props.hideTitle || (!showTitle && !this.showCaption) ? ( + return this.props.hideTitle || (!layout_showTitle && !this.layout_showCaption) ? ( this.contents ) : (
@@ -1319,11 +1319,11 @@ export class DocumentView extends React.Component { get LayoutFieldKey() { return this.docView?.LayoutFieldKey || 'layout'; } - @computed get fitWidth() { - return this.docView?._componentView?.fitWidth?.() ?? this.props.fitWidth?.(this.rootDoc) ?? this.layoutDoc?.fitWidth; + @computed get layout_fitWidth() { + return this.docView?._componentView?.layout_fitWidth?.() ?? this.props.layout_fitWidth?.(this.rootDoc) ?? this.layoutDoc?.layout_fitWidth; } @computed get anchorViewDoc() { - return this.props.LayoutTemplateString?.includes('anchor2') ? DocCast(this.rootDoc['anchor2']) : this.props.LayoutTemplateString?.includes('anchor1') ? DocCast(this.rootDoc['anchor1']) : undefined; + return this.props.LayoutTemplateString?.includes('link_anchor_2') ? DocCast(this.rootDoc['link_anchor_2']) : this.props.LayoutTemplateString?.includes('link_anchor_1') ? DocCast(this.rootDoc['link_anchor_1']) : undefined; } @computed get hideLinkButton() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton + (this.isSelected() ? ':selected' : '')); @@ -1339,13 +1339,13 @@ export class DocumentView extends React.Component { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); } @computed get nativeWidth() { - return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, !this.fitWidth)); + return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, !this.layout_fitWidth)); } @computed get nativeHeight() { - return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, !this.fitWidth)); + return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, !this.layout_fitWidth)); } @computed get shouldNotScale() { - return (this.fitWidth && !this.nativeWidth) || [CollectionViewType.Docking].includes(this.Document._viewType as any); + return (this.layout_fitWidth && !this.nativeWidth) || [CollectionViewType.Docking].includes(this.Document._viewType as any); } @computed get effectiveNativeWidth() { return this.shouldNotScale ? 0 : this.nativeWidth || NumCast(this.layoutDoc.width); @@ -1356,8 +1356,8 @@ export class DocumentView extends React.Component { @computed get nativeScaling() { if (this.shouldNotScale) return 1; const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0; - if (this.fitWidth || this.props.PanelHeight() / (this.effectiveNativeHeight || 1) > this.props.PanelWidth() / (this.effectiveNativeWidth || 1)) { - return Math.max(minTextScale, this.props.PanelWidth() / (this.effectiveNativeWidth || 1)); // width-limited or fitWidth + if (this.layout_fitWidth || this.props.PanelHeight() / (this.effectiveNativeHeight || 1) > this.props.PanelWidth() / (this.effectiveNativeWidth || 1)) { + return Math.max(minTextScale, this.props.PanelWidth() / (this.effectiveNativeWidth || 1)); // width-limited or layout_fitWidth } return Math.max(minTextScale, this.props.PanelHeight() / (this.effectiveNativeHeight || 1)); // height-limited or unscaled } @@ -1365,7 +1365,7 @@ export class DocumentView extends React.Component { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); } @computed get panelHeight() { - if (this.effectiveNativeHeight && (!this.fitWidth || !this.layoutDoc.nativeHeightUnfrozen)) { + if (this.effectiveNativeHeight && (!this.layout_fitWidth || !this.layoutDoc.nativeHeightUnfrozen)) { return Math.min(this.props.PanelHeight(), this.effectiveNativeHeight * this.nativeScaling); } return this.props.PanelHeight(); @@ -1374,7 +1374,10 @@ export class DocumentView extends React.Component { return this.effectiveNativeWidth ? Math.max(0, (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2) : 0; } @computed get Yshift() { - return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 && (!this.layoutDoc.nativeHeightUnfrozen || (!this.fitWidth && this.effectiveNativeHeight * this.nativeScaling <= this.props.PanelHeight())) + return this.effectiveNativeWidth && + this.effectiveNativeHeight && + Math.abs(this.Xshift) < 0.001 && + (!this.layoutDoc.nativeHeightUnfrozen || (!this.layout_fitWidth && this.effectiveNativeHeight * this.nativeScaling <= this.props.PanelHeight())) ? Math.max(0, (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2) : 0; } @@ -1410,10 +1413,10 @@ export class DocumentView extends React.Component { finished?.(); this.docView && (this.docView._animateScaleTime = animTime); }); - const layoutKey = Cast(this.Document.layoutKey, 'string', null); - if (layoutKey !== 'layout_icon') { + const layout_fieldKey = Cast(this.Document.layout_fieldKey, 'string', null); + if (layout_fieldKey !== 'layout_icon') { this.switchViews(true, 'icon', finalFinished); - if (layoutKey && layoutKey !== 'layout' && layoutKey !== 'layout_icon') this.Document.deiconifyLayout = layoutKey.replace('layout_', ''); + if (layout_fieldKey && layout_fieldKey !== 'layout' && layout_fieldKey !== 'layout_icon') this.Document.deiconifyLayout = layout_fieldKey.replace('layout_', ''); } else { const deiconifyLayout = Cast(this.Document.deiconifyLayout, 'string', null); this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finalFinished); @@ -1433,7 +1436,7 @@ export class DocumentView extends React.Component { setTimeout( action(() => { if (useExistingLayout && custom && this.rootDoc['layout_' + view]) { - this.rootDoc.layoutKey = 'layout_' + view; + this.rootDoc.layout_fieldKey = 'layout_' + view; } else { this.setCustomView(custom, view); } @@ -1520,7 +1523,7 @@ export class DocumentView extends React.Component { width: xshift ?? `${(100 * (this.props.PanelWidth() - this.Xshift * 2)) / this.props.PanelWidth()}%`, height: this.props.forceAutoHeight ? undefined - : yshift ?? (this.fitWidth ? `${this.panelHeight}px` : `${(((100 * this.effectiveNativeHeight) / this.effectiveNativeWidth) * this.props.PanelWidth()) / this.props.PanelHeight()}%`), + : yshift ?? (this.layout_fitWidth ? `${this.panelHeight}px` : `${(((100 * this.effectiveNativeHeight) / this.effectiveNativeWidth) * this.props.PanelWidth()) / this.props.PanelHeight()}%`), }}> Doc.AreProtosEqual(d, otherdoc))) { - const alias = Doc.MakeAlias(otherdoc); - alias.x = wid; - alias.y = 0; - alias._lockedPosition = false; + const embedding = Doc.MakeEmbedding(otherdoc); + embedding.x = wid; + embedding.y = 0; + embedding._lockedPosition = false; wid += otherdoc[WidthSym](); - Doc.AddDocToList(Doc.GetProto(linkCollection), 'data', alias); + Doc.AddDocToList(Doc.GetProto(linkCollection), 'data', embedding); } }); return links; diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 163c5a9ed..f17ab06e7 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -90,7 +90,7 @@ export class EquationBox extends ViewBoxBaseComponent() { }; render() { TraceMobx(); - const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1); + const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1); return (
this.updateSize()} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 7eae4e938..85dd779fc 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -50,7 +50,7 @@ export class FieldView extends React.Component { @computed get field(): FieldResult { - const { Document, fieldKey } = this.props; + const { Document, fieldKey: fieldKey } = this.props; return Document[fieldKey]; } render() { diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx index b43e359ff..db72209ab 100644 --- a/src/client/views/nodes/FunctionPlotBox.tsx +++ b/src/client/views/nodes/FunctionPlotBox.tsx @@ -90,7 +90,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent if (ele) { this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.layoutDoc); } - // if (this.autoHeight) this.tryUpdateScrollHeight(); + // if (this.layout_autoHeight) this.tryUpdateScrollHeight(); }; @computed get theGraph() { return
r && this.createGraph(r)} style={{ position: 'absolute', width: '100%', height: '100%' }} onPointerDown={e => e.stopPropagation()} />; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index c9be10d3a..7d1d50cc7 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -79,9 +79,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent ({ forceFull: this.props.renderDepth < 1 || this.layoutDoc._showFullRes, - scrSize: (this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0] / this.nativeSize.nativeWidth) * NumCast(this.rootDoc._viewScale, 1), + scrSize: (this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0] / this.nativeSize.nativeWidth) * NumCast(this.rootDoc._freeform_scale, 1), selected: this.props.isSelected(), }), ({ forceFull, scrSize, selected }) => (this._curSuffix = selected ? '_o' : this.fieldKey === 'icon' ? '_m' : forceFull ? '_o' : scrSize < 0.25 ? '_s' : scrSize < 0.5 ? '_m' : scrSize < 0.8 ? '_l' : '_o'), @@ -116,7 +116,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent this.layoutDoc._scrollTop, + () => this.layoutDoc.layout_scrollTop, s_top => { this._forcedScroll = true; !this._ignoreScroll && this._mainCont.current && (this._mainCont.current.scrollTop = NumCast(s_top)); @@ -144,7 +144,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { Doc.AddDocToList(this.dataDoc, this.fieldKey + '-alternates', drop); - this.rootDoc[this.fieldKey + '-usePath'] = 'alternate:hover'; + this.rootDoc[this.fieldKey + '_usePath'] = 'alternate:hover'; e.stopPropagation(); }) ); @@ -167,28 +167,28 @@ export class ImageBox extends ViewBoxAnnotatableComponent { - const scaling = (this.props.DocumentView?.().props.ScreenToLocalTransform().Scale || 1) / NumCast(this.rootDoc._viewScale, 1); + const scaling = (this.props.DocumentView?.().props.ScreenToLocalTransform().Scale || 1) / NumCast(this.rootDoc._freeform_scale, 1); const nscale = NumCast(this.props.PanelWidth()) / scaling; - const nh = nscale / NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']); - const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']); - this.dataDoc[this.fieldKey + '-nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']) * nh; - this.dataDoc[this.fieldKey + '-nativeWidth'] = NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']) * nh; - this.rootDoc._panX = nh * NumCast(this.rootDoc._panX); - this.rootDoc._panY = nh * NumCast(this.rootDoc._panY); - this.dataDoc._panXMax = this.dataDoc._panXMax ? nh * NumCast(this.dataDoc._panXMax) : undefined; - this.dataDoc._panXMin = this.dataDoc._panXMin ? nh * NumCast(this.dataDoc._panXMin) : undefined; - this.dataDoc._panYMax = this.dataDoc._panYMax ? nw * NumCast(this.dataDoc._panYMax) : undefined; - this.dataDoc._panYMin = this.dataDoc._panYMin ? nw * NumCast(this.dataDoc._panYMin) : undefined; + const nh = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']); + const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); + this.dataDoc[this.fieldKey + '_nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']) * nh; + this.dataDoc[this.fieldKey + '_nativeWidth'] = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']) * nh; + this.rootDoc._freeform_panX = nh * NumCast(this.rootDoc._freeform_panX); + this.rootDoc._freeform_panY = nh * NumCast(this.rootDoc._freeform_panY); + this.dataDoc._freeform_panXMax = this.dataDoc._freeform_panXMax ? nh * NumCast(this.dataDoc._freeform_panXMax) : undefined; + this.dataDoc._freeform_panXMin = this.dataDoc._freeform_panXMin ? nh * NumCast(this.dataDoc._freeform_panXMin) : undefined; + this.dataDoc._freeform_panYMax = this.dataDoc._freeform_panYMax ? nw * NumCast(this.dataDoc._freeform_panYMax) : undefined; + this.dataDoc._freeform_panYMin = this.dataDoc._freeform_panYMin ? nw * NumCast(this.dataDoc._freeform_panYMin) : undefined; }); @undoBatch rotate = action(() => { - const nw = NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']); - const nh = NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']); + const nw = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); + const nh = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']); const w = this.layoutDoc._width; const h = this.layoutDoc._height; this.dataDoc[this.fieldKey + '-rotation'] = (NumCast(this.dataDoc[this.fieldKey + '-rotation']) + 90) % 360; - this.dataDoc[this.fieldKey + '-nativeWidth'] = nh; - this.dataDoc[this.fieldKey + '-nativeHeight'] = nw; + this.dataDoc[this.fieldKey + '_nativeWidth'] = nh; + this.dataDoc[this.fieldKey + '_nativeHeight'] = nw; this.layoutDoc._width = h; this.layoutDoc._height = w; }); @@ -204,7 +204,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent; }; - getScrollHeight = () => (this.props.fitWidth?.(this.rootDoc) !== false && NumCast(this.rootDoc._viewScale, 1) === NumCast(this.rootDoc._viewScaleMin, 1) ? this.nativeSize.nativeHeight : undefined); + getScrollHeight = () => (this.props.layout_fitWidth?.(this.rootDoc) !== false && NumCast(this.rootDoc._freeform_scale, 1) === NumCast(this.rootDoc._freeform_scaleMin, 1) ? this.nativeSize.nativeHeight : undefined); @computed private get considerDownloadIcon() { @@ -358,13 +358,13 @@ export class ImageBox extends ViewBoxAnnotatableComponent setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => (this.rootDoc[`_${this.fieldKey}-usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined))} + onPointerDown={e => setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => (this.rootDoc[`_${this.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined))} style={{ display: (SnappingManager.GetIsDragging() && DragManager.DocDragData?.canEmbed) || DocListCast(this.dataDoc[this.fieldKey + '-alternates']).length ? 'block' : 'none', width: 'min(10%, 25px)', @@ -431,7 +431,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))} key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}> @@ -459,9 +459,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent; } - screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop) * this.props.ScreenToLocalTransform().Scale); + screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop) * this.props.ScreenToLocalTransform().Scale); marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.rootDoc._viewScale, 1) <= NumCast(this.rootDoc.viewScaleMin, 1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.rootDoc._freeform_scale, 1) <= NumCast(this.rootDoc.freeform_scaleMin, 1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -497,9 +497,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent { if (!this._forcedScroll) { - if (this.layoutDoc._scrollTop || this._mainCont.current?.scrollTop) { + if (this.layoutDoc._layout_scrollTop || this._mainCont.current?.scrollTop) { this._ignoreScroll = true; - this.layoutDoc._scrollTop = this._mainCont.current?.scrollTop; + this.layoutDoc._layout_scrollTop = this._mainCont.current?.scrollTop; this._ignoreScroll = false; } } @@ -510,7 +510,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { } reverseNativeScaling = returnTrue; able = returnAlways; - fitWidth = returnTrue; + layout_fitWidth = returnTrue; overridePointerEvents = returnAll; onClickScriptDisable = returnAlways; @observable private rows: KeyValuePair[] = []; + @observable _splitPercentage = 50; - @computed get splitPercentage() { - return NumCast(this.props.Document.schemaSplitPercentage, 50); - } get fieldDocToLayout() { return this.props.fieldKey ? DocCast(this.props.Document[this.props.fieldKey], DocCast(this.props.Document)) : this.props.Document; } @@ -147,7 +145,9 @@ export class KeyValueBox extends React.Component { const rows: JSX.Element[] = []; let i = 0; const self = this; - for (const key of Object.keys(ids).slice().sort()) { + const keys = Object.keys(ids).slice(); + //for (const key of [...keys.filter(id => id !== 'layout' && !id.includes('_')).sort(), ...keys.filter(id => id === 'layout' || id.includes('_')).sort()]) { + for (const key of keys.sort()) { rows.push( { if (el) self.rows.push(el); }; })()} - keyWidth={100 - this.splitPercentage} + keyWidth={100 - this._splitPercentage} rowStyle={'keyValueBox-' + (i++ % 2 ? 'oddRow' : 'evenRow')} key={key} keyName={key} @@ -180,7 +180,7 @@ export class KeyValueBox extends React.Component { this._keyInput.current!.select(); e.stopPropagation(); }} - style={{ width: `${100 - this.splitPercentage}%` }}> + style={{ width: `${100 - this._splitPercentage}%` }}> { this._valInput.current!.select(); e.stopPropagation(); }} - style={{ width: `${this.splitPercentage}%` }}> + style={{ width: `${this._splitPercentage}%` }}> @@ -199,7 +199,7 @@ export class KeyValueBox extends React.Component { @action onDividerMove = (e: PointerEvent): void => { const nativeWidth = this._mainCont.current!.getBoundingClientRect(); - this.props.Document.schemaSplitPercentage = Math.max(0, 100 - Math.round(((e.clientX - nativeWidth.left) / nativeWidth.width) * 100)); + this._splitPercentage = Math.max(0, 100 - Math.round(((e.clientX - nativeWidth.left) / nativeWidth.width) * 100)); }; @action onDividerUp = (e: PointerEvent): void => { @@ -216,7 +216,7 @@ export class KeyValueBox extends React.Component { getFieldView = async () => { const rows = this.rows.filter(row => row.isChecked); if (rows.length > 1) { - const parent = Docs.Create.StackingDocument([], { _autoHeight: true, _width: 300, title: `field views for ${DocCast(this.props.Document.data).title}`, _chromeHidden: true }); + const parent = Docs.Create.StackingDocument([], { _layout_autoHeight: true, _width: 300, title: `field views for ${DocCast(this.props.Document.data).title}`, _chromeHidden: true }); for (const row of rows) { const field = this.createFieldView(DocCast(this.props.Document.data), row); field && Doc.AddDocToList(parent, 'data', field); @@ -229,9 +229,9 @@ export class KeyValueBox extends React.Component { createFieldView = (templateDoc: Doc, row: KeyValuePair) => { const metaKey = row.props.keyName; - const fieldTemplate = Doc.IsDelegateField(templateDoc, metaKey) ? Doc.MakeDelegate(templateDoc) : Doc.MakeAlias(templateDoc); + const fieldTemplate = Doc.IsDelegateField(templateDoc, metaKey) ? Doc.MakeDelegate(templateDoc) : Doc.MakeEmbedding(templateDoc); fieldTemplate.title = metaKey; - fieldTemplate.fitWidth = true; + fieldTemplate.layout_fitWidth = true; fieldTemplate._xMargin = 10; fieldTemplate._yMargin = 10; fieldTemplate._width = 100; @@ -284,8 +284,8 @@ export class KeyValueBox extends React.Component { render() { const dividerDragger = - this.splitPercentage === 0 ? null : ( -
+ this._splitPercentage === 0 ? null : ( +
); @@ -295,10 +295,10 @@ export class KeyValueBox extends React.Component { - - diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss index 57d36932e..2b4867321 100644 --- a/src/client/views/nodes/KeyValuePair.scss +++ b/src/client/views/nodes/KeyValuePair.scss @@ -19,6 +19,7 @@ position: relative; margin: 0; } + .keyValuePair-keyFieldMod, .keyValuePair-keyField { width: 100%; margin-left: 20px; @@ -27,6 +28,9 @@ overflow: auto; display: inline; } + .keyValuePair-keyFieldMod { + margin-left: 35px; + } } } .keyValuePair-td-value { diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 85641124f..509bb667e 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -66,7 +66,7 @@ export class KeyValuePair extends React.Component { isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, - dropAction: 'alias', + dropAction: 'embed', bringToFront: emptyFunction, renderDepth: 1, isContentActive: returnFalse, @@ -108,8 +108,8 @@ export class KeyValuePair extends React.Component { })}> X - -
+ +
{'('.repeat(parenCount)} {props.fieldKey} {')'.repeat(parenCount)} diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 916458dfd..32026ea9c 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -37,7 +37,7 @@ export class LabelBox extends ViewBoxBaseComponent { @@ -82,7 +82,7 @@ export class LabelBox extends ViewBoxBaseComponent { + fitTextToBox = (r: any) => { const singleLine = BoolCast(this.rootDoc._singleLine, true); const params = { rotateText: null, @@ -141,9 +141,9 @@ export class LabelBox extends ViewBoxBaseComponent - this.fitTextToBox(r))}> + this.fitTextToBox(r))}> {label.startsWith('#') ? null : label.replace(/([^a-zA-Z])/g, '$1\u200b')}
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 31f1775e5..f38ef634c 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -46,14 +46,14 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { const separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); if (separation > 100) { const dragData = new DragManager.DocumentDragData([this.rootDoc]); - dragData.dropAction = 'alias'; - dragData.removeDropProperties = ['anchor1_x', 'anchor1_y', 'anchor2_x', 'anchor2_y', 'onClick']; + dragData.dropAction = 'embed'; + dragData.removeDropProperties = ['link_anchor_1_x', 'link_anchor_1_y', 'link_anchor_2_x', 'link_anchor_2_y', 'onClick']; DragManager.StartDocumentDrag([this._ref.current!], dragData, pt[0], pt[1]); return true; } else { this.rootDoc[this.fieldKey + '_x'] = ((pt[0] - bounds.left) / bounds.width) * 100; this.rootDoc[this.fieldKey + '_y'] = ((pt[1] - bounds.top) / bounds.height) * 100; - this.rootDoc.linkAutoMove = false; + this.rootDoc.layout_autoMoveAnchors = false; } } return false; @@ -67,10 +67,14 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { const x = NumCast(this.rootDoc[this.fieldKey + '_x'], 100); const y = NumCast(this.rootDoc[this.fieldKey + '_y'], 100); const background = this.props.styleProvider?.(this.dataDoc, this.props, StyleProp.BackgroundColor + ':anchor'); - const anchor = this.fieldKey === 'anchor1' ? 'anchor2' : 'anchor1'; - const anchorScale = !this.dataDoc[this.fieldKey + '-useLinkSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25; + const anchor = this.fieldKey === 'link_anchor_1' ? 'link_anchor_2' : 'link_anchor_1'; + const anchorScale = !this.dataDoc[this.fieldKey + '_useLinkSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25; const targetTitle = StrCast((this.dataDoc[anchor] as Doc)?.title); - const selView = SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('anchor1') ? 'anchor1' : SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('anchor2') ? 'anchor2' : ''; + const selView = SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_1') + ? 'link_anchor_1' + : SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_2') + ? 'link_anchor_2' + : ''; return (
() { - public static LayoutString(fieldKey: string) { + public static LayoutString(fieldKey: string = 'link') { return FieldView.LayoutString(LinkBox, fieldKey); } @@ -23,7 +23,7 @@ export class LinkBox extends ViewBoxBaseComponent() {
{ onDismiss = (add: boolean) => { LinkDescriptionPopup.descriptionPopup = false; if (add) { - LinkManager.currentLink && (Doc.GetProto(LinkManager.currentLink).description = this.description); + LinkManager.currentLink && (Doc.GetProto(LinkManager.currentLink).link_description = this.description); } }; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index c58b5dd8c..c6172ee01 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -58,13 +58,13 @@ export class LinkDocPreview extends React.Component { var linkTarget = this.props.linkDoc; this._linkSrc = this.props.linkSrc; this._linkDoc = this.props.linkDoc; - const anchor1 = this._linkDoc?.anchor1 as Doc; - const anchor2 = this._linkDoc?.anchor2 as Doc; - if (anchor1 && anchor2) { - linkTarget = Doc.AreProtosEqual(anchor1, this._linkSrc) || Doc.AreProtosEqual(anchor1?.annotationOn as Doc, this._linkSrc) ? anchor2 : anchor1; + const link_anchor_1 = this._linkDoc?.link_anchor_1 as Doc; + const link_anchor_2 = this._linkDoc?.link_anchor_2 as Doc; + if (link_anchor_1 && link_anchor_2) { + linkTarget = Doc.AreProtosEqual(link_anchor_1, this._linkSrc) || Doc.AreProtosEqual(link_anchor_1?.annotationOn as Doc, this._linkSrc) ? link_anchor_2 : link_anchor_1; } if (linkTarget?.annotationOn && linkTarget?.type !== DocumentType.RTF) { - // want to show annotation context document if annotation is not text + // want to show annotation embedContainer document if annotation is not text linkTarget && DocCastAsync(linkTarget.annotationOn).then(action(anno => (this._markerTargetDoc = this._targetDoc = anno))); } else { this._markerTargetDoc = this._targetDoc = linkTarget; @@ -111,7 +111,7 @@ export class LinkDocPreview extends React.Component { action(anchor => { if (anchor instanceof Doc && LinkManager.Links(anchor).length) { this._linkDoc = this._linkDoc ?? LinkManager.Links(anchor)[0]; - const automaticLink = this._linkDoc.linkRelationship === LinkManager.AutoKeywords; + const automaticLink = this._linkDoc.link_relationship === LinkManager.AutoKeywords; if (automaticLink) { // automatic links specify the target in the link info, not the source const linkTarget = anchor; @@ -175,7 +175,7 @@ export class LinkDocPreview extends React.Component { } else if (this.props.hrefs?.length) { const webDoc = Array.from(SearchBox.staticSearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ?? - Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, useCors: true }); + Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true }); this.props.docProps?.addDocTab(webDoc, OpenWhere.lightbox); } }; @@ -208,7 +208,7 @@ export class LinkDocPreview extends React.Component {
{StrCast(this._markerTargetDoc.title).length > 16 ? StrCast(this._markerTargetDoc.title).substr(0, 16) + '...' : StrCast(this._markerTargetDoc.title)} -

{StrCast(this._linkDoc.description)}

+

{StrCast(this._linkDoc.link_description)}

Next Link
} placement="top"> @@ -263,7 +263,7 @@ export class LinkDocPreview extends React.Component { isDocumentActive={returnFalse} isContentActive={returnFalse} addDocument={returnFalse} - showTitle={returnEmptyString} + layout_showTitle={returnEmptyString} removeDocument={returnFalse} addDocTab={returnFalse} pinToPres={returnFalse} @@ -278,7 +278,7 @@ export class LinkDocPreview extends React.Component { pointerEvents={returnNone} focus={emptyFunction} whenChildContentsActiveChanged={returnFalse} - ignoreAutoHeight={true} // need to ignore autoHeight otherwise autoHeight text boxes will expand beyond the preview panel size. + ignoreAutoHeight={true} // need to ignore layout_autoHeight otherwise layout_autoHeight text boxes will expand beyond the preview panel size. bringToFront={returnFalse} NativeWidth={Doc.NativeWidth(this._targetDoc) ? () => Doc.NativeWidth(this._targetDoc) : undefined} NativeHeight={Doc.NativeHeight(this._targetDoc) ? () => Doc.NativeHeight(this._targetDoc) : undefined} diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 36be7d257..9b0fddce4 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -98,7 +98,7 @@ export class MapBox extends ViewBoxAnnotatableComponent void); @computed get inlineTextAnnotations() { @@ -126,7 +126,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } }, 250); // listener to addmarker event @@ -282,7 +282,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } this.dataDoc.mapLat = this._map.getCenter()?.lat(); this.dataDoc.mapLng = this._map.getCenter()?.lng(); @@ -292,7 +292,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } this.dataDoc.mapZoom = this._map.getZoom(); }; @@ -327,7 +327,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { console.log('print all sidebar Docs'); - if (!this.layoutDoc._showSidebar) this.toggleSidebar(); + if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; docs.forEach(doc => { if (doc.lat !== undefined && doc.lng !== undefined) { @@ -351,7 +351,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { - if (this.layoutDoc._showSidebar) this.toggleSidebar(); + if (this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; return this.removeDocument(doc, sidebarKey); }; @@ -375,11 +375,11 @@ export class MapBox extends ViewBoxAnnotatableComponent 0) { this._showSidebar = true; this.layoutDoc._width = fullWidth + localDelta[0]; - this.layoutDoc._sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; + this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; } else { this._showSidebar = false; this.layoutDoc._width = mapWidth; - this.layoutDoc._sidebarWidthPercent = '0%'; + this.layoutDoc._layout_sidebarWidthPercent = '0%'; } return false; }), @@ -388,12 +388,12 @@ export class MapBox extends ViewBoxAnnotatableComponent (Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); - @computed get sidebarWidthPercent() { - return StrCast(this.layoutDoc._sidebarWidthPercent, '0%'); + sidebarWidth = () => (Number(this.layout_sidebarWidthPercent.substring(0, this.layout_sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); + @computed get layout_sidebarWidthPercent() { + return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); } @computed get sidebarColor() { - return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '-backgroundColor'], '#e4e4e4')); + return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '_backgroundColor'], '#e4e4e4')); } /** @@ -453,7 +453,7 @@ export class MapBox extends ViewBoxAnnotatableComponent @@ -467,8 +467,8 @@ export class MapBox extends ViewBoxAnnotatableComponent { //1.2 * w * ? = .2 * w .2/1.2 const prevWidth = this.sidebarWidth(); - this.layoutDoc._showSidebar = (this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; - this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); + this.layoutDoc._layout_showSidebar = (this.layoutDoc._layout_sidebarWidthPercent = StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; + this.layoutDoc._width = this.layoutDoc._layout_showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); }; sidebarDown = (e: React.PointerEvent) => { @@ -476,8 +476,8 @@ export class MapBox extends ViewBoxAnnotatableComponent { const bounds = this._ref.current!.getBoundingClientRect(); - this.layoutDoc._sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; - this.layoutDoc._showSidebar = this.layoutDoc._sidebarWidthPercent !== '0%'; + this.layoutDoc._layout_sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; + this.layoutDoc._layout_showSidebar = this.layoutDoc._layout_sidebarWidthPercent !== '0%'; e.preventDefault(); return false; }; @@ -548,7 +548,7 @@ export class MapBox extends ViewBoxAnnotatableComponent this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); - scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); + scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; infoWidth = () => this.props.PanelWidth() / 5; @@ -616,7 +616,7 @@ export class MapBox extends ViewBoxAnnotatableComponent + style={{ width: `calc(100% - ${this.layout_sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
{renderAnnotations(this.transparentFilter)}
{renderAnnotations(this.opaqueFilter)} {SnappingManager.GetIsDragging() ? null : renderAnnotations()} @@ -667,7 +667,7 @@ export class MapBox extends ViewBoxAnnotatableComponent {/* */} -
+
void); @computed get inlineTextAnnotations() { @@ -123,7 +123,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } }, 250); // listener to addmarker event @@ -279,7 +279,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } this.dataDoc.mapLat = this._map.getCenter()?.lat(); this.dataDoc.mapLng = this._map.getCenter()?.lng(); @@ -289,7 +289,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } this.dataDoc.mapZoom = this._map.getZoom(); }; @@ -324,7 +324,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { console.log('print all sidebar Docs'); - if (!this.layoutDoc._showSidebar) this.toggleSidebar(); + if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; docs.forEach(doc => { if (doc.lat !== undefined && doc.lng !== undefined) { @@ -348,7 +348,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { - if (this.layoutDoc._showSidebar) this.toggleSidebar(); + if (this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; return this.removeDocument(doc, sidebarKey); }; @@ -372,11 +372,11 @@ export class MapBox2 extends ViewBoxAnnotatableComponent 0) { this._showSidebar = true; this.layoutDoc._width = fullWidth + localDelta[0]; - this.layoutDoc._sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; + this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; } else { this._showSidebar = false; this.layoutDoc._width = mapWidth; - this.layoutDoc._sidebarWidthPercent = '0%'; + this.layoutDoc._layout_sidebarWidthPercent = '0%'; } return false; }), @@ -385,12 +385,12 @@ export class MapBox2 extends ViewBoxAnnotatableComponent (Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); - @computed get sidebarWidthPercent() { - return StrCast(this.layoutDoc._sidebarWidthPercent, '0%'); + sidebarWidth = () => (Number(this.layout_sidebarWidthPercent.substring(0, this.layout_sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); + @computed get layout_sidebarWidthPercent() { + return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); } @computed get sidebarColor() { - return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '-backgroundColor'], '#e4e4e4')); + return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '_backgroundColor'], '#e4e4e4')); } /** @@ -450,7 +450,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent @@ -464,8 +464,8 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { //1.2 * w * ? = .2 * w .2/1.2 const prevWidth = this.sidebarWidth(); - this.layoutDoc._showSidebar = (this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; - this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); + this.layoutDoc._layout_showSidebar = (this.layoutDoc._layout_sidebarWidthPercent = StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; + this.layoutDoc._width = this.layoutDoc._layout_showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); }; sidebarDown = (e: React.PointerEvent) => { @@ -473,8 +473,8 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { const bounds = this._ref.current!.getBoundingClientRect(); - this.layoutDoc._sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; - this.layoutDoc._showSidebar = this.layoutDoc._sidebarWidthPercent !== '0%'; + this.layoutDoc._layout_sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; + this.layoutDoc._layout_showSidebar = this.layoutDoc._layout_sidebarWidthPercent !== '0%'; e.preventDefault(); return false; }; @@ -545,7 +545,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); - scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); + scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; infoWidth = () => this.props.PanelWidth() / 5; @@ -566,7 +566,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { e.button === 0 && !e.ctrlKey && e.stopPropagation(); }} - style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}> + style={{ width: `calc(100% - ${this.layout_sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
{renderAnnotations(this.transparentFilter)}
{renderAnnotations(this.opaqueFilter)} {SnappingManager.GetIsDragging() ? null : renderAnnotations()} @@ -616,7 +616,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent {/* */} -
+
{ setupMoveUpEvents(this, e, returnFalse, emptyFunction, e => { - const newBox = Docs.Create.TextDocument('Note', { _autoHeight: true }); + const newBox = Docs.Create.TextDocument('Note', { _layout_autoHeight: true }); FormattedTextBox.SelectOnLoad = newBox[Id]; // track the new text box so we can give it a prop that tells it to focus itself when it's displayed Doc.AddDocToList(this.props.place, 'data', newBox); this._stack?.scrollToBottom(); @@ -42,7 +42,7 @@ export class MapBoxInfoWindow extends React.Component doc.type === DocumentType.RTF; + childLayoutFitWidth = (doc: Doc) => doc.type === DocumentType.RTF; addDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.AddDocToList(this.props.place, 'data', d), true as boolean); removeDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.RemoveDocFromList(this.props.place, 'data', d), true as boolean); render() { @@ -69,7 +69,7 @@ export class MapBoxInfoWindow extends React.Component (this._pdf = PDFBox.pdfcache.get(this.pdfUrl!.url.href))); else if (PDFBox.pdfpromise.get(this.pdfUrl.url.href)) PDFBox.pdfpromise.get(this.pdfUrl.url.href)?.then(action((pdf: any) => (this._pdf = pdf))); @@ -122,15 +122,15 @@ export class PDFBox extends ViewBoxAnnotatableComponent { @@ -173,15 +173,15 @@ export class PDFBox extends ViewBoxAnnotatableComponent { setTimeout(() => { this.dataDoc.icon = new ImageField(iconFile); - this.dataDoc['icon-nativeWidth'] = nativeWidth; - this.dataDoc['icon-nativeHeight'] = nativeHeight; + this.dataDoc['icon_nativeWidth'] = nativeWidth; + this.dataDoc['icon_nativeHeight'] = nativeHeight; }, 500); } ); @@ -201,13 +201,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent this.rootDoc.scrollTop, + () => this.rootDoc.layout_scrollTop, () => { - if (!(ComputedField.WithoutComputed(() => FieldValue(this.props.Document[this.SidebarKey + '-panY'])) instanceof ComputedField)) { - this.props.Document[this.SidebarKey + '-panY'] = ComputedField.MakeFunction('this.scrollTop'); + if (!(ComputedField.WithoutComputed(() => FieldValue(this.props.Document[this.SidebarKey + '_panY'])) instanceof ComputedField)) { + this.props.Document[this.SidebarKey + '_panY'] = ComputedField.MakeFunction('this.layout_scrollTop'); } - this.props.Document[this.SidebarKey + '-viewScale'] = 1; - this.props.Document[this.SidebarKey + '-panX'] = 0; + this.props.Document[this.SidebarKey + '_freeform_scale'] = 1; + this.props.Document[this.SidebarKey + '_freeform_panX'] = 0; } ); } @@ -215,7 +215,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pdfViewer?.brushView(view); sidebarAddDocTab = (doc: Doc, where: OpenWhere) => { - if (DocListCast(this.props.Document[this.props.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) { + if (DocListCast(this.props.Document[this.props.fieldKey + '_sidebar']).includes(doc) && !this.SidebarShown) { this.toggleSidebar(false); return true; } @@ -239,7 +239,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { const anchor = Docs.Create.TextanchorDocument({ - title: StrCast(this.rootDoc.title + '@' + NumCast(this.layoutDoc._scrollTop)?.toFixed(0)), + title: StrCast(this.rootDoc.title + '@' + NumCast(this.layoutDoc._layout_scrollTop)?.toFixed(0)), unrendered: true, annotationOn: this.rootDoc, }); @@ -258,11 +258,11 @@ export class PDFBox extends ViewBoxAnnotatableComponent { - this.dataDoc[this.props.fieldKey + '-numPages'] = np; + this.dataDoc[this.props.fieldKey + '_numPages'] = np; Doc.SetNativeWidth(this.dataDoc, Math.max(Doc.NativeWidth(this.dataDoc), (nw * 96) / 72)); Doc.SetNativeHeight(this.dataDoc, (nh * 96) / 72); this.layoutDoc._height = this.layoutDoc[WidthSym]() / (Doc.NativeAspect(this.dataDoc) || 1); - !this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw)); + !this.Document._layout_fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw)); }; public search = action((searchString: string, bwd?: boolean, clear: boolean = false) => { @@ -279,14 +279,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pdfViewer?.prevAnnotation(); public nextAnnotation = () => this._pdfViewer?.nextAnnotation(); public backPage = () => { - this.Document._curPage = Math.max(1, (NumCast(this.Document._curPage) || 1) - 1); + this.Document._layout_curPage = Math.max(1, (NumCast(this.Document._layout_curPage) || 1) - 1); return true; }; public forwardPage = () => { - this.Document._curPage = Math.min(NumCast(this.dataDoc[this.props.fieldKey + '-numPages']), (NumCast(this.Document._curPage) || 1) + 1); + this.Document._layout_curPage = Math.min(NumCast(this.dataDoc[this.props.fieldKey + '_numPages']), (NumCast(this.Document._layout_curPage) || 1) + 1); return true; }; - public gotoPage = (p: number) => (this.Document._curPage = p); + public gotoPage = (p: number) => (this.Document._layout_curPage = p); @undoBatch onKeyDown = action((e: KeyboardEvent) => { @@ -316,9 +316,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent) => (this._searchString = e.currentTarget.value); // adding external documents; to sidebar key - // if (doc.Geolocation) this.addDocument(doc, this.fieldkey+"-annotation") + // if (doc.Geolocation) this.addDocument(doc, this.fieldkey+"_annotation") sidebarAddDocument = (doc: Doc | Doc[], sidebarKey: string = this.SidebarKey) => { - if (!this.layoutDoc._showSidebar) this.toggleSidebar(); + if (!this.layoutDoc._show_sidebar) this.toggleSidebar(); return this.addDocument(doc, sidebarKey); }; sidebarBtnDown = (e: React.PointerEvent, onButton: boolean) => { @@ -332,13 +332,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent= 1) { this.layoutDoc.nativeWidth = nativeWidth * ratio; onButton && (this.layoutDoc._width = this.layoutDoc[WidthSym]() + localDelta[0]); - this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth; + this.layoutDoc._show_sidebar = nativeWidth !== this.layoutDoc._nativeWidth; } return false; }, @@ -352,7 +352,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent = undefined; @observable _previewWidth: Opt = undefined; toggleSidebar = action((preview: boolean = false) => { - const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth']); + const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']); const sideratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth : 0) + nativeWidth) / nativeWidth; const pdfratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth + PDFBox.sidebarResizerWidth : 0) + nativeWidth) / nativeWidth; const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth); @@ -363,7 +363,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent ); const searchTitle = `${!this._searching ? 'Open' : 'Close'} Search Bar`; - const curPage = NumCast(this.Document._curPage) || 1; + const curPage = NumCast(this.Document._layout_curPage) || 1; return !this.props.isContentActive() || this._pdfViewer?.isAnnotating ? null : (
99 ? 4 : 3}ch`, pointerEvents: 'all' }} - onChange={e => (this.Document._curPage = Number(e.currentTarget.value))} + onChange={e => (this.Document._layout_curPage = Number(e.currentTarget.value))} onKeyDown={e => e.stopPropagation()} onClick={action(() => (this._pageControls = !this._pageControls))} /> @@ -470,7 +470,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._sidebarRef.current?.anchorMenuClick; @observable _showSidebar = false; @computed get SidebarShown() { - return this._showSidebar || this.layoutDoc._showSidebar ? true : false; + return this._showSidebar || this.layoutDoc._show_sidebar ? true : false; } @computed get sidebarHandle() { return ( @@ -480,7 +480,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this.sidebarBtnDown(e, true)}> @@ -490,10 +490,10 @@ export class PDFBox extends ViewBoxAnnotatableComponent 600 ? (NumCast(this.Document._height) * this.props.PanelWidth()) / NumCast(this.Document._width) : undefined, + height: this.props.Document._layout_scrollTop && !this.Document._layout_fitWidth && window.screen.width > 600 ? (NumCast(this.Document._height) * this.props.PanelWidth()) / NumCast(this.Document._width) : undefined, }}>
this.sidebarBtnDown(e, false)} />
{ this.result = info; this.dataDoc.type = DocumentType.VID; - this.dataDoc[this.fieldKey + '-duration'] = this.videoDuration; + this.dataDoc[this.fieldKey + '_duration'] = this.videoDuration; this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey); this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.client); diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 75e61bbeb..7bf765042 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -129,7 +129,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent { - const startTime = Cast(this.layoutDoc._currentTimecode, 'number', null) || (this._videoRec ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined); + const startTime = Cast(this.layoutDoc._layout_currentTimecode, 'number', null) || (this._videoRec ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined); return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, startTime, startTime === undefined ? undefined : startTime + 3, undefined, addAsAnnotation) || this.rootDoc; }; @@ -236,13 +236,13 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent { if (this.dataDoc[this.fieldKey + '-dictation']) return; const dictationText = DocUtils.GetNewTextDoc('dictation', NumCast(this.rootDoc.x), NumCast(this.rootDoc.y) + NumCast(this.layoutDoc._height) + 10, NumCast(this.layoutDoc._width), 2 * NumCast(this.layoutDoc._height)); - dictationText._autoHeight = false; + dictationText._layout_autoHeight = false; const dictationTextProto = Doc.GetProto(dictationText); dictationTextProto.recordingSource = this.dataDoc; dictationTextProto.recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.props.fieldKey}-recordingStart"]`); dictationTextProto.mediaState = ComputedField.MakeFunction('self.recordingSource.mediaState'); this.dataDoc[this.fieldKey + '-dictation'] = dictationText; }; - videoPanelHeight = () => (NumCast(this.dataDoc[this.fieldKey + '-nativeHeight'], this.layoutDoc[HeightSym]()) / NumCast(this.dataDoc[this.fieldKey + '-nativeWidth'], this.layoutDoc[WidthSym]())) * this.props.PanelWidth(); + videoPanelHeight = () => (NumCast(this.dataDoc[this.fieldKey + '_nativeHeight'], this.layoutDoc[HeightSym]()) / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth'], this.layoutDoc[WidthSym]())) * this.props.PanelWidth(); formattedPanelHeight = () => Math.max(0, this.props.PanelHeight() - this.videoPanelHeight()); render() { TraceMobx(); diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index f09962b22..37fda14fc 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -167,7 +167,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { - this.rootDoc.layoutKey = 'layout'; + this.rootDoc.layout_fieldKey = 'layout'; }; // displays error message @@ -702,7 +702,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent - {!StrCast(this.rootDoc.layoutKey).startsWith('layout_on') ? null : ( + {!StrCast(this.rootDoc.layout_fieldKey).startsWith('layout_on') ? null : (
+ Key + Fields