From 5b7d51d47a967e679d17560771efe71522ada13a Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 19 Aug 2020 22:30:57 -0400 Subject: more cleanup of SearchBox. made searchMatch be a tri-state for forward/backward/nomatch --- src/client/views/collections/CollectionTreeView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f23fa8eb6..0f6274663 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -469,7 +469,7 @@ class TreeView extends React.Component { return <>
Date: Fri, 21 Aug 2020 16:05:52 -0400 Subject: trying scenes instead of workspaces --- src/client/util/CurrentUserUtils.ts | 40 ++++++------- src/client/util/History.ts | 2 +- src/client/util/SettingsManager.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/MainView.scss | 2 +- src/client/views/MainView.tsx | 50 ++++++++-------- .../views/collections/CollectionDockingView.tsx | 12 ++-- .../views/collections/CollectionTreeView.tsx | 8 +-- src/client/views/collections/CollectionView.tsx | 2 +- .../CollectionFreeFormLayoutEngines.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 10 ++-- .../views/nodes/formattedText/DashDocView.tsx | 4 +- .../views/nodes/formattedText/RichTextSchema.tsx | 4 +- src/mobile/MobileInterface.tsx | 70 +++++++++++----------- 15 files changed, 105 insertions(+), 106 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 8dd7b033b..4b1c48bd3 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -36,7 +36,7 @@ export class CurrentUserUtils { @computed public static get UserDocument() { return Doc.UserDoc(); } @observable public static GuestTarget: Doc | undefined; - @observable public static GuestWorkspace: Doc | undefined; + @observable public static GuestScene: Doc | undefined; @observable public static GuestMobile: Doc | undefined; @observable public static propertiesWidth: number = 0; @@ -511,7 +511,7 @@ export class CurrentUserUtils { this.setupSharingSidebar(doc); // sets up the right sidebar collection for mobile upload documents and sharing return [ { title: "Sharing", target: Cast(doc["sidebar-sharing"], Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc["sidebar-sharing"] as Doc }, - { title: "Workspace", target: Cast(doc["sidebar-workspaces"], Doc, null), icon: "desktop", click: 'selectMainMenu(self)' }, + { title: "Scenes", target: Cast(doc["sidebar-scenes"], Doc, null), icon: "desktop", click: 'selectMainMenu(self)' }, { title: "Catalog", target: undefined as any, icon: "file", click: 'selectMainMenu(self)' }, { title: "Archive", target: Cast(doc["sidebar-recentlyClosed"], Doc, null), icon: "archive", click: 'selectMainMenu(self)' }, { title: "Import", target: Cast(doc["sidebar-import"], Doc, null), icon: "upload", click: 'selectMainMenu(self)' }, @@ -592,7 +592,7 @@ export class CurrentUserUtils { // SEts up mobile buttons for inside mobile menu static setupMobileButtons(doc?: Doc, buttons?: string[]) { const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, info: string, dragFactory?: Doc }[] = [ - { title: "WORKSPACES", icon: "bars", click: 'switchToMobileLibrary()', backgroundColor: "lightgrey", info: "Access your Workspaces from your mobile, and navigate through all of your documents. " }, + { title: "SCENES", icon: "bars", click: 'switchToMobileLibrary()', backgroundColor: "lightgrey", info: "Access your Scenes from your mobile, and navigate through all of your documents. " }, { title: "UPLOAD", icon: "upload", click: 'openMobileUploads()', backgroundColor: "lightgrey", info: "Upload files from your mobile device so they can be accessed on Dash Web." }, { title: "MOBILE UPLOAD", icon: "mobile", click: 'switchToMobileUploadCollection()', backgroundColor: "lightgrey", info: "Access the collection of your mobile uploads." }, { title: "RECORD", icon: "microphone", click: 'openMobileAudio()', backgroundColor: "lightgrey", info: "Use your phone to record, dictate and then upload audio onto Dash Web." }, @@ -689,7 +689,7 @@ export class CurrentUserUtils { } static setupLibrary(userDoc: Doc) { - return CurrentUserUtils.setupWorkspaces(userDoc); + return CurrentUserUtils.setupScenes(userDoc); } // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. @@ -724,28 +724,28 @@ export class CurrentUserUtils { } } - static async setupWorkspaces(doc: Doc) { - // setup workspaces library item - await doc.myWorkspaces; - if (doc.myWorkspaces === undefined) { - doc.myWorkspaces = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "WORKSPACES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true, system: true + static async setupScenes(doc: Doc) { + // setup scenes library item + await doc.myScenes; + if (doc.myScenes === undefined) { + doc.myScenes = new PrefetchProxy(Docs.Create.TreeDocument([], { + title: "SCENES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true, system: true })); } - if (doc["sidebar-workspaces"] === undefined) { - const newWorkspace = ScriptField.MakeScript(`createNewWorkspace()`); - (doc.myWorkspaces as Doc).contextMenuScripts = new List([newWorkspace!]); - (doc.myWorkspaces as Doc).contextMenuLabels = new List(["Create New Workspace"]); + if (doc["sidebar-scenes"] === undefined) { + const newScene = ScriptField.MakeScript(`createNewScene()`); + (doc.myScenes as Doc).contextMenuScripts = new List([newScene!]); + (doc.myScenes as Doc).contextMenuLabels = new List(["Create New Scene"]); - const workspaces = doc.myWorkspaces as Doc; + const scenes = doc.myScenes as Doc; - doc["sidebar-workspaces"] = new PrefetchProxy(Docs.Create.TreeDocument([workspaces], { + doc["sidebar-scenes"] = new PrefetchProxy(Docs.Create.TreeDocument([scenes], { treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })) as any as Doc; } - return doc.myWorkspaces as any as Doc; + return doc.myScenes as any as Doc; } static setupCatalog(doc: Doc) { @@ -821,7 +821,7 @@ export class CurrentUserUtils { static async setupSidebarButtons(doc: Doc) { CurrentUserUtils.setupSidebarContainer(doc); await CurrentUserUtils.setupToolsBtnPanel(doc); - CurrentUserUtils.setupWorkspaces(doc); + CurrentUserUtils.setupScenes(doc); CurrentUserUtils.setupCatalog(doc); CurrentUserUtils.setupRecentlyClosed(doc); CurrentUserUtils.setupUserDoc(doc); @@ -1002,8 +1002,8 @@ export class CurrentUserUtils { } } -Scripting.addGlobal(function createNewWorkspace() { return MainView.Instance.createNewWorkspace(); }, - "creates a new workspace when called"); +Scripting.addGlobal(function createNewScene() { return MainView.Instance.createNewScene(); }, + "creates a new scene when called"); Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, "returns all the links to the document or its annotations", "(doc: any)"); diff --git a/src/client/util/History.ts b/src/client/util/History.ts index 7b7d4b835..aed887055 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -197,7 +197,7 @@ export namespace HistoryUtil { await Promise.all(Object.keys(init).map(id => initDoc(id, init[id]))); } if (field instanceof Doc) { - MainView.Instance.openWorkspace(field, true); + MainView.Instance.openScene(field, true); } } diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 5642c5a42..b2131c9b2 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -158,7 +158,7 @@ export default class SettingsManager extends React.Component<{}> {
Settings
{Doc.CurrentUserEmail}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 0cc492ee9..fdce8bf71 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -596,7 +596,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> return ; } render() { - const darkScheme = Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ? "dimgray" : undefined; + const darkScheme = Cast(Doc.UserDoc().activeScene, Doc, null)?.darkScheme ? "dimgray" : undefined; const bounds = this.Bounds; const seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index a05a2b858..fb80bfc0d 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -313,7 +313,7 @@ } -.mainView-workspace { +.mainView-scene { height: 200px; position: relative; display: flex; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 6bbe09974..08ac69a38 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -77,10 +77,10 @@ export class MainView extends React.Component { @observable private _panelHeight: number = 0; @observable private _flyoutTranslate: boolean = false; @observable public flyoutWidth: number = 0; - private get darkScheme() { return BoolCast(Cast(this.userDoc?.activeWorkspace, Doc, null)?.darkScheme); } + private get darkScheme() { return BoolCast(Cast(this.userDoc?.activeScene, Doc, null)?.darkScheme); } @computed private get userDoc() { return Doc.UserDoc(); } - @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; } + @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeScene, Doc)) : CurrentUserUtils.GuestScene; } @computed public get mainFreeform(): Opt { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } @computed public get searchDoc() { return Cast(this.userDoc["search-panel"], Doc) as Doc; } @@ -224,12 +224,12 @@ export class MainView extends React.Component { } initAuthenticationRouters = async () => { - // Load the user's active workspace, or create a new one if initial session after signup + // Load the user's active scene, or create a new one if initial session after signup const received = CurrentUserUtils.MainDocId; if (received && !this.userDoc) { reaction( () => CurrentUserUtils.GuestTarget, - target => target && this.createNewWorkspace(), + target => target && this.createNewScene(), { fireImmediately: true } ); } else { @@ -242,21 +242,21 @@ export class MainView extends React.Component { }), ); } - const doc = this.userDoc && await Cast(this.userDoc.activeWorkspace, Doc); + const doc = this.userDoc && await Cast(this.userDoc.activeScene, Doc); if (doc) { - this.openWorkspace(doc); + this.openScene(doc); } else { - this.createNewWorkspace(); + this.createNewScene(); } } } @action - createNewWorkspace = async (id?: string) => { + createNewScene = async (id?: string) => { const myCatalog = Doc.UserDoc().myCatalog as Doc; const presentation = Doc.MakeCopy(Doc.UserDoc().emptyPresentation as Doc, true); - const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; - const workspaceCount = DocListCast(workspaces.data).length + 1; + const scenes = Cast(this.userDoc.myScenes, Doc) as Doc; + const sceneCount = DocListCast(scenes.data).length + 1; const freeformOptions: DocumentOptions = { x: 0, y: 400, @@ -265,28 +265,28 @@ export class MainView extends React.Component { title: "Untitled Collection", }; const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); - const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [myCatalog] }], { title: `Workspace ${workspaceCount}` }, id, "row"); + const sceneDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [myCatalog] }], { title: `Scene ${sceneCount}` }, id, "row"); Doc.AddDocToList(myCatalog, "data", freeformDoc); Doc.AddDocToList(myCatalog, "data", presentation); Doc.UserDoc().activePresentation = presentation; const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); - const copyWorkspace = ScriptField.MakeScript(`copyWorkspace()`); - workspaceDoc.contextMenuScripts = new List([toggleTheme!, toggleComic!, copyWorkspace!]); - workspaceDoc.contextMenuLabels = new List(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Workspace"]); + const copyScene = ScriptField.MakeScript(`copyScene()`); + sceneDoc.contextMenuScripts = new List([toggleTheme!, toggleComic!, copyScene!]); + sceneDoc.contextMenuLabels = new List(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Scene"]); - Doc.AddDocToList(workspaces, "data", workspaceDoc); + Doc.AddDocToList(scenes, "data", sceneDoc); // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) - setTimeout(() => this.openWorkspace(workspaceDoc), 0); + setTimeout(() => this.openScene(sceneDoc), 0); } @action - openWorkspace = (doc: Doc, fromHistory = false) => { + openScene = (doc: Doc, fromHistory = false) => { CurrentUserUtils.MainDocId = doc[Id]; - if (doc) { // this has the side-effect of setting the main container since we're assigning the active/guest workspace + if (doc) { // this has the side-effect of setting the main container since we're assigning the active/guest scene !("presentationView" in doc) && (doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })])); - this.userDoc ? (this.userDoc.activeWorkspace = doc) : (CurrentUserUtils.GuestWorkspace = doc); + this.userDoc ? (this.userDoc.activeScene = doc) : (CurrentUserUtils.GuestScene = doc); } const state = this._urlState; if (state.sharing === true && !this.userDoc) { @@ -438,7 +438,7 @@ export class MainView extends React.Component { flyoutWidthFunc = () => this.flyoutWidth; addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => { return where === "close" ? CollectionDockingView.CloseRightSplit(doc) : - doc.dockingConfig ? this.openWorkspace(doc) : + doc.dockingConfig ? this.openScene(doc) : CollectionDockingView.AddRightSplit(doc, libraryPath); } sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0) - Number(SEARCH_PANEL_HEIGHT.replace("px", "")), 1); @@ -977,12 +977,12 @@ export class MainView extends React.Component { } Scripting.addGlobal(function selectMainMenu(doc: Doc, title: string) { MainView.Instance.selectMenu(doc); }); Scripting.addGlobal(function toggleComicMode() { Doc.UserDoc().fontFamily = "Comic Sans MS"; Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; }); -Scripting.addGlobal(function copyWorkspace() { - const copiedWorkspace = Doc.MakeCopy(Cast(Doc.UserDoc().activeWorkspace, Doc, null), true); - const workspaces = Cast(Doc.UserDoc().myWorkspaces, Doc, null); - Doc.AddDocToList(workspaces, "data", copiedWorkspace); +Scripting.addGlobal(function copyScene() { + const copiedScene = Doc.MakeCopy(Cast(Doc.UserDoc().activeScene, Doc, null), true); + const scenes = Cast(Doc.UserDoc().myScenes, Doc, null); + Doc.AddDocToList(scenes, "data", copiedScene); // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) - setTimeout(() => MainView.Instance.openWorkspace(copiedWorkspace), 0); + setTimeout(() => MainView.Instance.openScene(copiedScene), 0); }); Scripting.addGlobal(function importDocument() { return MainView.Instance.importDocument(); }, "imports files from device directly into the import sidebar"); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 43da0d3cf..6338e69a4 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -96,7 +96,7 @@ export class CollectionDockingView extends React.Component this.setupGoldenLayout(), 1); - DocListCast((Doc.UserDoc().myWorkspaces as Doc).data).map(d => d.workspaceBrush = false); - this.props.Document.workspaceBrush = true; + DocListCast((Doc.UserDoc().myScenes as Doc).data).map(d => d.sceneBrush = false); + this.props.Document.sceneBrush = true; } this._ignoreStateChange = ""; }, { fireImmediately: true }); @@ -421,7 +421,7 @@ export class CollectionDockingView extends React.Component void = () => { try { - this.props.Document.workspaceBrush = false; + this.props.Document.sceneBrush = false; this._goldenLayout.unbind('itemDropped', this.itemDropped); this._goldenLayout.unbind('tabCreated', this.tabCreated); this._goldenLayout.unbind('stackCreated', this.stackCreated); @@ -668,7 +668,7 @@ export class CollectionDockingView extends React.Component 0) { - return
Nested workspaces can't be rendered
; + return
Nested scenes can't be rendered
; } return ; diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx index 0a4334302..92c3f09b4 100644 --- a/src/client/views/Palette.tsx +++ b/src/client/views/Palette.tsx @@ -3,7 +3,7 @@ import { observer } from "mobx-react"; import * as React from "react"; import { Doc } from "../../fields/Doc"; import { NumCast } from "../../fields/Types"; -import { emptyFunction, emptyPath, returnEmptyString, returnZero, returnFalse, returnOne, returnTrue, returnEmptyFilter } from "../../Utils"; +import { emptyFunction, emptyPath, returnEmptyString, returnZero, returnFalse, returnOne, returnTrue, returnEmptyFilter, returnEmptyDoclist } from "../../Utils"; import { Transform } from "../util/Transform"; import { DocumentView } from "./nodes/DocumentView"; import "./Palette.scss"; @@ -60,6 +60,7 @@ export default class Palette extends React.Component { whenActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} />
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index eb20fc257..e4ba45648 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -10,7 +10,7 @@ import { Doc, DocListCast } from "../../fields/Doc"; import { Docs, DocUtils, } from "../documents/Documents"; import { StrCast, Cast } from "../../fields/Types"; import { CollectionTreeView } from "./collections/CollectionTreeView"; -import { returnTrue, emptyFunction, returnFalse, returnOne, emptyPath, returnZero, returnEmptyFilter } from "../../Utils"; +import { returnTrue, emptyFunction, returnFalse, returnOne, emptyPath, returnZero, returnEmptyFilter, returnEmptyDoclist } from "../../Utils"; import { Transform } from "../util/Transform"; import { ScriptField, ComputedField } from "../../fields/ScriptField"; import { Scripting } from "../util/Scripting"; @@ -133,6 +133,7 @@ export class TemplateMenu extends React.Component { ContainingCollectionDoc={undefined} ContainingCollectionView={undefined} docFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} rootSelected={returnFalse} onCheckedClick={this.scriptField} onChildClick={this.scriptField} diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 83321d6e0..74b1e5714 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -14,7 +14,7 @@ import { FieldId } from "../../../fields/RefField"; import { listSpec } from '../../../fields/Schema'; import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils } from "../../../Utils"; +import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils, returnEmptyDoclist } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; @@ -938,6 +938,7 @@ export class DockedFrameRenderer extends React.Component { addDocTab={this.addDocTab} pinToPres={DockedFrameRenderer.PinDoc} docFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} fitToBox={true} />
@@ -979,6 +980,7 @@ export class DockedFrameRenderer extends React.Component { addDocTab={this.addDocTab} pinToPres={DockedFrameRenderer.PinDoc} docFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} /> {document._viewType === CollectionViewType.Freeform && !this._document?.hideMinimap ? this.renderMiniMap() : (null)} diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index e1b07077e..0fd18034f 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -166,6 +166,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { whenActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={this.props.docFilters} + searchFilterDocs={this.props.searchFilterDocs} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} />
; diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 388eda2b3..5580c32f2 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -131,7 +131,7 @@ export class CollectionViewBaseChrome extends React.Component Doc.GetProto(this.target).data = new List(source)), // Doc.aliasDocs(source), + immediate: undoBatch((source: Doc[]) => Doc.GetProto(this.target).data = new List(source)), initialize: emptyFunction, }; _onClickCommand = { @@ -180,12 +180,16 @@ export class CollectionViewBaseChrome extends React.Component this.target._docFilters = undefined), - initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : ""; }, + script: `self.target._docFilters = copyField(self['target-docFilters']); + self.target._searchFilterDocs = compareLists(self['target-searchFilterDocs'],self.target._searchFilterDocs) ? undefined: copyField(self['target-searchFilterDocs']);`, + immediate: undoBatch((source: Doc[]) => { this.target._docFilters = undefined; this.target._searchFilterDocs = undefined; }), + initialize: (button: Doc) => { + button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : undefined; + button['target-searchFilterDocs'] = this.target._searchFilterDocs instanceof ObjectField ? ObjectField.MakeCopy(this.target._searchFilterDocs as any as ObjectField) : undefined; + }, }; - @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; } + @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand, this._saveFilterCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; } @computed get _stacking_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._contentCommand, this._templateCommand]; } @computed get _masonry_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._contentCommand, this._templateCommand]; } @computed get _schema_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._templateCommand, this._narrativeCommand]; } diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 4bd69041b..2f1f7a90f 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -229,7 +229,7 @@ export class CollectionSchemaCell extends React.Component { const fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); const onItemDown = async (e: React.PointerEvent) => { - if (this.props.Document._searchDoc !== undefined) { + if (this.props.Document._searchDoc) { const doc = Doc.GetProto(this.props.rowProps.original); const aliasdoc = await SearchUtil.GetAliasesOfDocument(doc); let targetContext = undefined; @@ -315,7 +315,7 @@ export class CollectionSchemaCell extends React.Component { } } let search = false; - if (this.props.Document._searchDoc !== undefined) { + if (this.props.Document._searchDoc) { search = true; } @@ -900,7 +900,7 @@ export class CollectionSchemaButtons extends CollectionSchemaCell { // (!this.props.CollectionView || !this.props.CollectionView.props.isSelected() ? undefined : // SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); // }; - return !BoolCast(this.props.Document._searchDoc) ? <> + return !this.props.Document._searchDoc ? <> : [DocumentType.PDF, DocumentType.RTF].includes(StrCast(doc.type) as DocumentType) ?
; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 2f536a464..c5ea02a2f 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -64,6 +64,8 @@ export interface TreeViewProps { onCheckedClick?: () => ScriptField; onChildClick?: () => ScriptField; ignoreFields?: string[]; + firstLevel: boolean; + forceOpen: boolean; } @observer @@ -77,6 +79,7 @@ export interface TreeViewProps { */ class TreeView extends React.Component { private _editTitleScript: (() => ScriptField) | undefined; + private _openScript: (() => ScriptField) | undefined; private _header?: React.RefObject = React.createRef(); private _treedropDisposer?: DragManager.DragDropDisposer; private _dref = React.createRef(); @@ -96,7 +99,7 @@ class TreeView extends React.Component { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; } - @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen; } + @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen || this.props.forceOpen; } @computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.treeViewDefaultExpandedView); } @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); } @computed get dataDoc() { return this.doc[DataSym]; } @@ -130,8 +133,10 @@ class TreeView extends React.Component { constructor(props: any) { super(props); - const script = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); documentView.select();} `, { documentView: "any" }); - this._editTitleScript = script && (() => script); + const titleScript = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); documentView.select();} `, { documentView: "any" }); + const openScript = ScriptField.MakeScript(`openOnRight(self)`); + this._editTitleScript = titleScript && (() => titleScript); + this._openScript = openScript && (() => openScript); if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false); } @@ -280,7 +285,7 @@ class TreeView extends React.Component { DocListCast(contents), this.props.treeViewDoc, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields); + [...this.props.renderedIds, doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, false); } else { contentElement = { (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true), true); const docs = expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs; const sortKey = `${this.fieldKey}-sortAscending`; - return
    { + return
      { this.doc[sortKey] = (this.doc[sortKey] ? false : (this.doc[sortKey] === false ? undefined : true)); e.stopPropagation(); }}> @@ -331,7 +336,7 @@ class TreeView extends React.Component { this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, this.doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields)} + [...this.props.renderedIds, this.doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, false)}
    ; } else if (this.treeViewExpandedView === "fields") { return
      @@ -409,10 +414,11 @@ class TreeView extends React.Component { this._docRef.current?.ContentDiv && simulateMouseClick(this._docRef.current.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); } focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true); - contextMenuItems = () => [{ script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; + contextMenuItems = () => [{ script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }, { script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }]; truncateTitleWidth = () => NumCast(this.props.treeViewDoc.treeViewTruncateTitleWidth, 0); showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || ""); onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.editTitleScript)); + onChildDoubleClick = () => this._openScript?.() || ScriptCast(this.doc.editTitleScript); /** * Renders the EditableView title element for placement into the tree. */ @@ -449,6 +455,7 @@ class TreeView extends React.Component { rootSelected={returnTrue} pinToPres={emptyFunction} onClick={this.onChildClick} + onDoubleClick={this.onChildDoubleClick} dropAction={this.props.dropAction} moveDocument={this.move} removeDocument={this.removeDoc} @@ -482,9 +489,6 @@ class TreeView extends React.Component { {view}
      {headerElements} -
      - -
      ; } @@ -502,30 +506,31 @@ class TreeView extends React.Component { } } } else this._editMaxWidth = ""; - return
      this.props.active(true) && SelectionManager.DeselectAll()}> -
    • -
      { - if (this.props.active(true)) { - e.stopPropagation(); - e.preventDefault(); - SelectionManager.DeselectAll(); - } - }} - onPointerDown={e => { + return this.doc.treeViewHideTopDoc && this.props.firstLevel ? !this.treeViewOpen || this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent : +
      this.props.active(true) && SelectionManager.DeselectAll()}> +
    • +
      { if (this.props.active(true)) { e.stopPropagation(); e.preventDefault(); + SelectionManager.DeselectAll(); } }} - onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}> - {this.renderBullet} - {this.renderTitle} -
      -
      - {!this.treeViewOpen || this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent} -
      -
    • -
      ; + onPointerDown={e => { + if (this.props.active(true)) { + e.stopPropagation(); + e.preventDefault(); + } + }} + onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}> + {this.renderBullet} + {this.renderTitle} +
+
+ {!this.treeViewOpen || this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent} +
+ +
; } public static GetChildElements( childDocs: Doc[], @@ -554,7 +559,9 @@ class TreeView extends React.Component { libraryPath: Doc[] | undefined, onCheckedClick: undefined | (() => ScriptField), onChildClick: undefined | (() => ScriptField), - ignoreFields: string[] | undefined + ignoreFields: string[] | undefined, + firstLevel: boolean, + forceOpen: boolean ) { const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField); if (viewSpecScript) { @@ -663,13 +670,15 @@ class TreeView extends React.Component { treeViewHideHeaderFields={treeViewHideHeaderFields} treeViewPreventOpen={treeViewPreventOpen} renderedIds={renderedIds} - ignoreFields={ignoreFields} />; + ignoreFields={ignoreFields} + firstLevel={firstLevel} + forceOpen={forceOpen} />; }); } } export type collectionTreeViewProps = { - treeViewHideTitle?: boolean; + treeViewHideTopDoc?: boolean; treeViewHideHeaderFields?: boolean; onCheckedClick?: () => ScriptField; onChildClick?: () => ScriptField; @@ -745,7 +754,7 @@ export class CollectionTreeView extends CollectionSubView this.doc.treeViewPreventOpen = !this.doc.treeViewPreventOpen, icon: "paint-brush" }); layoutItems.push({ description: (this.doc.treeViewHideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.doc.treeViewHideHeaderFields = !this.doc.treeViewHideHeaderFields, icon: "paint-brush" }); - layoutItems.push({ description: (this.doc.treeViewHideTitle ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTitle = !this.doc.treeViewHideTitle, icon: "paint-brush" }); + layoutItems.push({ description: (this.doc.treeViewHideTopDoc ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTopDoc = !this.doc.treeViewHideTopDoc, icon: "paint-brush" }); layoutItems.push({ description: (this.doc.treeViewHideLinkLines ? "Show" : "Hide") + " Link Lines", event: () => this.doc.treeViewHideLinkLines = !this.doc.treeViewHideLinkLines, icon: "paint-brush" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: layoutItems, icon: "eye" }); } @@ -817,6 +826,12 @@ export class CollectionTreeView extends CollectionSubView this.addDoc(doc, relativeTo, before); const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(d, target, addDoc); const childDocs = this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs; + const childElements = childDocs && TreeView.GetChildElements(childDocs, this.doc, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, + moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, + this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), + BoolCast(this.doc.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick, + this.onChildClick, this.props.ignoreFields, true, BoolCast(this.props.Document.treeViewOpen)); + const hideTitle = this.props.treeViewHideTopDoc || this.doc.treeViewHideTopDoc; return !childDocs ? (null) : (
this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} ref={this.createTreeDropTarget}> - {this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? (null) : } {this.doc.allowClear ? this.renderClearButton : (null)} -
    - { - TreeView.GetChildElements(childDocs, this.doc, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, - moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, - this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), - BoolCast(this.doc.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick, - this.onChildClick, this.props.ignoreFields) - } -
+
    {childElements}
); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 1ad63c34e..38809e1e8 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -178,7 +178,6 @@ export class CollectionView extends Touchable Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); (targetDataDoc[this.props.fieldKey] as List).push(...added); targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); const lastModified = "lastModified"; @@ -550,7 +549,7 @@ export class CollectionView extends Touchable {
{this.editableTitle}
-
runInAction(() => { this.inOptions = true; })} +
this.inOptions = true)} onPointerLeave={action(() => this.inOptions = false)}>
runInAction(() => { this.openOptions = !this.openOptions; })} + onPointerDown={action(() => this.openOptions = !this.openOptions)} style={{ backgroundColor: this.openOptions ? "black" : "" }}> Options
@@ -860,7 +860,7 @@ export class PropertiesView extends React.Component {
runInAction(() => { this.openSharing = !this.openSharing; })} + onPointerDown={action(() => this.openSharing = !this.openSharing)} style={{ backgroundColor: this.openSharing ? "black" : "" }}> Sharing {"&"} Permissions
@@ -914,7 +914,7 @@ export class PropertiesView extends React.Component { {!this.isInk ? (null) :
runInAction(() => { this.openAppearance = !this.openAppearance; })} + onPointerDown={action(() => this.openAppearance = !this.openAppearance)} style={{ backgroundColor: this.openAppearance ? "black" : "" }}> Appearance
@@ -929,7 +929,7 @@ export class PropertiesView extends React.Component { {this.isInk ?
runInAction(() => { this.openTransform = !this.openTransform; })} + onPointerDown={action(() => this.openTransform = !this.openTransform)} style={{ backgroundColor: this.openTransform ? "black" : "" }}> Transform
@@ -943,7 +943,7 @@ export class PropertiesView extends React.Component {
runInAction(() => { this.openFields = !this.openFields; })} + onPointerDown={action(() => this.openFields = !this.openFields)} style={{ backgroundColor: this.openFields ? "black" : "" }}> Fields {"&"} Tags
@@ -961,10 +961,10 @@ export class PropertiesView extends React.Component {
runInAction(() => { this.openLayout = !this.openLayout; })} + onPointerDown={action(() => this.openLayout = !this.openLayout)} style={{ backgroundColor: this.openLayout ? "black" : "" }}> Layout -
runInAction(() => { this.openLayout = !this.openLayout; })}> +
@@ -1002,7 +1002,7 @@ export class PropertiesView extends React.Component {
} {!selectedItem ? (null) :
runInAction(() => { this.openPresProgressivize = !this.openPresProgressivize; })} + onPointerDown={action(() => { this.openPresProgressivize = !this.openPresProgressivize; })} style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}>     Progressivize
@@ -1015,7 +1015,7 @@ export class PropertiesView extends React.Component {
} {!selectedItem ? (null) :
runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })} + onPointerDown={action(() => { this.openSlideOptions = !this.openSlideOptions; })} style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}>     {PresBox.Instance.stringType} options
@@ -1028,7 +1028,7 @@ export class PropertiesView extends React.Component {
}
runInAction(() => { this.openAddSlide = !this.openAddSlide; })} + onPointerDown={action(() => { this.openAddSlide = !this.openAddSlide; })} style={{ backgroundColor: this.openAddSlide ? "black" : "" }}>     Add new slide
@@ -1041,7 +1041,7 @@ export class PropertiesView extends React.Component {
{/*
runInAction(() => { this.openSharing = !this.openSharing; })} + onPointerDown={acition(() => { this.openSharing = !this.openSharing; })} style={{ backgroundColor: this.openSharing ? "black" : "" }}> Sharing {"&"} Permissions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 767a4504d..9ab2889e1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -286,6 +286,8 @@ export class DocumentView extends DocComponent(Docu } } + _timeout: NodeJS.Timeout | undefined; + onClick = action((e: React.MouseEvent | React.PointerEvent) => { if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && this.props.renderDepth >= 0 && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { @@ -293,6 +295,10 @@ export class DocumentView extends DocComponent(Docu let preventDefault = true; !this.props.Document.isBackground && this.props.bringToFront(this.props.Document); if (this._doubleTap && this.props.renderDepth && (this.props.Document.type !== DocumentType.FONTICON || this.onDoubleClickHandler)) {// && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click + if (this._timeout) { + clearTimeout(this._timeout); + this._timeout = undefined; + } if (!(e.nativeEvent as any).formattedHandled) { if (this.onDoubleClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself const func = () => this.onDoubleClickHandler.script.run({ @@ -324,9 +330,14 @@ export class DocumentView extends DocComponent(Docu documentView: this, shiftKey: e.shiftKey }, console.log); - if (!Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-undo"] as Doc) && !Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-redo"] as Doc)) { - UndoManager.RunInBatch(func, "on click"); - } else func(); + const clickFunc = () => { + if (!Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-undo"] as Doc) && !Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-redo"] as Doc)) { + UndoManager.RunInBatch(func, "on click"); + } else func(); + }; + if (this.onDoubleClickHandler) { + this._timeout = setTimeout(() => { this._timeout = undefined; clickFunc(); }, 500); + } else clickFunc(); } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself this.props.addDocTab(DocUtils.makeCustomViewClicked(Doc.MakeAlias(this.props.Document), undefined, "onClick"), "onRight"); } else if (this.allLinks && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) { @@ -771,7 +782,7 @@ export class DocumentView extends DocComponent(Docu moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" }); } moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); - Doc.AreProtosEqual(this.props.Document, Cast(Doc.UserDoc()["sidebar-userDoc"], Doc, null)) && moreItems.push({ description: "Toggle Alternate Button Bar", event: () => Doc.UserDoc()["documentLinksButton-hideEnd"] = !Doc.UserDoc()["documentLinksButton-hideEnd"], icon: "eye" }); + Doc.AreProtosEqual(this.props.Document, Cast(Doc.UserDoc().myUserDoc, Doc, null)) && moreItems.push({ description: "Toggle Alternate Button Bar", event: () => Doc.UserDoc()["documentLinksButton-hideEnd"] = !Doc.UserDoc()["documentLinksButton-hideEnd"], icon: "eye" }); } const collectionAcl = GetEffectiveAcl(this.props.ContainingCollectionDoc?.[DataSym]); diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 532e7dc15..a067f23af 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -26,6 +26,8 @@ export class LinkBox extends ViewBoxBaseComponent( NativeWidth={returnZero} ignoreFields={Cast(this.props.Document.linkBoxExcludedKeys, listSpec("string"), null)} annotationsKey={""} + dontRegisterView={true} + renderDepth={this.props.renderDepth + 1} CollectionView={undefined} addDocument={returnFalse} removeDocument={returnFalse} diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 6bde94a76..5e20b6f9f 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -436,7 +436,7 @@ export class PresBox extends ViewBoxBaseComponent const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc); if (this.layoutDoc.inOverlay) { this.layoutDoc.presStatus = 'edit'; - Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc); + Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc); CollectionDockingView.AddRightSplit(this.rootDoc); this.layoutDoc.inOverlay = false; } else if (this.layoutDoc.context && docView) { @@ -447,7 +447,7 @@ export class PresBox extends ViewBoxBaseComponent this.rootDoc._height = 35; this.rootDoc._width = 250; docView.props.removeDocument?.(this.layoutDoc); - Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc); + Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc); } else { this.layoutDoc.presStatus = 'manual'; const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); @@ -456,7 +456,7 @@ export class PresBox extends ViewBoxBaseComponent this.rootDoc._height = 35; this.rootDoc._width = 250; this.props.addDocTab?.(this.rootDoc, "close"); - Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc); + Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc); } } diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 866e41ee0..5d51c420b 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -73,7 +73,7 @@ export class ScreenshotBox extends ViewBoxBaseComponent { - const audioRightSidebar = Cast(Doc.UserDoc()["sidebar-sharing"], Doc) as Doc; + const audioRightSidebar = Cast(Doc.UserDoc().mySharedDocs, Doc) as Doc; const audioDoc = this._audioCol; const data = Cast(audioRightSidebar.data, listSpec(Doc)); for (let i = 1; i < 8; i++) { diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 8ca67f9ee..841862f49 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -402,7 +402,7 @@ export class MobileInterface extends React.Component { title: "Collection " + dashboardCount, }; const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); - const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Dashboard ${dashboardCount}` }, id, "row"); + const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row"); const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); @@ -440,7 +440,7 @@ export class MobileInterface extends React.Component { // DocButton that uses UndoManager and handles the opacity change if CanUndo is true @computed get undo() { if (this.mainContainer && this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && - this._activeDoc !== Doc.UserDoc()["sidebar-sharing"] && this._activeDoc.title !== "WORKSPACES") { + this._activeDoc !== Doc.UserDoc().mySharedDocs && this._activeDoc.title !== "WORKSPACES") { return (
; } @@ -632,7 +632,7 @@ export class MobileInterface extends React.Component { */ @action switchToMobileUploads = () => { - const mobileUpload = Cast(Doc.UserDoc()["sidebar-sharing"], Doc) as Doc; + const mobileUpload = Cast(Doc.UserDoc().mySharedDocs, Doc) as Doc; this.switchCurrentView(mobileUpload); this._homeMenu = false; } -- cgit v1.2.3-70-g09d2 From 69f94b19baa37a0a9114bc21710d2e09b49b638d Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 24 Aug 2020 18:37:46 -0400 Subject: removed treeViewOpen from sidebar panels since they don't need them now that the top level is hidden. --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 8 ++++---- src/client/views/MainView.tsx | 6 ++++-- src/client/views/collections/CollectionTreeView.tsx | 10 +++++----- src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 3 ++- 6 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 759310241..cef7c5d4d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -694,7 +694,7 @@ export namespace Docs { linkDocProto.anchor2_timecode = target.doc._currentTimecode || target.doc.displayTimecode; if (linkDocProto.linkBoxExcludedKeys === undefined) { - Cast(linkDocProto.proto, Doc, null).linkBoxExcludedKeys = new List(["treeViewExpandedView", "aliases", "treeViewHideTopDoc", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); + Cast(linkDocProto.proto, Doc, null).linkBoxExcludedKeys = new List(["treeViewExpandedView", "aliases", "treeViewHideTopLevel", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); Cast(linkDocProto.proto, Doc, null).layoutKey = undefined; } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index a4cfd67fb..997807ce4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -218,7 +218,7 @@ export class CurrentUserUtils { const shared = { _chromeStatus: "disabled", _autoHeight: true, _xMargin: 0 }; const detailViewOpts = { title: "detailView", _width: 300, _fontFamily: "Arial", _fontSize: "12pt" }; - const descriptionWrapperOpts = { title: "descriptions", _height: 300, _columnWidth: -1, treeViewHideTopDoc: true, _pivotField: "title", system: true }; + const descriptionWrapperOpts = { title: "descriptions", _height: 300, _columnWidth: -1, treeViewHideTopLevel: true, _pivotField: "title", system: true }; const descriptionWrapper = MasonryDocument([details, short, long], { ...shared, ...descriptionWrapperOpts }); descriptionWrapper._columnHeaders = new List([ @@ -738,7 +738,7 @@ export class CurrentUserUtils { doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Dashboards", _height: 400, treeViewHideTopLevel: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true, + treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); const newDashboard = ScriptField.MakeScript(`createNewDashboard()`); @@ -754,7 +754,7 @@ export class CurrentUserUtils { doc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Presentations", _height: 100, treeViewHideTopLevel: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true, + treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); const newPresentations = ScriptField.MakeScript(`createNewPresentation()`); @@ -772,7 +772,7 @@ export class CurrentUserUtils { doc.myInactiveDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "Inactive", _height: 500, treeViewHideTopLevel: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true, + treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); const clearAll = ScriptField.MakeScript(`self.data = new List([])`); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 9189c1951..67d1de2ec 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -293,8 +293,9 @@ export class MainView extends React.Component { const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); const copyDashboard = ScriptField.MakeScript(`copyDashboard()`); - dashboardDoc.contextMenuScripts = new List([toggleTheme!, toggleComic!, copyDashboard!]); - dashboardDoc.contextMenuLabels = new List(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard"]); + const createDashboard = ScriptField.MakeScript(`createDashb oard()`); + dashboardDoc.contextMenuScripts = new List([toggleTheme!, toggleComic!, copyDashboard!, createDashboard!]); + dashboardDoc.contextMenuLabels = new List(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Create Dashboard"]); Doc.AddDocToList(dashboards, "data", dashboardDoc); // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) @@ -1005,5 +1006,6 @@ Scripting.addGlobal(function copyDashboard() { setTimeout(() => MainView.Instance.openDashboard(copy), 0); }); }); +Scripting.addGlobal(function createDashboard() { MainView.Instance.createNewDashboard(); }); Scripting.addGlobal(function importDocument() { return MainView.Instance.importDocument(); }, "imports files from device directly into the import sidebar"); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c5ea02a2f..585d1f775 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -327,7 +327,7 @@ class TreeView extends React.Component { (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true), true); const docs = expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs; const sortKey = `${this.fieldKey}-sortAscending`; - return
    { + return
      { this.doc[sortKey] = (this.doc[sortKey] ? false : (this.doc[sortKey] === false ? undefined : true)); e.stopPropagation(); }}> @@ -506,7 +506,7 @@ class TreeView extends React.Component { } } } else this._editMaxWidth = ""; - return this.doc.treeViewHideTopDoc && this.props.firstLevel ? !this.treeViewOpen || this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent : + return this.doc.treeViewHideTopLevel && this.props.firstLevel ? !this.treeViewOpen || this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent :
      this.props.active(true) && SelectionManager.DeselectAll()}>
    • { @@ -678,7 +678,7 @@ class TreeView extends React.Component { } export type collectionTreeViewProps = { - treeViewHideTopDoc?: boolean; + treeViewHideTopLevel?: boolean; treeViewHideHeaderFields?: boolean; onCheckedClick?: () => ScriptField; onChildClick?: () => ScriptField; @@ -754,7 +754,7 @@ export class CollectionTreeView extends CollectionSubView this.doc.treeViewPreventOpen = !this.doc.treeViewPreventOpen, icon: "paint-brush" }); layoutItems.push({ description: (this.doc.treeViewHideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.doc.treeViewHideHeaderFields = !this.doc.treeViewHideHeaderFields, icon: "paint-brush" }); - layoutItems.push({ description: (this.doc.treeViewHideTopDoc ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTopDoc = !this.doc.treeViewHideTopDoc, icon: "paint-brush" }); + layoutItems.push({ description: (this.doc.treeViewHideTopLevel ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTopLevel = !this.doc.treeViewHideTopLevel, icon: "paint-brush" }); layoutItems.push({ description: (this.doc.treeViewHideLinkLines ? "Show" : "Hide") + " Link Lines", event: () => this.doc.treeViewHideLinkLines = !this.doc.treeViewHideLinkLines, icon: "paint-brush" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: layoutItems, icon: "eye" }); } @@ -831,7 +831,7 @@ export class CollectionTreeView extends CollectionSubView this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), BoolCast(this.doc.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick, this.onChildClick, this.props.ignoreFields, true, BoolCast(this.props.Document.treeViewOpen)); - const hideTitle = this.props.treeViewHideTopDoc || this.doc.treeViewHideTopDoc; + const hideTitle = this.props.treeViewHideTopLevel || this.doc.treeViewHideTopLevel; return !childDocs ? (null) : (
      (Docu } } } else if (this.onClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself + const shiftKey = e.shiftKey; const func = () => this.onClickHandler.script.run({ this: this.layoutDoc, self: this.rootDoc, scriptContext: this.props.scriptContext, thisContainer: this.props.ContainingCollectionDoc, documentView: this, - shiftKey: e.shiftKey + shiftKey }, console.log); const clickFunc = () => { if (!Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-undo"] as Doc) && !Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-redo"] as Doc)) { -- cgit v1.2.3-70-g09d2 From ec89542cbd31aaff9d4f58e9e9bf045e934a8235 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 25 Aug 2020 18:13:39 -0400 Subject: changed system documents to act like dividers in tree views. removed some menu items in cases they don't apply. fixed ink selection to not use boudning box. --- src/client/util/CurrentUserUtils.ts | 19 +++-------- src/client/util/InteractionUtils.tsx | 2 +- src/client/views/ContextMenu.tsx | 2 +- src/client/views/InkingStroke.tsx | 7 ++-- .../views/collections/CollectionTreeView.scss | 9 ++++++ .../views/collections/CollectionTreeView.tsx | 11 ++++--- src/client/views/nodes/DocumentView.tsx | 37 +++++++++++----------- 7 files changed, 43 insertions(+), 44 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 4a51daa9f..e91cf118f 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -394,7 +394,7 @@ export class CurrentUserUtils { }[] { if (doc.emptyPresentation === undefined) { doc.emptyPresentation = Docs.Create.PresDocument(new List(), - { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true }); + { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true, cloneFieldFilter: new List(["system"]) }); ((doc.emptyPresentation as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptyCollection === undefined) { @@ -444,30 +444,18 @@ export class CurrentUserUtils { { toolTip: "Tap to create a cat image in a new pane, drag for a cat image", title: "Image", icon: "cat", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyImage as Doc }, { toolTip: "Tap to create a comparison box in a new pane, drag for a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyComparison as Doc, noviceMode: true }, { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc }, - // { title: "Drag a webcam", title: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' }, { toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true }, { toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc, noviceMode: true }, - - { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true }, + { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory))', drag: `Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true }, { toolTip: "Tap to create a search box in a new pane, drag for a search box", title: "Query", icon: "search", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySearch as Doc }, { toolTip: "Tap to create a scripting box in a new pane, drag for a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScript as Doc }, - // { title: "Drag an import folder", title: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, { toolTip: "Tap to create a mobile view in a new pane, drag for a mobile view", title: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc }, - // { title: "Drag an instance of the device collection", title: "Buxton", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.Buxton()' }, - // { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)', backgroundColor: "blue", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc }, - // { title: "use highlighter", icon: "highlighter", click: 'activateBrush(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc }, - // { title: "use stamp", icon: "stamp", click: 'activateStamp(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)', backgroundColor: "orange", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc }, - // { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this);', ischecked: `sameDocs(this.activeInkPen, this)`, backgroundColor: "pink", activeInkPen: doc }, - // { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activeInkPen = this;', ischecked: `sameDocs(this.activeInkPen, this)`, backgroundColor: "white", activeInkPen: doc }, { toolTip: "Tap to create a document previewer in a new pane, drag for a document previewer", title: "Prev", icon: "expand", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyDocHolder as Doc }, { toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", click: 'addOverlayWindow("ScriptingRepl", { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" })' }, - { toolTip: "Connect a Google Account", title: "Google Account", icon: "external-link-alt", click: 'GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(true)' }, ]; } - - // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static async setupCreatorButtons(doc: Doc) { let alreadyCreatedButtons: string[] = []; @@ -496,7 +484,8 @@ export class CurrentUserUtils { dragFactory, clickFactory, userDoc: noviceMode ? undefined as any : doc, - hidden: noviceMode ? undefined as any : ComputedField.MakeFunction("self.userDoc.noviceMode"), system: true + hidden: noviceMode ? undefined as any : ComputedField.MakeFunction("self.userDoc.noviceMode"), + system: true })); if (dragCreatorSet === undefined) { diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index bb58423c8..d1e656e3f 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -210,7 +210,7 @@ export namespace InteractionUtils { points={strpts} style={{ filter: drawHalo ? "url(#inkSelectionHalo)" : undefined, - fill: fill ? fill : "transparent", + fill: fill ? fill : "none", opacity: strokeWidth !== width ? 0.5 : undefined, pointerEvents: pevents as any, stroke: color ?? "rgb(0, 0, 0)", diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index cb34b8873..349fd077c 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -95,7 +95,7 @@ export class ContextMenu extends React.Component { } @action moveAfter(item: ContextMenuProps, after: ContextMenuProps) { - if (this.findByDescription(after.description)) { + if (after && this.findByDescription(after.description)) { const curInd = this._items.findIndex((i) => i.description === item.description); this._items.splice(curInd, 1); const afterInd = this._items.findIndex((i) => i.description === after.description); diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index b972d4e41..d47d0d90c 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -113,18 +113,18 @@ export class InkingStroke extends ViewBoxBaseComponent 1 && lineRgt - lineLft > 1, false); const hpoints = InteractionUtils.CreatePolyline(data, left, top, this.props.isSelected() && strokeWidth > 5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15), - StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"), + StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"), "none", "none", undefined, scaleX, scaleY, "", this.props.active() ? "visiblepainted" : "none", false, true); //points for adding const apoints = InteractionUtils.CreatePoints(data, left, top, strokeColor, strokeWidth, strokeWidth, - StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"), + StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"), StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker), StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false); @@ -208,6 +208,7 @@ export class InkingStroke extends ViewBoxBaseComponent FormatShapePane.Instance._controlBtn = !FormatShapePane.Instance._controlBtn), icon: "paint-brush" }); //cm.addItem({ description: "Format Shape...", event: this.formatShape, icon: "paint-brush" }); } }} diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index c9bf82406..f96a5c4f0 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -85,6 +85,15 @@ white-space: pre-wrap; min-width: 10px; } +.docContainer-system { + font-variant: all-small-caps; + border-radius: 5px; + background: grey; + color: white; + padding-left: 3px; + padding-right: 3px; + padding-bottom: 2px; +} .treeViewItem-openRight { display: none; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 585d1f775..83f212336 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -135,8 +135,9 @@ class TreeView extends React.Component { super(props); const titleScript = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); documentView.select();} `, { documentView: "any" }); const openScript = ScriptField.MakeScript(`openOnRight(self)`); - this._editTitleScript = titleScript && (() => titleScript); - this._openScript = openScript && (() => openScript); + const treeOpenScript = ScriptField.MakeScript(`self.treeViewOpen = !self.treeViewOpen`); + this._editTitleScript = !Doc.IsSystem(this.props.document) ? titleScript && (() => titleScript) : treeOpenScript && (() => treeOpenScript); + this._openScript = !Doc.IsSystem(this.props.document) ? openScript && (() => openScript) : undefined; if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false); } @@ -414,7 +415,7 @@ class TreeView extends React.Component { this._docRef.current?.ContentDiv && simulateMouseClick(this._docRef.current.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); } focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true); - contextMenuItems = () => [{ script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }, { script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }]; + contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : [{ script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }, { script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; truncateTitleWidth = () => NumCast(this.props.treeViewDoc.treeViewTruncateTitleWidth, 0); showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || ""); onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.editTitleScript)); @@ -479,7 +480,7 @@ class TreeView extends React.Component { ContainingCollectionDoc={this.props.containingCollection} />; return <> -
      { }} > {view}
      - {headerElements} + {Doc.IsSystem(this.doc) ? (null) : headerElements} ; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c8ac59bcd..56791fc81 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -105,17 +105,15 @@ export class DocumentView extends DocComponent(Docu private _lastTap: number = 0; private _doubleTap = false; private _mainCont = React.createRef(); - private _dropDisposer?: DragManager.DragDropDisposer; - private _showKPQuery: boolean = false; - private _queries: string = ""; private _titleRef = React.createRef(); + private _dropDisposer?: DragManager.DragDropDisposer; private _gestureEventDisposer?: GestureUtils.GestureEventDisposer; private _holdDisposer?: InteractionUtils.MultiTouchEventDisposer; protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; + private get active() { return SelectionManager.IsSelected(this, true) || this.props.parentActive(true); } public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive public get ContentDiv() { return this._mainCont.current; } - private get active() { return SelectionManager.IsSelected(this, true) || this.props.parentActive(true); } @computed get topMost() { return this.props.renderDepth === 0; } @computed get freezeDimensions() { return this.props.FreezeDimensions; } @computed get nativeWidth() { return NumCast(this.layoutDoc._nativeWidth, this.props.NativeWidth() || (this.freezeDimensions ? this.layoutDoc[WidthSym]() : 0)); } @@ -308,7 +306,7 @@ export class DocumentView extends DocComponent(Docu shiftKey: e.shiftKey }, console.log); func(); - } else { + } else if (!Doc.IsSystem(this.props.Document)) { UndoManager.RunInBatch(() => { let fullScreenDoc = this.props.Document; if (StrCast(this.props.Document.layoutKey) !== "layout_fullScreen" && this.props.Document.layout_fullScreen) { @@ -732,7 +730,7 @@ export class DocumentView extends DocComponent(Docu Cast(this.props.Document.contextMenuLabels, listSpec("string"), []).forEach((label, i) => cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" })); this.props.contextMenuItems?.().forEach(item => - cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" })); + item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" })); const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); const appearance = cm.findByDescription("UI Controls..."); @@ -743,21 +741,22 @@ export class DocumentView extends DocComponent(Docu const options = cm.findByDescription("Options..."); const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; - optionItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" }); + !this.props.treeViewDoc && this.props.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform && optionItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" }); !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" }); - - const existingOnClick = cm.findByDescription("OnClick..."); - const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; - onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); - onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); - onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); - onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" }); - !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("onRight", false, false), icon: "link" }); - onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" }); - onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" }); - onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" }); - !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, addDivider: true, subitems: onClicks, icon: "mouse-pointer" }); + if (!Doc.IsSystem(this.rootDoc) && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) { + const existingOnClick = cm.findByDescription("OnClick..."); + const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; + onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); + onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); + onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); + onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" }); + !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("onRight", false, false), icon: "link" }); + onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" }); + onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" }); + onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" }); + !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, addDivider: true, subitems: onClicks, icon: "mouse-pointer" }); + } const funcs: ContextMenuProps[] = []; if (this.layoutDoc.onDragStart) { -- cgit v1.2.3-70-g09d2 From 0e4da0ffd9ff7eaf571451d8b267c7e708e152d7 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 25 Aug 2020 22:24:27 -0400 Subject: changed treeViewHideTopLevel back to treeViewHideTitle. cleaned up some stuff. --- src/client/documents/Documents.ts | 9 ++-- src/client/util/CurrentUserUtils.ts | 10 ++-- src/client/util/SelectionManager.ts | 1 - src/client/views/EditableView.tsx | 2 +- src/client/views/MainView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 53 +++++++++++----------- src/client/views/collections/CollectionView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../formattedText/ProsemirrorExampleTransfer.ts | 4 +- src/fields/documentSchemas.ts | 1 + 10 files changed, 44 insertions(+), 42 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index cef7c5d4d..b8cac2beb 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -187,7 +187,7 @@ export interface DocumentOptions { cloneFieldFilter?: List; // fields not to copy when the document is cloned _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view - treeViewHideTopLevel?: boolean; // whether to hide the top document of a tree view + treeViewHideTitle?: boolean; // whether to hide the top document of a tree view treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items. treeViewOpen?: boolean; // whether this document is expanded in a tree view treeViewExpandedView?: string; // which field/thing is displayed when this item is opened in tree view @@ -333,7 +333,7 @@ export namespace Docs { }], [DocumentType.INK, { layout: { view: InkingStroke, dataField: defaultDataKey }, - options: { backgroundColor: "transparent" } + options: { _fontFamily: "cursive", backgroundColor: "transparent" } }], [DocumentType.SCREENSHOT, { layout: { view: ScreenshotBox, dataField: defaultDataKey }, @@ -683,7 +683,7 @@ export namespace Docs { export function LinkDocument(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, options: DocumentOptions = {}, id?: string) { const doc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, { dontRegisterChildViews: true, - isLinkButton: true, treeViewHideTopLevel: true, backgroundColor: "lightBlue", // lightBlue is default color for linking dot and link documents text comment area + isLinkButton: true, treeViewHideTitle: true, backgroundColor: "lightBlue", // lightBlue is default color for linking dot and link documents text comment area treeViewExpandedView: "fields", removeDropProperties: new List(["isBackground", "isLinkButton"]), ...options }, id); const linkDocProto = Doc.GetProto(doc); @@ -694,7 +694,7 @@ export namespace Docs { linkDocProto.anchor2_timecode = target.doc._currentTimecode || target.doc.displayTimecode; if (linkDocProto.linkBoxExcludedKeys === undefined) { - Cast(linkDocProto.proto, Doc, null).linkBoxExcludedKeys = new List(["treeViewExpandedView", "aliases", "treeViewHideTopLevel", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); + Cast(linkDocProto.proto, Doc, null).linkBoxExcludedKeys = new List(["treeViewExpandedView", "aliases", "treeViewHideTitle", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); Cast(linkDocProto.proto, Doc, null).layoutKey = undefined; } @@ -723,6 +723,7 @@ export namespace Docs { I._backgroundColor = "transparent"; I._width = options._width; I._height = options._height; + I._fontFamily = "cursive"; I.author = Doc.CurrentUserEmail; I.rotation = 0; I.data = new InkField(points); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index e91cf118f..435944a74 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -218,7 +218,7 @@ export class CurrentUserUtils { const shared = { _chromeStatus: "disabled", _autoHeight: true, _xMargin: 0 }; const detailViewOpts = { title: "detailView", _width: 300, _fontFamily: "Arial", _fontSize: "12pt" }; - const descriptionWrapperOpts = { title: "descriptions", _height: 300, _columnWidth: -1, treeViewHideTopLevel: true, _pivotField: "title", system: true }; + const descriptionWrapperOpts = { title: "descriptions", _height: 300, _columnWidth: -1, treeViewHideTitle: true, _pivotField: "title", system: true }; const descriptionWrapper = MasonryDocument([details, short, long], { ...shared, ...descriptionWrapperOpts }); descriptionWrapper._columnHeaders = new List([ @@ -726,7 +726,7 @@ export class CurrentUserUtils { if (doc.myDashboards === undefined) { doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Dashboards", _height: 400, - treeViewHideTopLevel: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); @@ -742,7 +742,7 @@ export class CurrentUserUtils { if (doc.myPresentations === undefined) { doc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Presentations", _height: 100, - treeViewHideTopLevel: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); @@ -760,7 +760,7 @@ export class CurrentUserUtils { if (doc.myInactiveDocs === undefined) { doc.myInactiveDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "Inactive", _height: 500, - treeViewHideTopLevel: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); @@ -776,7 +776,7 @@ export class CurrentUserUtils { doc.treeViewOpen = true; doc.treeViewExpandedView = "fields"; doc.myUserDoc = new PrefetchProxy(Docs.Create.TreeDocument([doc], { - treeViewHideTopLevel: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, title: "My UserDoc", + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, title: "My UserDoc", treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })) as any as Doc; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 35b82cc30..6d4f2c190 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -21,7 +21,6 @@ export namespace SelectionManager { } @action SelectDoc(docView: DocumentView, ctrlPressed: boolean): void { - // if doc is not in SelectedDocuments, add it if (!manager.SelectedDocuments.get(docView)) { if (!ctrlPressed) { diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 8b2fa9472..1b4b9a2be 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -151,7 +151,7 @@ export class EditableView extends React.Component { @action setIsFocused = (value: boolean) => { const wasFocused = this._editing; - //this._editing = value; + this._editing = value; return wasFocused !== this._editing; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 33e316dbe..cfa2534c9 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -293,7 +293,7 @@ export class MainView extends React.Component { const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); const copyDashboard = ScriptField.MakeScript(`copyDashboard()`); - const createDashboard = ScriptField.MakeScript(`createDashb oard()`); + const createDashboard = ScriptField.MakeScript(`createDashboard()`); dashboardDoc.contextMenuScripts = new List([toggleTheme!, toggleComic!, copyDashboard!, createDashboard!]); dashboardDoc.contextMenuLabels = new List(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Create Dashboard"]); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 83f212336..5a80541be 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -37,7 +37,6 @@ import { TraceMobx } from '../../../fields/util'; export interface TreeViewProps { document: Doc; dataDoc?: Doc; - libraryPath: Doc[] | undefined; containingCollection: Doc; prevSibling?: Doc; renderDepth: number; @@ -65,7 +64,6 @@ export interface TreeViewProps { onChildClick?: () => ScriptField; ignoreFields?: string[]; firstLevel: boolean; - forceOpen: boolean; } @observer @@ -99,7 +97,7 @@ class TreeView extends React.Component { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; } - @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen || this.props.forceOpen; } + @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen; } @computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.treeViewDefaultExpandedView); } @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); } @computed get dataDoc() { return this.doc[DataSym]; } @@ -119,7 +117,7 @@ class TreeView extends React.Component { Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey])); } - @undoBatch openRight = () => this.props.addDocTab(this.doc, "onRight", this.props.libraryPath); + @undoBatch openRight = () => this.props.addDocTab(this.doc, "onRight"); @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { return this.doc !== target && this.props.deleteDoc(doc) && addDoc(doc); } @@ -137,7 +135,7 @@ class TreeView extends React.Component { const openScript = ScriptField.MakeScript(`openOnRight(self)`); const treeOpenScript = ScriptField.MakeScript(`self.treeViewOpen = !self.treeViewOpen`); this._editTitleScript = !Doc.IsSystem(this.props.document) ? titleScript && (() => titleScript) : treeOpenScript && (() => treeOpenScript); - this._openScript = !Doc.IsSystem(this.props.document) ? openScript && (() => openScript) : undefined; + this._openScript = !Doc.IsSystem(this.props.document) && !this.props.treeViewDoc.treeViewOutlineMode ? openScript && (() => openScript) : undefined; if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false); } @@ -201,7 +199,7 @@ class TreeView extends React.Component { }} OnTab={undoBatch((shift?: boolean) => { shift ? this.props.outdentDocument?.() : this.props.indentDocument?.(); - setTimeout(() => Doc.SetInPlace(this.doc, "editTitle", "*", false), 0); + setTimeout(() => Doc.SetInPlace(this.doc, "editTitle", "*", false), 250); })} />) @@ -286,7 +284,7 @@ class TreeView extends React.Component { DocListCast(contents), this.props.treeViewDoc, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, false); + [...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false); } else { contentElement = { (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true), true); const docs = expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs; const sortKey = `${this.fieldKey}-sortAscending`; - return
        { + return
          { this.doc[sortKey] = (this.doc[sortKey] ? false : (this.doc[sortKey] === false ? undefined : true)); e.stopPropagation(); }}> @@ -337,7 +335,7 @@ class TreeView extends React.Component { this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, this.doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, false)} + [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false)}
        ; } else if (this.treeViewExpandedView === "fields") { return
          @@ -418,8 +416,8 @@ class TreeView extends React.Component { contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : [{ script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }, { script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; truncateTitleWidth = () => NumCast(this.props.treeViewDoc.treeViewTruncateTitleWidth, 0); showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || ""); - onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.editTitleScript)); - onChildDoubleClick = () => this._openScript?.() || ScriptCast(this.doc.editTitleScript); + onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); + onChildDoubleClick = () => this._openScript?.() || ScriptCast(this.doc.treeChildDoubleClick); /** * Renders the EditableView title element for placement into the tree. */ @@ -428,7 +426,7 @@ class TreeView extends React.Component { TraceMobx(); const headerElements = this.props.treeViewHideHeaderFields() ? (null) : <> - { this.showContextMenu(e); e.stopPropagation(); }} /> + { this.showContextMenu(e); e.stopPropagation(); }} /> { if (this.treeViewOpen) { @@ -450,7 +448,7 @@ class TreeView extends React.Component { Document={this.doc} DataDoc={undefined} treeViewDoc={this.props.treeViewDoc} - LibraryPath={this.props.libraryPath || emptyPath} + LibraryPath={emptyPath} addDocument={undefined} addDocTab={this.props.addDocTab} rootSelected={returnTrue} @@ -479,13 +477,15 @@ class TreeView extends React.Component { ContainingCollectionView={undefined} ContainingCollectionDoc={this.props.containingCollection} />; + const activeSel = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; + const pointerEvents = !this.props.active() && !SnappingManager.GetIsDragging() && activeSel?.props.treeViewDoc !== this.props.treeViewDoc ? "none" : undefined; return <>
          {view}
          @@ -507,7 +507,7 @@ class TreeView extends React.Component { } } } else this._editMaxWidth = ""; - return this.doc.treeViewHideTopLevel && this.props.firstLevel ? !this.treeViewOpen || this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent : + return this.doc.treeViewHideTitle && this.props.firstLevel ? this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent :
          this.props.active(true) && SelectionManager.DeselectAll()}>
        • { @@ -557,12 +557,10 @@ class TreeView extends React.Component { treeViewHideHeaderFields: () => boolean, treeViewPreventOpen: boolean, renderedIds: string[], - libraryPath: Doc[] | undefined, onCheckedClick: undefined | (() => ScriptField), onChildClick: undefined | (() => ScriptField), ignoreFields: string[] | undefined, firstLevel: boolean, - forceOpen: boolean ) { const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField); if (viewSpecScript) { @@ -644,7 +642,6 @@ class TreeView extends React.Component { return !(child instanceof Doc) ? (null) : { treeViewPreventOpen={treeViewPreventOpen} renderedIds={renderedIds} ignoreFields={ignoreFields} - firstLevel={firstLevel} - forceOpen={forceOpen} />; + firstLevel={firstLevel} />; }); } } export type collectionTreeViewProps = { - treeViewHideTopLevel?: boolean; + treeViewHideTitle?: boolean; treeViewHideHeaderFields?: boolean; onCheckedClick?: () => ScriptField; onChildClick?: () => ScriptField; @@ -755,7 +751,7 @@ export class CollectionTreeView extends CollectionSubView this.doc.treeViewPreventOpen = !this.doc.treeViewPreventOpen, icon: "paint-brush" }); layoutItems.push({ description: (this.doc.treeViewHideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.doc.treeViewHideHeaderFields = !this.doc.treeViewHideHeaderFields, icon: "paint-brush" }); - layoutItems.push({ description: (this.doc.treeViewHideTopLevel ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTopLevel = !this.doc.treeViewHideTopLevel, icon: "paint-brush" }); + layoutItems.push({ description: (this.doc.treeViewHideTitle ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTitle = !this.doc.treeViewHideTitle, icon: "paint-brush" }); layoutItems.push({ description: (this.doc.treeViewHideLinkLines ? "Show" : "Hide") + " Link Lines", event: () => this.doc.treeViewHideLinkLines = !this.doc.treeViewHideLinkLines, icon: "paint-brush" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: layoutItems, icon: "eye" }); } @@ -803,6 +799,9 @@ export class CollectionTreeView extends CollectionSubView UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.doc, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit" }); + onClicks.push({ + description: `${this.props.Document.treeViewOutlineMode ? "Delay " : "Immediate "} Title Editing`, event: () => UndoManager.RunInBatch(() => this.props.Document.treeViewOutlineMode = !this.props.Document.treeViewOutlineMode, "edit onCheckedClick"), icon: "edit" + }); !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" }); } outerXf = () => Utils.GetScreenTransform(this._mainEle!); @@ -830,9 +829,11 @@ export class CollectionTreeView extends CollectionSubView this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), - BoolCast(this.doc.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick, - this.onChildClick, this.props.ignoreFields, true, BoolCast(this.props.Document.treeViewOpen)); - const hideTitle = this.props.treeViewHideTopLevel || this.doc.treeViewHideTopLevel; + BoolCast(this.doc.treeViewPreventOpen), [], this.props.onCheckedClick, + this.onChildClick, this.props.ignoreFields, true); + const hideTitle = this.props.treeViewHideTitle || this.doc.treeViewHideTitle; + const activeSel = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; + const pointerEvents = !this.props.active() && !SnappingManager.GetIsDragging() && activeSel?.props.treeViewDoc !== this.props.Document ? "none" : undefined; return !childDocs ? (null) : (
          this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index bf81e4509..a7361bc9c 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -550,7 +550,7 @@ export class CollectionView extends Touchable this.showTimeline = !this.showTimeline), icon: "eye" }); this.props.ContainingCollectionView && - optionItems.push({ description: "Undo Collection", event: this.promoteCollection, icon: "table" }); + optionItems.push({ description: "Move Items Out of Collection", event: this.promoteCollection, icon: "table" }); optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" }); optionItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" }); if (!Doc.UserDoc().noviceMode) { diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts index 0eb675b4e..a65eea50f 100644 --- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts +++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts @@ -143,7 +143,7 @@ export function buildKeymap>(schema: S, props: any, mapKey const layoutKey = StrCast(originalDoc.layoutKey); const newDoc = Doc.MakeCopy(originalDoc, true); newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = undefined; - newDoc.y = NumCast(originalDoc.y) + NumCast(originalDoc._height) + 10; + newDoc.x = NumCast(originalDoc.x) + NumCast(originalDoc._width) + 10; if (layoutKey !== "layout" && originalDoc[layoutKey] instanceof Doc) { newDoc[layoutKey] = originalDoc[layoutKey]; } @@ -168,7 +168,7 @@ export function buildKeymap>(schema: S, props: any, mapKey const layoutKey = StrCast(originalDoc.layoutKey); const newDoc = Doc.MakeCopy(originalDoc, true); newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = undefined; - newDoc.x = NumCast(originalDoc.x) + NumCast(originalDoc._width) + 10; + newDoc.y = NumCast(originalDoc.y) + NumCast(originalDoc._height) + 10; if (layoutKey !== "layout" && originalDoc[layoutKey] instanceof Doc) { newDoc[layoutKey] = originalDoc[layoutKey]; } diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index c669b1185..a83fec4ab 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -87,6 +87,7 @@ export const documentSchema = createSchema({ treeViewLockExpandedView: "boolean", // whether the expanded view can be changed treeViewDefaultExpandedView: "string", // name of field whose contents are displayed by default treeViewPreventOpen: "boolean", // ignores the treeViewOpen flag (for allowing a view to not be slaved to other views of the document) + treeViewOutlineMode: "boolean", // whether tree view is an outline and clicks edit document titles immediately since double-click opening is turned off // interaction and linking properties ignoreClick: "boolean", // whether documents ignores input clicks (but does not ignore manipulation and other events) -- cgit v1.2.3-70-g09d2 From a2fb0c0483b77730a43f91e8a967f216bde51144 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Aug 2020 00:07:20 -0400 Subject: fixed immediate Title Editing of tree views --- src/client/views/collections/CollectionTreeView.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 5a80541be..a7c414bcc 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -135,7 +135,7 @@ class TreeView extends React.Component { const openScript = ScriptField.MakeScript(`openOnRight(self)`); const treeOpenScript = ScriptField.MakeScript(`self.treeViewOpen = !self.treeViewOpen`); this._editTitleScript = !Doc.IsSystem(this.props.document) ? titleScript && (() => titleScript) : treeOpenScript && (() => treeOpenScript); - this._openScript = !Doc.IsSystem(this.props.document) && !this.props.treeViewDoc.treeViewOutlineMode ? openScript && (() => openScript) : undefined; + this._openScript = !Doc.IsSystem(this.props.document) ? openScript && (() => openScript) : undefined; if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false); } @@ -199,7 +199,7 @@ class TreeView extends React.Component { }} OnTab={undoBatch((shift?: boolean) => { shift ? this.props.outdentDocument?.() : this.props.indentDocument?.(); - setTimeout(() => Doc.SetInPlace(this.doc, "editTitle", "*", false), 250); + setTimeout(() => Doc.SetInPlace(this.doc, "editTitle", "*", false), 0); })} />) @@ -417,7 +417,7 @@ class TreeView extends React.Component { truncateTitleWidth = () => NumCast(this.props.treeViewDoc.treeViewTruncateTitleWidth, 0); showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || ""); onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); - onChildDoubleClick = () => this._openScript?.() || ScriptCast(this.doc.treeChildDoubleClick); + onChildDoubleClick = () => (!this.props.treeViewDoc.treeViewOutlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); /** * Renders the EditableView title element for placement into the tree. */ -- cgit v1.2.3-70-g09d2 From 8b995364cf2a1fab24f72827daf6c7500024dfa4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Aug 2020 00:50:33 -0400 Subject: more efficient way to update tree view active() flag --- .../views/collections/CollectionTreeView.tsx | 29 +++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a7c414bcc..5b2957654 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -64,6 +64,7 @@ export interface TreeViewProps { onChildClick?: () => ScriptField; ignoreFields?: string[]; firstLevel: boolean; + whenActiveChanged: (isActive: boolean) => void; } @observer @@ -284,7 +285,7 @@ class TreeView extends React.Component { DocListCast(contents), this.props.treeViewDoc, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false); + [...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, this.props.whenActiveChanged); } else { contentElement = { this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false)} + [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, this.props.whenActiveChanged)}
        ; } else if (this.treeViewExpandedView === "fields") { return
          @@ -469,7 +470,7 @@ class TreeView extends React.Component { renderDepth={1} focus={returnTrue} parentActive={returnTrue} - whenActiveChanged={emptyFunction} + whenActiveChanged={this.props.whenActiveChanged} bringToFront={emptyFunction} dontRegisterView={BoolCast(this.props.treeViewDoc.dontRegisterChildViews)} docFilters={returnEmptyFilter} @@ -477,15 +478,13 @@ class TreeView extends React.Component { ContainingCollectionView={undefined} ContainingCollectionDoc={this.props.containingCollection} />; - const activeSel = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; - const pointerEvents = !this.props.active() && !SnappingManager.GetIsDragging() && activeSel?.props.treeViewDoc !== this.props.treeViewDoc ? "none" : undefined; return <>
          {view}
          @@ -561,6 +560,7 @@ class TreeView extends React.Component { onChildClick: undefined | (() => ScriptField), ignoreFields: string[] | undefined, firstLevel: boolean, + whenActiveChanged: (isActive: boolean) => void ) { const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField); if (viewSpecScript) { @@ -669,7 +669,8 @@ class TreeView extends React.Component { treeViewPreventOpen={treeViewPreventOpen} renderedIds={renderedIds} ignoreFields={ignoreFields} - firstLevel={firstLevel} />; + firstLevel={firstLevel} + whenActiveChanged={whenActiveChanged} />; }); } } @@ -819,6 +820,11 @@ export class CollectionTreeView extends CollectionSubView { return this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick); } + _isChildActive = false; + whenActiveChanged = (isActive: boolean) => { + this.props.whenActiveChanged(this._isChildActive = isActive); + } + active = (outsideReaction: boolean | undefined) => { return this.props.active(outsideReaction) || this._isChildActive; } render() { TraceMobx(); if (!(this.doc instanceof Doc)) return (null); @@ -828,12 +834,11 @@ export class CollectionTreeView extends CollectionSubView this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), + this.outerXf, this.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), BoolCast(this.doc.treeViewPreventOpen), [], this.props.onCheckedClick, - this.onChildClick, this.props.ignoreFields, true); + this.onChildClick, this.props.ignoreFields, true, this.whenActiveChanged); const hideTitle = this.props.treeViewHideTitle || this.doc.treeViewHideTitle; - const activeSel = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; - const pointerEvents = !this.props.active() && !SnappingManager.GetIsDragging() && activeSel?.props.treeViewDoc !== this.props.Document ? "none" : undefined; + return !childDocs ? (null) : (
          this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} -- cgit v1.2.3-70-g09d2 From d2e29bc56a8c0bc8bee0d1ceb28726b3caabdb36 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Aug 2020 01:50:05 -0400 Subject: fix so that tabbing tree view items works when treview aliases (eg minimap) are displayed. just doesn't work if the document is open more than once in the same treeview --- .../views/collections/CollectionTreeView.tsx | 37 +++++++++++----------- 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 5b2957654..918377052 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -11,7 +11,6 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Ty import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, simulateMouseClick, Utils, returnEmptyFilter, returnEmptyDoclist } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from "../../documents/DocumentTypes"; -import { DocumentManager } from '../../util/DocumentManager'; import { SnappingManager } from '../../util/SnappingManager'; import { DragManager, dropActionType } from "../../util/DragManager"; import { Scripting } from '../../util/Scripting'; @@ -54,7 +53,7 @@ export interface TreeViewProps { ScreenToLocalTransform: () => Transform; backgroundColor?: (doc: Doc, renderDepth: number) => string | undefined; outerXf: () => { translateX: number, translateY: number }; - treeViewDoc: Doc; + treeView: CollectionTreeView; parentKey: string; active: (outsideReaction?: boolean) => boolean; treeViewHideHeaderFields: () => boolean; @@ -200,13 +199,13 @@ class TreeView extends React.Component { }} OnTab={undoBatch((shift?: boolean) => { shift ? this.props.outdentDocument?.() : this.props.indentDocument?.(); - setTimeout(() => Doc.SetInPlace(this.doc, "editTitle", "*", false), 0); + setTimeout(() => Doc.SetInPlace(this.doc, "editTitle", `${this.props.treeView._uniqueId}`, false), 0); })} />) preTreeDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => { const dragData = de.complete.docDragData; - dragData && (dragData.dropAction = this.props.treeViewDoc === dragData.treeViewDoc ? "same" : dragData.dropAction); + dragData && (dragData.dropAction = this.props.treeView.props.Document === dragData.treeViewDoc ? "same" : dragData.dropAction); } @undoBatch @@ -282,7 +281,7 @@ class TreeView extends React.Component { const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce( (flg, doc) => flg && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true), true); contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : - DocListCast(contents), this.props.treeViewDoc, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, + DocListCast(contents), this.props.treeView, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, [...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, this.props.whenActiveChanged); @@ -332,7 +331,7 @@ class TreeView extends React.Component { e.stopPropagation(); }}> {!docs ? (null) : - TreeView.GetChildElements(docs, this.props.treeViewDoc, this.layoutDoc, + TreeView.GetChildElements(docs, this.props.treeView, this.layoutDoc, this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, @@ -391,7 +390,7 @@ class TreeView extends React.Component { this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc, heading: this.props.containingCollection.title, checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? undefined : "check", - containingTreeView: this.props.treeViewDoc, + containingTreeView: this.props.treeView, }, console.log); } else { this.treeViewOpen = !this.treeViewOpen; @@ -413,12 +412,13 @@ class TreeView extends React.Component { showContextMenu = (e: React.MouseEvent) => { this._docRef.current?.ContentDiv && simulateMouseClick(this._docRef.current.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); } - focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true); contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : [{ script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }, { script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; - truncateTitleWidth = () => NumCast(this.props.treeViewDoc.treeViewTruncateTitleWidth, 0); - showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || ""); + truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, 0); + @computed get showTitleEdit() { + return ["*", this._uniqueId, this.props.treeView._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || ""); + } onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); - onChildDoubleClick = () => (!this.props.treeViewDoc.treeViewOutlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); + onChildDoubleClick = () => (!this.props.treeView.props.Document.treeViewOutlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); /** * Renders the EditableView title element for placement into the tree. */ @@ -443,12 +443,12 @@ class TreeView extends React.Component { {this.treeViewExpandedView} ; - const view = this.showTitleEdit() ? this.editableView("title") : + const view = this.showTitleEdit ? this.editableView("title") : { parentActive={returnTrue} whenActiveChanged={this.props.whenActiveChanged} bringToFront={emptyFunction} - dontRegisterView={BoolCast(this.props.treeViewDoc.dontRegisterChildViews)} + dontRegisterView={BoolCast(this.props.treeView.props.Document.dontRegisterChildViews)} docFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} ContainingCollectionView={undefined} @@ -495,7 +495,7 @@ class TreeView extends React.Component { render() { TraceMobx(); const sorting = this.doc[`${this.fieldKey}-sortAscending`]; - if (this.showTitleEdit()) { // find containing CollectionTreeView and set our maximum width so the containing tree view won't have to scroll + if (this.showTitleEdit) { // find containing CollectionTreeView and set our maximum width so the containing tree view won't have to scroll let par: any = this._header?.current; if (par) { while (par && par.className !== "collectionTreeView-dropTarget") par = par.parentNode; @@ -534,7 +534,7 @@ class TreeView extends React.Component { } public static GetChildElements( childDocs: Doc[], - treeViewDoc: Doc, + treeView: CollectionTreeView, containingCollection: Doc, dataDoc: Doc | undefined, key: string, @@ -644,7 +644,7 @@ class TreeView extends React.Component { dataDoc={pair.data} containingCollection={containingCollection} prevSibling={docs[i]} - treeViewDoc={treeViewDoc} + treeView={treeView} key={child[Id]} indentDocument={indent} outdentDocument={outdent} @@ -687,6 +687,7 @@ export class CollectionTreeView extends CollectionSubView this.addDoc(doc, relativeTo, before); const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(d, target, addDoc); const childDocs = this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs; - const childElements = childDocs && TreeView.GetChildElements(childDocs, this.doc, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, + const childElements = childDocs && TreeView.GetChildElements(childDocs, this, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.outerXf, this.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), BoolCast(this.doc.treeViewPreventOpen), [], this.props.onCheckedClick, -- cgit v1.2.3-70-g09d2 From 6471ccff7dd145d3725492ccccaecc6035e851f2 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Aug 2020 02:30:44 -0400 Subject: fixed warnings. fixed url / annoation updating when navigating web pages. --- src/client/views/collections/CollectionMenu.tsx | 6 +++--- src/client/views/collections/CollectionSchemaCells.tsx | 6 +++--- src/client/views/collections/CollectionTreeView.tsx | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 2f257d00b..5f40ac59c 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -725,6 +725,8 @@ export class CollectionFreeFormViewChrome extends React.Component([]); } } @@ -751,9 +753,7 @@ export class CollectionFreeFormViewChrome extends React.Component([]); + this._url = url; } } } catch (e) { diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 95f425524..18ca29aaa 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -169,7 +169,7 @@ export class CollectionSchemaCell extends React.Component { const targetContext = aliasdoc.length <= 0 ? undefined : Cast(aliasdoc[0].context, Doc, null); DocumentManager.Instance.jumpToDocument(this._rowDoc, false, () => undefined, targetContext); } - }; + } renderCellWithType(type: string | undefined) { const dragRef: React.RefObject = React.createRef(); @@ -330,7 +330,7 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell { componentWillUnmount() { this.onBlur(); } - onBlur = () => { this._overlayDisposer?.(); } + onBlur = () => { this._overlayDisposer?.(); }; onFocus = () => { this.onBlur(); this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); @@ -443,7 +443,7 @@ export class CollectionSchemaListCell extends CollectionSchemaCell { } render() { - let link = false; + const link = false; const reference = React.createRef(); if (this._optionsList?.length) { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 918377052..5099f0022 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -825,7 +825,7 @@ export class CollectionTreeView extends CollectionSubView { this.props.whenActiveChanged(this._isChildActive = isActive); } - active = (outsideReaction: boolean | undefined) => { return this.props.active(outsideReaction) || this._isChildActive; } + active = (outsideReaction: boolean | undefined) => this.props.active(outsideReaction) || this._isChildActive; render() { TraceMobx(); if (!(this.doc instanceof Doc)) return (null); -- cgit v1.2.3-70-g09d2 From 022e36458815b9fd4ce79bea3ac1ae158a0c9463 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Aug 2020 10:25:37 -0400 Subject: added dropdown dashboards input at top left + new & snapshot --- src/client/util/CurrentUserUtils.ts | 89 +++++++++++++++++++++- src/client/util/History.ts | 4 +- src/client/views/MainView.tsx | 89 ++-------------------- .../views/collections/CollectionDockingView.tsx | 8 +- .../views/collections/CollectionTreeView.tsx | 4 +- src/client/views/search/SearchBox.scss | 50 +++++++++++- src/client/views/search/SearchBox.tsx | 28 +++++-- 7 files changed, 171 insertions(+), 101 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 435944a74..a76aa0dee 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1,4 +1,4 @@ -import { computed, observable, reaction } from "mobx"; +import { computed, observable, reaction, action } from "mobx"; import * as rp from 'request-promise'; import { Utils } from "../../Utils"; import { DocServer } from "../DocServer"; @@ -24,6 +24,8 @@ import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMu import { LabelBox } from "../views/nodes/LabelBox"; import { LinkManager } from "./LinkManager"; import { Id } from "../../fields/FieldSymbols"; +import { HistoryUtil } from "./History"; +import { CollectionDockingView } from "../views/collections/CollectionDockingView"; export class CurrentUserUtils { private static curr_id: string; @@ -730,7 +732,7 @@ export class CurrentUserUtils { treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); - const newDashboard = ScriptField.MakeScript(`createNewDashboard()`); + const newDashboard = ScriptField.MakeScript(`createNewDashboard(Doc.UserDoc())`); (doc.myDashboards as any as Doc).contextMenuScripts = new List([newDashboard!]); (doc.myDashboards as any as Doc).contextMenuLabels = new List(["Create New Dashboard"]); } @@ -976,9 +978,90 @@ export class CurrentUserUtils { } }); } + + public static _urlState: HistoryUtil.DocUrl; + + public static openDashboard = (userDoc: Doc, doc: Doc, fromHistory = false) => { + CurrentUserUtils.MainDocId = doc[Id]; + + if (doc) { // this has the side-effect of setting the main container since we're assigning the active/guest dashboard + !("presentationView" in doc) && (doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })])); + userDoc ? (userDoc.activeDashboard = doc) : (CurrentUserUtils.GuestDashboard = doc); + } + const state = CurrentUserUtils._urlState; + if (state.sharing === true && !userDoc) { + DocServer.Control.makeReadOnly(); + } else { + fromHistory || HistoryUtil.pushState({ + type: "doc", + docId: doc[Id], + readonly: state.readonly, + nro: state.nro, + sharing: false, + }); + if (state.readonly === true || state.readonly === null) { + DocServer.Control.makeReadOnly(); + } else if (state.safe) { + if (!state.nro) { + DocServer.Control.makeReadOnly(); + } + CollectionView.SetSafeMode(true); + } else if (state.nro || state.nro === null || state.readonly === false) { + } else if (doc.readOnly) { + DocServer.Control.makeReadOnly(); + } else { + DocServer.Control.makeEditable(); + } + } + + return true; + } + + public static snapshotDashboard = (userDoc: Doc) => { + const activeDashboard = Cast(userDoc.activeDashboard, Doc, null); + CollectionDockingView.Copy(activeDashboard).then(copy => { + Doc.AddDocToList(Cast(userDoc.myDashboards, Doc, null), "data", copy); + // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) + setTimeout(() => CurrentUserUtils.openDashboard(userDoc, copy), 0); + }); + } + + public static createNewDashboard = async (userDoc: Doc, id?: string) => { + const myPresentations = userDoc.myPresentations as Doc; + const presentation = Doc.MakeCopy(userDoc.emptyPresentation as Doc, true); + const dashboards = Cast(userDoc.myDashboards, Doc) as Doc; + const dashboardCount = DocListCast(dashboards.data).length + 1; + const emptyPane = Cast(userDoc.emptyPane, Doc, null); + emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; + const freeformOptions: DocumentOptions = { + x: 0, + y: 400, + _width: 1500, + _height: 1000, + title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`, + }; + const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); + const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row"); + Doc.AddDocToList(myPresentations, "data", presentation); + userDoc.activePresentation = presentation; + const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); + const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); + const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`); + const createDashboard = ScriptField.MakeScript(`createNewDashboard()`); + dashboardDoc.contextMenuScripts = new List([toggleTheme!, toggleComic!, snapshotDashboard!, createDashboard!]); + dashboardDoc.contextMenuLabels = new List(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Create Dashboard"]); + + Doc.AddDocToList(dashboards, "data", dashboardDoc); + // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) + setTimeout(() => { + CurrentUserUtils.openDashboard(userDoc, dashboardDoc); + }, 0); + } } -Scripting.addGlobal(function createNewDashboard() { return MainView.Instance.createNewDashboard(); }, +Scripting.addGlobal(function snapshotDashboard() { CurrentUserUtils.snapshotDashboard(Doc.UserDoc()); }, + "creates a snapshot copy of a dashboard"); +Scripting.addGlobal(function createNewDashboard() { return CurrentUserUtils.createNewDashboard(Doc.UserDoc()); }, "creates a new dashboard when called"); Scripting.addGlobal(function createNewPresentation() { return MainView.Instance.createNewPresentation(); }, "creates a new presentation when called"); diff --git a/src/client/util/History.ts b/src/client/util/History.ts index cab682ac7..cbe36b401 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -1,8 +1,8 @@ import { Doc } from "../../fields/Doc"; import { DocServer } from "../DocServer"; -import { MainView } from "../views/MainView"; import * as qs from 'query-string'; import { Utils, OmitKeys } from "../../Utils"; +import { CurrentUserUtils } from "./CurrentUserUtils"; export namespace HistoryUtil { export interface DocInitializerList { @@ -197,7 +197,7 @@ export namespace HistoryUtil { await Promise.all(Object.keys(init).map(id => initDoc(id, init[id]))); } if (field instanceof Doc) { - MainView.Instance.openDashboard(field, true); + CurrentUserUtils.openDashboard(Doc.UserDoc(), field, true); } } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cfa2534c9..d107b74f0 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -70,7 +70,6 @@ import "./MainView.scss"; export class MainView extends React.Component { public static Instance: MainView; private _buttonBarHeight = 36; - private _urlState: HistoryUtil.DocUrl; private _docBtnRef = React.createRef(); private _mainViewRef = React.createRef(); @@ -145,7 +144,7 @@ export class MainView extends React.Component { super(props); MainView.Instance = this; this.sidebarContent.proto = undefined; - this._urlState = HistoryUtil.parseUrl(window.location) || {} as any; + CurrentUserUtils._urlState = HistoryUtil.parseUrl(window.location) || {} as any; // causes errors to be generated when modifying an observable outside of an action CurrentUserUtils.propertiesWidth = 0; @@ -233,11 +232,11 @@ export class MainView extends React.Component { if (received && !this.userDoc) { reaction( () => CurrentUserUtils.GuestTarget, - target => target && this.createNewDashboard(), + target => target && CurrentUserUtils.createNewDashboard(Doc.UserDoc()), { fireImmediately: true } ); } else { - if (received && this._urlState.sharing) { + if (received && CurrentUserUtils._urlState.sharing) { reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized, initialized => initialized && received && DocServer.GetRefField(received).then(docField => { if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) { @@ -248,9 +247,9 @@ export class MainView extends React.Component { } const doc = this.userDoc && await Cast(this.userDoc.activeDashboard, Doc); if (doc) { - this.openDashboard(doc); + CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); } else { - this.createNewDashboard(); + CurrentUserUtils.createNewDashboard(Doc.UserDoc()); } } } @@ -271,73 +270,6 @@ export class MainView extends React.Component { Doc.AddDocToList(myPresentations, "data", pres); } - @action - createNewDashboard = async (id?: string) => { - const myPresentations = Doc.UserDoc().myPresentations as Doc; - const presentation = Doc.MakeCopy(Doc.UserDoc().emptyPresentation as Doc, true); - const dashboards = Cast(this.userDoc.myDashboards, Doc) as Doc; - const dashboardCount = DocListCast(dashboards.data).length + 1; - const emptyPane = Cast(this.userDoc.emptyPane, Doc, null); - emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; - const freeformOptions: DocumentOptions = { - x: 0, - y: 400, - _width: this._panelWidth * .7 - this.propertiesWidth() * 0.7, - _height: this._panelHeight, - title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`, - }; - const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); - const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row"); - Doc.AddDocToList(myPresentations, "data", presentation); - Doc.UserDoc().activePresentation = presentation; - const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); - const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); - const copyDashboard = ScriptField.MakeScript(`copyDashboard()`); - const createDashboard = ScriptField.MakeScript(`createDashboard()`); - dashboardDoc.contextMenuScripts = new List([toggleTheme!, toggleComic!, copyDashboard!, createDashboard!]); - dashboardDoc.contextMenuLabels = new List(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Create Dashboard"]); - - Doc.AddDocToList(dashboards, "data", dashboardDoc); - // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) - setTimeout(() => this.openDashboard(dashboardDoc), 0); - } - - @action - openDashboard = (doc: Doc, fromHistory = false) => { - CurrentUserUtils.MainDocId = doc[Id]; - - if (doc) { // this has the side-effect of setting the main container since we're assigning the active/guest dashboard - !("presentationView" in doc) && (doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })])); - this.userDoc ? (this.userDoc.activeDashboard = doc) : (CurrentUserUtils.GuestDashboard = doc); - } - const state = this._urlState; - if (state.sharing === true && !this.userDoc) { - DocServer.Control.makeReadOnly(); - } else { - fromHistory || HistoryUtil.pushState({ - type: "doc", - docId: doc[Id], - readonly: state.readonly, - nro: state.nro, - sharing: false, - }); - if (state.readonly === true || state.readonly === null) { - DocServer.Control.makeReadOnly(); - } else if (state.safe) { - if (!state.nro) { - DocServer.Control.makeReadOnly(); - } - CollectionView.SetSafeMode(true); - } else if (state.nro || state.nro === null || state.readonly === false) { - } else if (doc.readOnly) { - DocServer.Control.makeReadOnly(); - } else { - DocServer.Control.makeEditable(); - } - } - - return true; - } onDrop = (e: React.DragEvent) => { e.preventDefault(); @@ -454,7 +386,7 @@ export class MainView extends React.Component { flyoutWidthFunc = () => this.flyoutWidth; addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => { return where === "close" ? CollectionDockingView.CloseRightSplit(doc) : - doc.dockingConfig ? this.openDashboard(doc) : + doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : CollectionDockingView.AddRightSplit(doc, libraryPath); } sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0) - Number(SEARCH_PANEL_HEIGHT.replace("px", "")), 1); @@ -998,14 +930,5 @@ export class MainView extends React.Component { } Scripting.addGlobal(function selectMainMenu(doc: Doc, title: string) { MainView.Instance.selectMenu(doc); }); Scripting.addGlobal(function toggleComicMode() { Doc.UserDoc().fontFamily = "Comic Sans MS"; Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; }); -Scripting.addGlobal(function copyDashboard() { - const activeDashboard = Cast(Doc.UserDoc().activeDashboard, Doc, null); - CollectionDockingView.Copy(activeDashboard).then(copy => { - Doc.AddDocToList(Cast(Doc.UserDoc().myDashboards, Doc, null), "data", copy); - // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) - setTimeout(() => MainView.Instance.openDashboard(copy), 0); - }); -}); -Scripting.addGlobal(function createDashboard() { MainView.Instance.createNewDashboard(); }); Scripting.addGlobal(function importDocument() { return MainView.Instance.importDocument(); }, "imports files from device directly into the import sidebar"); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index e7f54ff86..dfefd645a 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -25,7 +25,6 @@ import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoBatch } from "../../util/UndoManager"; -import { MainView } from '../MainView'; import { DocumentView } from "../nodes/DocumentView"; import { PresBox } from '../nodes/PresBox'; import "./CollectionDockingView.scss"; @@ -34,6 +33,7 @@ import { SubCollectionViewProps, CollectionSubView } from "./CollectionSubView"; import { CollectionViewType } from './CollectionView'; import { DockingViewButtonSelector } from './ParentDocumentSelector'; import React = require("react"); +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -87,7 +87,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { @action public OpenFullScreen(docView: DocumentView, libraryPath?: Doc[]) { if (docView.props.Document._viewType === CollectionViewType.Docking && docView.props.Document.layoutKey === "layout") { - return MainView.Instance.openDashboard(docView.props.Document); + return CurrentUserUtils.openDashboard(Doc.UserDoc(), docView.props.Document); } const document = Doc.MakeAlias(docView.props.Document); const newItemStackConfig = { @@ -188,7 +188,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { @action public static AddRightSplit(document: Doc, libraryPath?: Doc[]) { if (!CollectionDockingView.Instance) return false; - if (document._viewType === CollectionViewType.Docking) return MainView.Instance.openDashboard(document); + if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document); const instance = CollectionDockingView.Instance; const newItemStackConfig = { type: 'stack', @@ -864,7 +864,7 @@ export class DockedFrameRenderer extends React.Component { addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => { SelectionManager.DeselectAll(); if (doc._viewType === CollectionViewType.Docking) { - return MainView.Instance.openDashboard(doc); + return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc); } else if (location === "onRight") { return CollectionDockingView.AddRightSplit(doc, libraryPath); } else if (location === "close") { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 5099f0022..d7f0f8e14 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -20,7 +20,6 @@ import { undoBatch, UndoManager } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from "../EditableView"; -import { MainView } from '../MainView'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; import { DocumentView } from '../nodes/DocumentView'; import { ImageBox } from '../nodes/ImageBox'; @@ -32,6 +31,7 @@ import { CollectionViewType } from './CollectionView'; import React = require("react"); import { makeTemplate } from '../../util/DropConverter'; import { TraceMobx } from '../../../fields/util'; +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; export interface TreeViewProps { document: Doc; @@ -739,7 +739,7 @@ export class CollectionTreeView extends CollectionSubView { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myDashboards) { - ContextMenu.Instance.addItem({ description: "Create Dashboard", event: () => MainView.Instance.createNewDashboard(), icon: "plus" }); + ContextMenu.Instance.addItem({ description: "Create Dashboard", event: () => CurrentUserUtils.createNewDashboard(Doc.UserDoc()), icon: "plus" }); ContextMenu.Instance.addItem({ description: "Delete Dashboard", event: () => this.remove(this.doc), icon: "minus" }); e.stopPropagation(); e.preventDefault(); diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index b5557e0d9..aa5180c96 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -6,23 +6,69 @@ flex-direction: column; width: 100%; height: 100%; - position: absolute; + position: relative; font-size: 10px; line-height: 1; overflow-y: auto; overflow-x: visible; background: lightgrey; + overflow: visible; + z-index: 10000; + .searchBox-lozenge-user, + .searchBox-lozenge-dashboard, .searchBox-lozenge { background-color: #313131; border-radius: 5px; - height: 15px; + height: 18px; padding: 4px; box-shadow: lightgrey 0.15em 0.15em 0.1em; margin: 2px; margin-bottom: 4px; border-top: dimgrey 1px solid; border-left: dimgrey 1px solid; + display: flex; + .searchBox-logoff, + .searchBox-dashboards { + border-radius: 3px; + background: olivedrab; + color: white; + position: relative; + display: none; + margin-left: 3px; + padding-left: 2px; + padding-right: 2px; + padding-bottom: 11px; + cursor: default; + } + .searchBox-logoff { + background: red; + } + + .searchBox-dashSelect{ + background-color: black; + color: white; + font-size: 9; + margin-right: 6; + border-radius: 5px; + position: relative; + height: 15px; + transform: translate(0,-3px); + + &:hover { + cursor: pointer; + } + } + } + .searchBox-lozenge-user:hover { + .searchBox-logoff { + display:inline-block; + } + } + .searchBox-lozenge-dashboard:hover { + .searchBox-dashboards { + display:inline-block; + } } } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 5739c2a67..7e233ecbb 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -5,14 +5,15 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc'; import { documentSchema } from "../../../fields/documentSchemas"; -import { Id, Copy } from '../../../fields/FieldSymbols'; +import { Copy, Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { createSchema, listSpec, makeInterface } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; -import { returnFalse, returnZero, setupMoveUpEvents, emptyFunction } from '../../../Utils'; +import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DocumentType } from "../../documents/DocumentTypes"; +import { CurrentUserUtils } from "../../util/CurrentUserUtils"; import { SetupDrag } from '../../util/DragManager'; import { SearchUtil } from '../../util/SearchUtil'; import { Transform } from '../../util/Transform'; @@ -22,6 +23,7 @@ import { CollectionViewType } from '../collections/CollectionView'; import { ViewBoxBaseComponent } from "../DocComponent"; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./SearchBox.scss"; +import { undoBatch } from "../../util/UndoManager"; export const searchSchema = createSchema({ Document: Doc }); @@ -485,19 +487,35 @@ export class SearchBox extends ViewBoxBaseComponent(docsForFilter) : undefined; collectionView.props.Document._docFilters = docsForFilter?.length && docFilters?.length ? new List(docFilters) : undefined; } + } + showLogout = () => { + } render() { + const myDashboards = DocListCast(Cast(Doc.UserDoc().myDashboards, Doc, null).data); return (
          -
          +
          {`${Doc.CurrentUserEmail}`} +
          window.location.assign(Utils.prepend("/logout"))}> + Logoff +
          {`UI project`}
          -
          - {`âž± ${Cast(Doc.UserDoc().activeDashboard, Doc, null)?.title}`} +
          + +
          CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}> + New +
          +
          CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}> + Snapshot +
          -- cgit v1.2.3-70-g09d2 From 3eac88792e7b11f731aac9270a918b31c58ec83e Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 27 Aug 2020 12:51:45 -0400 Subject: switched back to recentlyClosed from inactive. fixed adding tag to multiple document seleciton. --- src/client/util/CurrentUserUtils.ts | 12 ++++++------ src/client/views/DocComponent.tsx | 2 +- src/client/views/collections/CollectionDockingView.tsx | 4 ++-- src/client/views/collections/CollectionTreeView.tsx | 4 ++-- src/client/views/collections/CollectionView.tsx | 2 +- .../collections/collectionFreeForm/PropertiesView.tsx | 6 +++--- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 15 --------------- 7 files changed, 15 insertions(+), 30 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index a76aa0dee..ef7beb030 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -508,7 +508,7 @@ export class CurrentUserUtils { this.setupSharingSidebar(doc); // sets up the right sidebar collection for mobile upload documents and sharing return [ { title: "Dashboards", target: Cast(doc.myDashboards, Doc, null), icon: "desktop", click: 'selectMainMenu(self)' }, - { title: "Inactive", target: Cast(doc.myInactiveDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' }, + { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' }, { title: "Import", target: Cast(doc.myImportPanel, Doc, null), icon: "upload", click: 'selectMainMenu(self)' }, { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc }, { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' }, @@ -758,17 +758,17 @@ export class CurrentUserUtils { static setupInactiveDocs(doc: Doc) { // setup Recently Closed library item - doc.myInactiveDocs === undefined; - if (doc.myInactiveDocs === undefined) { - doc.myInactiveDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { + doc.myRecentlyClosedDocs === undefined; + if (doc.myRecentlyClosedDocs === undefined) { + doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "Inactive", _height: 500, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); const clearAll = ScriptField.MakeScript(`self.data = new List([])`); - (doc.myInactiveDocs as any as Doc).contextMenuScripts = new List([clearAll!]); - (doc.myInactiveDocs as any as Doc).contextMenuLabels = new List(["Clear All"]); + (doc.myRecentlyClosedDocs as any as Doc).contextMenuScripts = new List([clearAll!]); + (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List(["Clear All"]); } } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index d621a792b..1cea94064 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -131,7 +131,7 @@ export function ViewBoxAnnotatableComponent

          docs.includes(v)); if (toRemove.length !== 0) { - const recent = Cast(Doc.UserDoc().myInactiveDocs, Doc) as Doc; + const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc) as Doc; toRemove.forEach(doc => { Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey + "-annotations", doc); recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index dfefd645a..003f0c514 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -611,7 +611,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { if (doc instanceof Doc) { const theDoc = doc; - const recent = await Cast(Doc.UserDoc().myInactiveDocs, Doc); + const recent = await Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc); if (recent) { Doc.AddDocToList(recent, "data", doc, undefined, true, true); } @@ -682,7 +682,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { const doc = await DocServer.GetRefField(contentItem.config.props.documentId); if (doc instanceof Doc) { let recent: Doc | undefined; - if (recent = await Cast(Doc.UserDoc().myInactiveDocs, Doc)) { + if (recent = await Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc)) { Doc.AddDocToList(recent, "data", doc, undefined, true, true); } const theDoc = doc; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index d7f0f8e14..66bdcf130 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -744,8 +744,8 @@ export class CollectionTreeView extends CollectionSubView Doc.UserDoc().myInactiveDocs = new List(), icon: "plus" }); + } else if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myRecentlyClosedDocs) { + ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.UserDoc().myRecentlyClosedDocs = new List(), icon: "plus" }); e.stopPropagation(); e.preventDefault(); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a7361bc9c..f028b797c 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -198,7 +198,7 @@ export class CollectionView extends Touchable docs.includes(v)); if (toRemove.length !== 0) { - const recent = Cast(Doc.UserDoc().myInactiveDocs, Doc) as Doc; + const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc) as Doc; toRemove.forEach(doc => { Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc); recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 2627afbae..f9ffb4260 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -233,8 +233,8 @@ export class PropertiesView extends React.Component { @undoBatch setKeyValue = (value: string) => { - if (this.selectedDoc && this.dataDoc) { - const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc; + const docs = SelectionManager.SelectedDocuments().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.SelectedDocuments().map(dv => this.layoutFields ? dv.layoutDoc : dv.dataDoc); + docs.forEach(doc => { if (value.indexOf(":") !== -1) { const newVal = value[0].toUpperCase() + value.substring(1, value.length); KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true); @@ -244,7 +244,7 @@ export class PropertiesView extends React.Component { KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true); return true; } - } + }); return false; } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 816f5028b..48f10ba26 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -58,21 +58,6 @@ export class CollectionFreeFormDocumentView extends DocComponent Date: Fri, 28 Aug 2020 15:45:07 -0400 Subject: fixed undo for collection tabs. fixed treeview to support freezeChildren to prevent children from being removed from the tree. Made _isBackground a layoutfield. fixed formattedTextBox exceptions on undo from a tab. --- src/client/documents/Documents.ts | 16 +- src/client/util/CurrentUserUtils.ts | 19 +- src/client/views/DocComponent.tsx | 6 +- src/client/views/MainView.tsx | 2 +- src/client/views/animationtimeline/Keyframe.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 316 ++++++++------------- .../views/collections/CollectionTreeView.tsx | 18 +- src/client/views/collections/CollectionView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 16 +- .../collections/collectionFreeForm/MarqueeView.tsx | 8 +- .../collectionFreeForm/PropertiesView.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 6 +- src/client/views/nodes/DocumentView.tsx | 18 +- src/client/views/nodes/ImageBox.tsx | 4 +- src/client/views/nodes/LinkAnchorBox.tsx | 2 +- src/client/views/nodes/PresBox.tsx | 12 +- src/client/views/nodes/VideoBox.tsx | 3 +- src/client/views/nodes/WebBox.tsx | 8 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 16 +- .../views/presentationview/PresElementBox.tsx | 2 +- src/client/views/search/SearchBox.tsx | 2 +- src/fields/Doc.ts | 22 +- src/fields/documentSchemas.ts | 2 +- 23 files changed, 231 insertions(+), 275 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b8cac2beb..18ff993fe 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -33,7 +33,6 @@ import { ColorBox } from "../views/nodes/ColorBox"; import { ComparisonBox } from "../views/nodes/ComparisonBox"; import { DocHolderBox } from "../views/nodes/DocHolderBox"; import { FontIconBox } from "../views/nodes/FontIconBox"; -import { MenuIconBox } from "../views/nodes/MenuIconBox"; import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox"; import { ImageBox } from "../views/nodes/ImageBox"; import { KeyValueBox } from "../views/nodes/KeyValueBox"; @@ -129,7 +128,7 @@ export interface DocumentOptions { isAnnotating?: boolean; // whether we web document is annotation mode where links can't be clicked to allow annotations to be created opacity?: number; defaultBackgroundColor?: string; - isBackground?: boolean; + _isBackground?: boolean; isLinkButton?: boolean; _columnWidth?: number; _fontSize?: string; @@ -186,6 +185,7 @@ export interface DocumentOptions { strokeWidth?: number; cloneFieldFilter?: List; // fields not to copy when the document is cloned _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere + freezeChildren?: string; // whether children are now allowed to be added and or removed from a collection treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view treeViewHideTitle?: boolean; // whether to hide the top document of a tree view treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items. @@ -535,7 +535,7 @@ export namespace Docs { Scripting.addGlobal(Buxton); - const delegateKeys = ["x", "y", "system", "layoutKey", "dropAction", "lockedPosiiton", "childDropAction", "isLinkButton", "isBackground", "removeDropProperties", "treeViewOpen"]; + const delegateKeys = ["x", "y", "system", "layoutKey", "dropAction", "lockedPosiiton", "childDropAction", "isLinkButton", "removeDropProperties", "treeViewOpen"]; /** * This function receives the relevant document prototype and uses @@ -684,7 +684,7 @@ export namespace Docs { const doc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, { dontRegisterChildViews: true, isLinkButton: true, treeViewHideTitle: true, backgroundColor: "lightBlue", // lightBlue is default color for linking dot and link documents text comment area - treeViewExpandedView: "fields", removeDropProperties: new List(["isBackground", "isLinkButton"]), ...options + treeViewExpandedView: "fields", removeDropProperties: new List(["_isBackground", "isLinkButton"]), ...options }, id); const linkDocProto = Doc.GetProto(doc); linkDocProto.treeViewOpen = true;// setting this in the instance creator would set it on the view document. @@ -694,7 +694,7 @@ export namespace Docs { linkDocProto.anchor2_timecode = target.doc._currentTimecode || target.doc.displayTimecode; if (linkDocProto.linkBoxExcludedKeys === undefined) { - Cast(linkDocProto.proto, Doc, null).linkBoxExcludedKeys = new List(["treeViewExpandedView", "aliases", "treeViewHideTitle", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); + Cast(linkDocProto.proto, Doc, null).linkBoxExcludedKeys = new List(["treeViewExpandedView", "aliases", "treeViewHideTitle", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "aliasNumber", "isPrototype", "creationDate", "author"]); Cast(linkDocProto.proto, Doc, null).layoutKey = undefined; } @@ -825,9 +825,9 @@ export namespace Docs { } export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { - const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); - const tabs = TreeDocument(documents, { title: "On-Screen Tabs", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true }); - const all = TreeDocument([], { title: "Off-Screen Tabs", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true }); + const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); + const tabs = TreeDocument(documents, { title: "On-Screen Tabs", freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true }); + const all = TreeDocument([], { title: "Off-Screen Tabs", freezeChildren: "add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true }); Doc.GetProto(inst).data = new List([tabs, all]); return inst; } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2c9c870aa..c60403701 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -26,6 +26,8 @@ import { LinkManager } from "./LinkManager"; import { Id } from "../../fields/FieldSymbols"; import { HistoryUtil } from "./History"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; +import { SelectionManager } from "./SelectionManager"; +import { DocumentManager } from "./DocumentManager"; export class CurrentUserUtils { private static curr_id: string; @@ -1018,12 +1020,9 @@ export class CurrentUserUtils { } public static snapshotDashboard = (userDoc: Doc) => { - const activeDashboard = Cast(userDoc.activeDashboard, Doc, null); - CollectionDockingView.Copy(activeDashboard).then(copy => { - Doc.AddDocToList(Cast(userDoc.myDashboards, Doc, null), "data", copy); - // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) - setTimeout(() => CurrentUserUtils.openDashboard(userDoc, copy), 0); - }); + const copy = CollectionDockingView.Copy(Cast(userDoc.activeDashboard, Doc, null)); + Doc.AddDocToList(Cast(userDoc.myDashboards, Doc, null), "data", copy); + CurrentUserUtils.openDashboard(userDoc, copy); } public static createNewDashboard = async (userDoc: Doc, id?: string) => { @@ -1059,6 +1058,14 @@ export class CurrentUserUtils { } } +Scripting.addGlobal(function openDragFactory(dragFactory: Doc) { + const copy = Doc.copyDragFactory(dragFactory); + if (copy) { + CollectionDockingView.AddRightSplit(copy); + const view = DocumentManager.Instance.getFirstDocumentView(copy); + view && SelectionManager.SelectDoc(view, false); + } +}); Scripting.addGlobal(function snapshotDashboard() { CurrentUserUtils.snapshotDashboard(Doc.UserDoc()); }, "creates a snapshot copy of a dashboard"); Scripting.addGlobal(function createNewDashboard() { return CurrentUserUtils.createNewDashboard(Doc.UserDoc()); }, diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 1cea94064..e9469d7bb 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -58,7 +58,7 @@ export function ViewBoxBaseComponent

          (schemaCtor: lookupField = (field: string) => ScriptCast(this.layoutDoc.lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field, container: this.props.ContainingCollectionDoc }).result; - active = (outsideReaction?: boolean) => !this.props.Document.isBackground && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0 || this.layoutDoc.forceActive);// && !Doc.SelectedTool(); // bcz: inking state shouldn't affect static tools + active = (outsideReaction?: boolean) => !this.props.Document._isBackground && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0 || this.layoutDoc.forceActive);// && !Doc.SelectedTool(); // bcz: inking state shouldn't affect static tools protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; } return Component; @@ -187,9 +187,9 @@ export function ViewBoxAnnotatableComponent

          this.props.whenActiveChanged(this._isChildActive = isActive)); - active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.props.Document.isBackground) && + active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.props.Document._) && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0 || BoolCast((this.layoutDoc as any).forceActive)) ? true : false) - annotationsActive = (outsideReaction?: boolean) => (Doc.GetSelectedTool() !== InkTool.None || (this.props.Document.isBackground && this.props.active()) || + annotationsActive = (outsideReaction?: boolean) => (Doc.GetSelectedTool() !== InkTool.None || (this.props.Document._isBackground && this.props.active()) || (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) } return Component; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 9371728ce..3afda13c2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -386,7 +386,7 @@ export class MainView extends React.Component { addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => { return where === "close" ? CollectionDockingView.CloseRightSplit(doc) : doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : - CollectionDockingView.AddRightSplit(doc, libraryPath); + CollectionDockingView.AddRightSplit(doc); } sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0) - Number(SEARCH_PANEL_HEIGHT.replace("px", "")), 1); mainContainerXf = () => this.sidebarScreenToLocal().translate(-58, 0); diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index 1b81c544a..4fb362ab1 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -331,7 +331,7 @@ export class Keyframe extends React.Component { }), TimelineMenu.Instance.addItem("button", "Show Data", action(() => { const kvp = Docs.Create.KVPDocument(kf, { _width: 300, _height: 300 }); - CollectionDockingView.AddRightSplit(kvp, emptyPath); + CollectionDockingView.AddRightSplit(kvp); })), TimelineMenu.Instance.addItem("button", "Delete", action(() => { (this.regiondata.keyframes as List).splice(this.keyframes.indexOf(kf), 1); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 3d8ac2a23..86d27acd5 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -24,7 +24,7 @@ import { Scripting } from '../../util/Scripting'; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoBatch } from "../../util/UndoManager"; +import { undoBatch, UndoManager } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import { PresBox } from '../nodes/PresBox'; import "./CollectionDockingView.scss"; @@ -59,7 +59,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { @observable private _goldenLayout: any = null; private _containerRef = React.createRef(); - private _flush: boolean = false; + private _flush: UndoManager.Batch | undefined; private _ignoreStateChange = ""; private _isPointerDown = false; private _maximizedSrc: Opt; @@ -73,6 +73,8 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { DragManager.StartWindowDrag = this.StartOtherDrag; } public StartOtherDrag = (e: any, dragDocs: Doc[]) => { + console.log("START drag batch"); + !this._flush && (this._flush = UndoManager.StartBatch("golden layout drag")); const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) : { type: 'row', @@ -104,6 +106,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { SelectionManager.DeselectAll(); } + @undoBatch public CloseFullScreen = () => { const target = this._goldenLayout._maximisedItem; if (target !== null && this._maximizedSrc) { @@ -121,25 +124,24 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { @undoBatch @action public static CloseRightSplit(document: Opt): boolean { - const instance = CollectionDockingView.Instance; const tryClose = (childItem: any) => { if (childItem.config?.component === "DocumentFrameRenderer") { const docView = DocumentManager.Instance.getDocumentViewById(childItem.config.props.documentId); if (docView && ((!document && docView.Document.isDisplayPanel) || (document && Doc.AreProtosEqual(docView.props.Document, document)))) { childItem.remove(); - instance.layoutChanged(document); return true; } } return false; }; - const retVal = !instance?._goldenLayout.root.contentItems[0].isRow ? false : - Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => Array.from(child.contentItems).some(tryClose)); + const retVal = !CollectionDockingView.Instance?._goldenLayout.root.contentItems[0].isRow ? false : + Array.from(CollectionDockingView.Instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => Array.from(child.contentItems).some(tryClose)); - retVal && instance.stateChanged(); + retVal && CollectionDockingView.Instance.layoutChanged(document); return retVal; } + @undoBatch @action layoutChanged(removed?: Doc) { this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]); @@ -147,20 +149,17 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig()); this.stateChanged(); } - @undoBatch - @action + public static ReplaceRightSplit(document: Doc, libraryPath?: Doc[], addToSplit?: boolean): boolean { if (!CollectionDockingView.Instance) return false; const instance = CollectionDockingView.Instance; - let retVal = false; - if (instance._goldenLayout.root.contentItems[0].isRow) { - retVal = Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => { + const retVal = !instance._goldenLayout.root.contentItems[0].isRow ? false : + Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => { if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" && DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)?.Document.isDisplayPanel) { const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); child.addChild(newItemStackConfig, undefined); !addToSplit && child.contentItems[0].remove(); - instance.layoutChanged(document); return true; } return Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { @@ -168,16 +167,12 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); child.addChild(newItemStackConfig, undefined); !addToSplit && child.contentItems[j].remove(); - instance.layoutChanged(document); return true; } return false; }); }); - } - if (retVal) { - instance.stateChanged(); - } + retVal && instance.layoutChanged(document); return retVal; } @@ -186,34 +181,51 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { // @undoBatch @action - public static AddRightSplit(document: Doc, libraryPath?: Doc[]) { + public static AddRightSplit(document: Doc, dontSelect: boolean = false, isDisplayPanel: Opt = undefined) { if (!CollectionDockingView.Instance) return false; - if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document); - const instance = CollectionDockingView.Instance; - const newItemStackConfig = { - type: 'stack', - content: [CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath)] - }; - const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); - - if (instance._goldenLayout.root.contentItems.length === 0) { - instance._goldenLayout.root.addChild(newContentItem); - } else if (instance._goldenLayout.root.contentItems[0].isRow) { - instance._goldenLayout.root.contentItems[0].addChild(newContentItem); + const ind = CollectionDockingView.Instance._tabMap.findIndex((val) => val.doc === document); + if (ind !== -1) { + const tab = CollectionDockingView.Instance._tabMap[ind].tab; + const activeContentItem = tab.header.parent.getActiveContentItem(); + if (tab.contentItem !== activeContentItem) { + tab.header.parent.setActiveContentItem(tab.contentItem); + } + tab.setActive(true); } else { - const collayout = instance._goldenLayout.root.contentItems[0]; - const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout); - collayout.parent.replaceChild(collayout, newRow); + document.isDisplayPanel = isDisplayPanel; - newRow.addChild(newContentItem, undefined, true); - newRow.addChild(collayout, 0, true); + if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document); + const instance = CollectionDockingView.Instance; + const newItemStackConfig = { + type: 'stack', + content: [CollectionDockingView.makeDocumentConfig(document, undefined, [])] + }; + + const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout); - collayout.config.width = 50; - newContentItem.config.width = 50; + if (instance._goldenLayout.root.contentItems.length === 0) { + instance._goldenLayout.root.addChild(newContentItem); + } else if (instance._goldenLayout.root.contentItems[0].isRow) { + instance._goldenLayout.root.contentItems[0].addChild(newContentItem); + } else { + const collayout = instance._goldenLayout.root.contentItems[0]; + const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout); + collayout.parent.replaceChild(collayout, newRow); + + newRow.addChild(newContentItem, undefined, true); + newRow.addChild(collayout, 0, true); + + collayout.config.width = 50; + newContentItem.config.width = 50; + } + newContentItem.callDownwards('_$init'); + instance.layoutChanged(); + } + if (!dontSelect) { + const view = DocumentManager.Instance.getFirstDocumentView(document); + view && SelectionManager.SelectDoc(view, false); } - newContentItem.callDownwards('_$init'); - instance.layoutChanged(); return true; } @@ -221,7 +233,6 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { // // Creates a split on any side of the docking view based on the passed input pullSide and then adds the Document to the requested side // - @undoBatch @action public static AddSplit(document: Doc, pullSide: string, libraryPath?: Doc[]) { if (!CollectionDockingView.Instance) return false; @@ -289,19 +300,13 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { // // Creates a vertical split on the right side of the docking view, and then adds the Document to that split // - @undoBatch - @action public static UseRightSplit(document: Doc, libraryPath?: Doc[], shiftKey?: boolean) { - document.isDisplayPanel = true; if (shiftKey || !CollectionDockingView.ReplaceRightSplit(document, libraryPath, shiftKey)) { - CollectionDockingView.AddRightSplit(document, libraryPath); + CollectionDockingView.AddRightSplit(document, false, true); } } - @undoBatch - @action public AddTab = (stack: any, document: Doc, libraryPath?: Doc[]) => { - Doc.GetProto(document).lastOpened = new DateField; const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); if (stack === undefined) { let stack: any = this._goldenLayout.root; @@ -324,10 +329,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { return true; } - @undoBatch - @action public ReplaceTab = (stack: any, document: Doc, libraryPath?: Doc[]) => { - Doc.GetProto(document).lastOpened = new DateField; const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); if (stack === undefined) { let stack: any = this._goldenLayout.root; @@ -350,9 +352,15 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { return true; } - setupGoldenLayout() { + _tabMap: { tab: any, doc: Doc }[] = []; + + async setupGoldenLayout() { const config = StrCast(this.props.Document.dockingConfig); if (config) { + const matches = config.match(/\"documentId\":\"[a-z0-9-]+\"/g); + const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) ?? []; + await Promise.all(docids.map(id => DocServer.GetRefField(id))); + if (!this._goldenLayout) { runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config))); } @@ -361,7 +369,6 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { return; } try { - this._goldenLayout.unbind('itemDropped', this.itemDropped); this._goldenLayout.unbind('tabCreated', this.tabCreated); this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed); this._goldenLayout.unbind('stackCreated', this.stackCreated); @@ -369,12 +376,12 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { this._goldenLayout.destroy(); runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config))); } - this._goldenLayout.on('itemDropped', this.itemDropped); this._goldenLayout.on('tabCreated', this.tabCreated); this._goldenLayout.on('tabDestroyed', this.tabDestroyed); this._goldenLayout.on('stackCreated', this.stackCreated); this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer); this._goldenLayout.container = this._containerRef.current; + //this._goldenLayout.on("stateChanged", () => console.log("STATE CHANGED")); if (this._goldenLayout.config.maximisedItemId === '__glMaximised') { try { this._goldenLayout.config.root.getItemsById(this._goldenLayout.config.maximisedItemId)[0].toggleMaximise(); @@ -388,46 +395,39 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { reactionDisposer?: Lambda; componentDidMount: () => void = () => { if (this._containerRef.current) { - const observer = new _global.ResizeObserver(action((entries: any) => { - for (const entry of entries) { - this.onResize(null as any); - } - })); + const observer = new _global.ResizeObserver(this.onResize); observer.observe(this._containerRef.current); this.reactionDisposer = reaction( - () => this.props.Document.dockingConfig, - () => { - if (!this._goldenLayout || this._ignoreStateChange !== JSON.stringify(this._goldenLayout.toConfig())) { - // Because this is in a set timeout, if this component unmounts right after mounting, - // we will leak a GoldenLayout, because we try to destroy it before we ever create it - setTimeout(() => this.setupGoldenLayout(), 1); + () => StrCast(this.props.Document.dockingConfig), + config => { + if (!this._goldenLayout || this._ignoreStateChange !== config) { + this.setupGoldenLayout(); DocListCast((Doc.UserDoc().myDashboards as Doc).data).map(d => d.dashboardBrush = false); this.props.Document.dashboardBrush = true; } this._ignoreStateChange = ""; - }, { fireImmediately: true }); - + }); + setTimeout(() => this.setupGoldenLayout(), 0); window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window } } componentWillUnmount: () => void = () => { try { this.props.Document.dashboardBrush = false; - this._goldenLayout.unbind('itemDropped', this.itemDropped); this._goldenLayout.unbind('tabCreated', this.tabCreated); this._goldenLayout.unbind('stackCreated', this.stackCreated); this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed); } catch (e) { } - this._goldenLayout && this._goldenLayout.destroy(); + this._goldenLayout?.destroy(); runInAction(() => { CollectionDockingView.Instances.splice(CollectionDockingView.Instances.indexOf(this), 1); this._goldenLayout = null; }); window.removeEventListener('resize', this.onResize); - this.reactionDisposer && this.reactionDisposer(); + this.reactionDisposer?.(); } @action onResize = (event: any) => { @@ -437,26 +437,26 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { } @action - onPointerUp = (e: React.PointerEvent): void => { + onPointerUp = (e: MouseEvent): void => { + window.removeEventListener("pointerup", this.onPointerUp); + this._isPointerDown = false; if (this._flush) { - this._flush = false; setTimeout(() => { CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig()); this.stateChanged(); + console.log("END BATCH Up"); + this._flush!.end(); + this._flush = undefined; }, 10); } } @action onPointerDown = (e: React.PointerEvent): void => { - this._isPointerDown = true; - const onPointerUp = action(() => { - window.removeEventListener("pointerup", onPointerUp); - this._isPointerDown = false; - }); - window.addEventListener("pointerup", onPointerUp); - const className = (e.target as any).className; - if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") { - this._flush = true; + window.addEventListener("mouseup", this.onPointerUp); + + if (!(e.target as HTMLElement).closest("*.lm_content") && ((e.target as HTMLElement).closest("*.lm_tab") || (e.target as HTMLElement).closest("*.lm_stack"))) { + console.log("START BATCH dwn"); + this._flush = UndoManager.StartBatch("golden layout edit"); } if (e.nativeEvent.cancelBubble || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) || InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || (Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) { return; @@ -464,29 +464,11 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { e.stopPropagation(); } } - - updateDataField = async (json: string) => { - const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g); - const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")); - - const docs = !docids ? [] : (await Promise.all(docids.map(id => DocServer.GetRefField(id)))).filter(f => f).map(f => f as Doc); - const sublists = DocListCast(this.props.Document[this.props.fieldKey]); - const tabs = Cast(sublists[0], Doc, null); - const other = Cast(sublists[1], Doc, null); - const tabdocs = DocListCast(tabs.data); - const otherdocs = DocListCast(other.data); - Doc.GetProto(tabs).data = new List(docs); - const otherSet = new Set(); - otherdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc)); - tabdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc)); - Doc.GetProto(other).data = new List(Array.from(otherSet.values())); - } - - public static async Copy(doc: Doc) { + public static Copy(doc: Doc) { let json = StrCast(doc.dockingConfig); const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g); const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) || []; - const docs = (await Promise.all(docids.map(id => DocServer.GetRefField(id)))).filter(f => f).map(f => f as Doc); + const docs = docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc); const newtabs = docs.map(doc => { const copy = Doc.MakeAlias(doc); json = json.replace(doc[Id], copy[Id]); @@ -503,34 +485,36 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { return copy; } - @undoBatch + @action stateChanged = () => { const json = JSON.stringify(this._goldenLayout.toConfig()); - this.props.Document.dockingConfig = json; - this.updateDataField(json); - } - - itemDropped = () => { - CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig()); - this.stateChanged(); - } + const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g); + const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")); + const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc); - htmlToElement(html: string) { - const template = document.createElement('template'); - html = html.trim(); // Never return a text node of whitespace as the result - template.innerHTML = html; - return template.content.firstChild; + this.props.Document.dockingConfig = json; + const sublists = DocListCast(this.props.Document[this.props.fieldKey]); + const tabs = Cast(sublists[0], Doc, null); + const other = Cast(sublists[1], Doc, null); + const tabdocs = DocListCast(tabs.data); + const otherdocs = DocListCast(other.data); + Doc.GetProto(tabs).data = new List(docs); + const otherSet = new Set(); + otherdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc)); + tabdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc)); + Doc.GetProto(other).data = new List(Array.from(otherSet.values())); } - tabCreated = async (tab: any) => { + tabCreated = (tab: any) => { tab.titleElement[0].Tab = tab; if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") { if (tab.contentItem.config.fixed) { tab.contentItem.parent.config.fixed = true; } - const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId) as Doc; + const doc = DocServer.GetCachedRefField(tab.contentItem.config.props.documentId) as Doc; if (doc instanceof Doc) { + this._tabMap.push({ tab: tab, doc: doc }); tab.titleElement[0].onclick = (e: any) => { if (Date.now() - tab.titleElement[0].lastClick < 1000) tab.titleElement[0].select(); tab.titleElement[0].lastClick = Date.now(); @@ -550,8 +534,10 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { gearSpan.style.paddingRight = "12px"; const stack = tab.contentItem.parent; tab.element[0].onpointerdown = (e: any) => { - const view = DocumentManager.Instance.getDocumentView(doc); - view && SelectionManager.SelectDoc(view, false); + if (e.target.className !== "lm_close_tab") { + const view = DocumentManager.Instance.getDocumentView(doc); + view && SelectionManager.SelectDoc(view, false); + } }; // shifts the focus to this tab when another tab is dragged over it tab.element[0].onmouseenter = (e: any) => { @@ -594,27 +580,23 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { tab.reactComponents = [gearSpan]; tab.element.append(gearSpan); tab.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => { - tab.titleElement[0].textContent = title, { fireImmediately: true }; + tab.titleElement[0].value = title; tab.titleElement[0].style.padding = degree ? 0 : 2; tab.titleElement[0].style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`; - }); + }, { fireImmediately: true }); //TODO why can't this just be doc instead of the id? tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId; } } tab.closeElement.off('click') //unbind the current click handler - .click(async function () { + .click(function () { tab.selectionDisposer?.(); tab.reactionDisposer?.(); tab.buttonDisposer?.(); - const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId); + const doc = DocServer.GetCachedRefField(tab.contentItem.config.props.documentId); if (doc instanceof Doc) { - const theDoc = doc; - - const recent = await Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc); - if (recent) { - Doc.AddDocToList(recent, "data", doc, undefined, true, true); - } + const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc, null); + recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); SelectionManager.DeselectAll(); } CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig()); @@ -624,6 +606,8 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { } tabDestroyed = (tab: any) => { + const ind = this._tabMap.findIndex((val) => val.tab === tab); + ind !== -1 && this._tabMap.splice(ind, 1); if (tab.reactComponents) { for (const ele of tab.reactComponents) { ReactDOM.unmountComponentAtNode(ele); @@ -631,15 +615,8 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { } } - stackActiveChanged = () => { - try { - CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig()); - this.stateChanged(); - } catch (e) { } // catch exception thrown when config has not been initialzed yet - } stackCreated = (stack: any) => { - stack.layoutManager.on("activeContentItemChanged", this.stackActiveChanged); //stack.header.controlsContainer.find('.lm_popout').hide(); stack.header.element.on('mousedown', (e: any) => { if (e.target === stack.header.element[0] && e.button === 2) { @@ -651,58 +628,28 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { } }); - // starter code for bezel to add new pane - // stack.element.on("touchstart", (e: TouchEvent) => { - // if (e.targetTouches.length === 2) { - // let pt1 = e.targetTouches.item(0); - // let pt2 = e.targetTouches.item(1); - // let threshold = 40 * window.devicePixelRatio; - // if (pt1 && pt2 && InteractionUtils.TwoPointEuclidist(pt1, pt2) < threshold) { - // let edgeThreshold = 30 * window.devicePixelRatio; - // let center = InteractionUtils.CenterPoint([pt1, pt2]); - // let stackRect: DOMRect = stack.element.getBoundingClientRect(); - // let nearLeft = center.X - stackRect.x < edgeThreshold; - // let nearTop = center.Y - stackRect.y < edgeThreshold; - // let nearRight = stackRect.right - center.X < edgeThreshold; - // let nearBottom = stackRect.bottom - center.Y < edgeThreshold; - // let ns = [nearLeft, nearTop, nearRight, nearBottom].filter(n => n); - // if (ns.length === 1) { - - // } - // } - // } - // }); stack.header.controlsContainer.find('.lm_close') //get the close icon .off('click') //unbind the current click handler - .click(action(async () => { + .click(action(() => { //if (confirm('really close this?')) { - stack.remove(); - stack.contentItems.forEach(async (contentItem: any) => { - const doc = await DocServer.GetRefField(contentItem.config.props.documentId); + stack.contentItems.forEach((contentItem: any) => { + const doc = Cast(DocServer.GetCachedRefField(contentItem.config.props.documentId), Doc, null); if (doc instanceof Doc) { - let recent: Doc | undefined; - if (recent = await Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc)) { - Doc.AddDocToList(recent, "data", doc, undefined, true, true); - } - const theDoc = doc; + const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc, null); + recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); } }); - //} })); stack.header.controlsContainer.find('.lm_popout') //get the close icon .off('click') //unbind the current click handler .click(action(() => { // stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size - const emptyPane = Cast(Doc.UserDoc().emptyPane, Doc, null); emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1; this.AddTab(stack, Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}` })); - - // const url = Utils.prepend("/doc/" + stack.contentItems[0].tab.contentItem.config.props.documentId); - // let win = window.open(url, stack.contentItems[0].tab.title, "width=300,height=400"); })); } @@ -710,10 +657,8 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { if (this.props.renderDepth > 0) { return

          Nested dashboards can't be rendered
          ; } - return