From 566b33847cff9217ed6e4e11bed2e1b92798bc95 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Tue, 21 Jun 2022 18:16:46 -0400 Subject: trying to get basic data viz view to work --- src/client/documents/DocumentTypes.ts | 1 + src/client/documents/Documents.ts | 9 +++++++++ src/client/util/CurrentUserUtils.ts | 5 ++++- src/client/views/nodes/DataViz.scss | 0 src/client/views/nodes/DataViz.tsx | 14 ++++++++++++++ src/client/views/nodes/DocumentContentsView.tsx | 3 ++- 6 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/client/views/nodes/DataViz.scss create mode 100644 src/client/views/nodes/DataViz.tsx (limited to 'src') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index ca942a38a..2343c2f34 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -25,6 +25,7 @@ export enum DocumentType { EQUATION = "equation", // equation editor FUNCPLOT = "funcplot", // function plotter MAP = "map", + DATAVIZ = "dataviz", // special purpose wrappers that either take no data or are compositions of lower level types LINK = "link", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0bb6ce27f..c5ec9eaf6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -62,6 +62,7 @@ import { DocumentType } from "./DocumentTypes"; import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { MapBox } from "../views/nodes/MapBox/MapBox"; import { RecordingBox } from "../views/nodes/RecordingBox/RecordingBox"; +import DataViz from "../views/nodes/DataViz"; const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); class EmptyBox { @@ -517,6 +518,10 @@ export namespace Docs { layout: { view: EmptyBox, dataField: defaultDataKey }, options: { links: "@links(self)" } }], + [DocumentType.DATAVIZ, { + layout: { view: DataViz, dataField: defaultDataKey }, + options: { _fitWidth: true, _fitHeight: true, links: "@links(self)" } + }] ]); const suffix = "Proto"; @@ -922,6 +927,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) }); } + export function DataVizDocument(options?: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.DATAVIZ), undefined, { title: "Data Viz", ...options }); + } + export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 60bfc165b..a96f5cb18 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -262,7 +262,10 @@ export class CurrentUserUtils { doc.emptyHeader = headerTemplate; } if (doc.emptyComparison === undefined) { - doc.emptyComparison = Docs.Create.ComparisonDocument({ ...standardOps(), title: "Comparer", _width: 300, _height: 300 }); + doc.emptyComparison = Docs.Create.ComparisonDocument({ ...standardOps(), title: "comparer", _width: 300, _height: 300 }); + } + if (doc.emptyDataViz === undefined) { + doc.emptyDataViz = Docs.Create.DataVizDocument({ ...standardOps(), title: "data viz", _width: 300, _height: 300 }); } if (doc.emptyScript === undefined) { doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { ...standardOps(), title: "script", _width: 200, _height: 250, }); diff --git a/src/client/views/nodes/DataViz.scss b/src/client/views/nodes/DataViz.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/client/views/nodes/DataViz.tsx b/src/client/views/nodes/DataViz.tsx new file mode 100644 index 000000000..60b27c19c --- /dev/null +++ b/src/client/views/nodes/DataViz.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import "./DataViz.scss"; +import { FieldView, FieldViewProps } from "./FieldView"; +import { ViewBoxBaseComponent } from '../DocComponent'; + +export class DataViz extends ViewBoxBaseComponent() { + public static LayoutString(fieldKey: string) { + return FieldView.LayoutString(DataViz, fieldKey); + } + + render() { + return (
Hi
) + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 70732e74c..8715fc33a 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -42,6 +42,7 @@ import React = require("react"); import XRegExp = require("xregexp"); import { MapBox } from "./MapBox/MapBox"; import { RecordingBox } from "./RecordingBox"; +import { DataViz } from "./DataViz"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? @@ -229,7 +230,7 @@ export class DocumentContentsView extends React.Component Date: Tue, 21 Jun 2022 19:30:17 -0400 Subject: running into jsx parsing error --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 3 ++- src/client/views/nodes/DataViz.tsx | 14 +++++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c5ec9eaf6..42191bd7e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -62,7 +62,7 @@ import { DocumentType } from "./DocumentTypes"; import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { MapBox } from "../views/nodes/MapBox/MapBox"; import { RecordingBox } from "../views/nodes/RecordingBox/RecordingBox"; -import DataViz from "../views/nodes/DataViz"; +import { DataViz } from "../views/nodes/DataViz"; const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); class EmptyBox { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index a96f5cb18..8ccb0d197 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -310,7 +310,8 @@ export class CurrentUserUtils { { 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 }, { toolTip: "Tap to create a custom header note document, drag for a custom header note", title: "Custom", icon: "window-maximize", click: 'openOnRight(delegateDragFactory(this.dragFactory))', drag: 'delegateDragFactory(this.dragFactory)', dragFactory: doc.emptyHeader 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: "Tap to create a map in the new pane, drag for a map", title: "Map", icon: "map-marker-alt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyMap as Doc, noviceMode: true } + { toolTip: "Tap to create a map in the new pane, drag for a map", title: "Map", icon: "map-marker-alt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyMap as Doc, noviceMode: true }, + { toolTip: "Tap to create a data visualization in a new pane", title: "Data Viz", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyDataViz as Doc} ]; } diff --git a/src/client/views/nodes/DataViz.tsx b/src/client/views/nodes/DataViz.tsx index 60b27c19c..57c5c0259 100644 --- a/src/client/views/nodes/DataViz.tsx +++ b/src/client/views/nodes/DataViz.tsx @@ -4,11 +4,23 @@ import { FieldView, FieldViewProps } from "./FieldView"; import { ViewBoxBaseComponent } from '../DocComponent'; export class DataViz extends ViewBoxBaseComponent() { + + constructor(props: any) { + super(props); + } + + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DataViz, fieldKey); } render() { - return (
Hi
) + return ( +
+
+ Hi +
+
+ ); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From e691d8e72ba632f0ef2d4122fe7233f9a48d4439 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 21 Jun 2022 21:36:40 -0400 Subject: fixed issues with register DataViz jsx. --- src/client/documents/Documents.ts | 17 ++++++++--------- src/client/views/nodes/DataViz.tsx | 6 +++--- src/client/views/nodes/DocumentContentsView.tsx | 13 ++++++------- 3 files changed, 17 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 42191bd7e..29536b642 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,7 +1,8 @@ +import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { action, runInAction } from "mobx"; import { basename } from "path"; import { DateField } from "../../fields/DateField"; -import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Initializing, Opt, updateCachedAcls, WidthSym } from "../../fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, Field, Initializing, Opt, updateCachedAcls } from "../../fields/Doc"; import { Id } from "../../fields/FieldSymbols"; import { HtmlField } from "../../fields/HtmlField"; import { InkField, PointData } from "../../fields/InkField"; @@ -14,7 +15,7 @@ import { Cast, NumCast, StrCast } from "../../fields/Types"; import { AudioField, ImageField, MapField, PdfField, RecordingField, VideoField, WebField, YoutubeField } from "../../fields/URLField"; import { SharingPermissions } from "../../fields/util"; import { Upload } from "../../server/SharedMediaTypes"; -import { OmitKeys, Utils, aggregateBounds } from "../../Utils"; +import { aggregateBounds, OmitKeys, Utils } from "../../Utils"; import { YoutubeBox } from "../apis/youtube/YoutubeBox"; import { DocServer } from "../DocServer"; import { Networking } from "../Network"; @@ -33,13 +34,14 @@ import { ContextMenuProps } from "../views/ContextMenuItem"; import { DFLT_IMAGE_NATIVE_DIM } from "../views/global/globalCssVariables.scss"; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, InkingStroke } from "../views/InkingStroke"; import { AudioBox } from "../views/nodes/AudioBox"; +import { FontIconBox } from "../views/nodes/button/FontIconBox"; import { ColorBox } from "../views/nodes/ColorBox"; import { ComparisonBox } from "../views/nodes/ComparisonBox"; +import { DataVizBox } from "../views/nodes/DataViz"; import { DocFocusOptions } from "../views/nodes/DocumentView"; import { EquationBox } from "../views/nodes/EquationBox"; import { FieldViewProps } from "../views/nodes/FieldView"; import { FilterBox } from "../views/nodes/FilterBox"; -import { FontIconBox } from "../views/nodes/button/FontIconBox"; import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox"; import { FunctionPlotBox } from "../views/nodes/FunctionPlotBox"; import { ImageBox } from "../views/nodes/ImageBox"; @@ -47,7 +49,9 @@ import { KeyValueBox } from "../views/nodes/KeyValueBox"; import { LabelBox } from "../views/nodes/LabelBox"; import { LinkBox } from "../views/nodes/LinkBox"; import { LinkDescriptionPopup } from "../views/nodes/LinkDescriptionPopup"; +import { MapBox } from "../views/nodes/MapBox/MapBox"; import { PDFBox } from "../views/nodes/PDFBox"; +import { RecordingBox } from "../views/nodes/RecordingBox/RecordingBox"; import { ScreenshotBox } from "../views/nodes/ScreenshotBox"; import { ScriptingBox } from "../views/nodes/ScriptingBox"; import { SliderBox } from "../views/nodes/SliderBox"; @@ -57,12 +61,7 @@ import { PresElementBox } from "../views/nodes/trails/PresElementBox"; import { VideoBox } from "../views/nodes/VideoBox"; import { WebBox } from "../views/nodes/WebBox"; import { SearchBox } from "../views/search/SearchBox"; -import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; -import { IconProp } from "@fortawesome/fontawesome-svg-core"; -import { MapBox } from "../views/nodes/MapBox/MapBox"; -import { RecordingBox } from "../views/nodes/RecordingBox/RecordingBox"; -import { DataViz } from "../views/nodes/DataViz"; const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); class EmptyBox { @@ -519,7 +518,7 @@ export namespace Docs { options: { links: "@links(self)" } }], [DocumentType.DATAVIZ, { - layout: { view: DataViz, dataField: defaultDataKey }, + layout: { view: DataVizBox, dataField: defaultDataKey }, options: { _fitWidth: true, _fitHeight: true, links: "@links(self)" } }] ]); diff --git a/src/client/views/nodes/DataViz.tsx b/src/client/views/nodes/DataViz.tsx index 57c5c0259..a3ffade70 100644 --- a/src/client/views/nodes/DataViz.tsx +++ b/src/client/views/nodes/DataViz.tsx @@ -1,9 +1,9 @@ import React from "react"; +import { ViewBoxBaseComponent } from '../DocComponent'; import "./DataViz.scss"; import { FieldView, FieldViewProps } from "./FieldView"; -import { ViewBoxBaseComponent } from '../DocComponent'; -export class DataViz extends ViewBoxBaseComponent() { +export class DataVizBox extends ViewBoxBaseComponent() { constructor(props: any) { super(props); @@ -11,7 +11,7 @@ export class DataViz extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { - return FieldView.LayoutString(DataViz, fieldKey); + return FieldView.LayoutString(DataVizBox, fieldKey); } render() { diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 8715fc33a..60eef7cfd 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -16,14 +16,15 @@ import { SearchBox } from "../search/SearchBox"; import { DashWebRTCVideo } from "../webcam/DashWebRTCVideo"; import { YoutubeBox } from "./../../apis/youtube/YoutubeBox"; import { AudioBox } from "./AudioBox"; +import { FontIconBox } from "./button/FontIconBox"; import { ColorBox } from "./ColorBox"; import { ComparisonBox } from "./ComparisonBox"; +import { DataVizBox } from "./DataViz"; import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import { EquationBox } from "./EquationBox"; import { FieldView, FieldViewProps } from "./FieldView"; import { FilterBox } from "./FilterBox"; -import { FontIconBox } from "./button/FontIconBox"; import { FormattedTextBox, FormattedTextBoxProps } from "./formattedText/FormattedTextBox"; import { FunctionPlotBox } from "./FunctionPlotBox"; import { ImageBox } from "./ImageBox"; @@ -31,18 +32,17 @@ import { KeyValueBox } from "./KeyValueBox"; import { LabelBox } from "./LabelBox"; import { LinkAnchorBox } from "./LinkAnchorBox"; import { LinkBox } from "./LinkBox"; +import { MapBox } from "./MapBox/MapBox"; import { PDFBox } from "./PDFBox"; -import { PresBox } from "./trails/PresBox"; +import { RecordingBox } from "./RecordingBox"; import { ScreenshotBox } from "./ScreenshotBox"; import { ScriptingBox } from "./ScriptingBox"; import { SliderBox } from "./SliderBox"; +import { PresBox } from "./trails/PresBox"; import { VideoBox } from "./VideoBox"; import { WebBox } from "./WebBox"; import React = require("react"); import XRegExp = require("xregexp"); -import { MapBox } from "./MapBox/MapBox"; -import { RecordingBox } from "./RecordingBox"; -import { DataViz } from "./DataViz"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? @@ -229,8 +229,7 @@ export class DocumentContentsView extends React.Component Date: Tue, 21 Jun 2022 21:51:28 -0400 Subject: fixed rendering error with DataViz --- src/client/views/nodes/DataViz.tsx | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataViz.tsx b/src/client/views/nodes/DataViz.tsx index a3ffade70..d9541dba0 100644 --- a/src/client/views/nodes/DataViz.tsx +++ b/src/client/views/nodes/DataViz.tsx @@ -1,26 +1,21 @@ -import React from "react"; +import { observer } from "mobx-react"; +import * as React from "react"; import { ViewBoxBaseComponent } from '../DocComponent'; import "./DataViz.scss"; import { FieldView, FieldViewProps } from "./FieldView"; +@observer export class DataVizBox extends ViewBoxBaseComponent() { - constructor(props: any) { - super(props); - } - - - public static LayoutString(fieldKey: string) { - return FieldView.LayoutString(DataVizBox, fieldKey); - } + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DataVizBox, fieldKey); } render() { return ( -
-
- Hi +
+
+ Hi +
-
); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 5bf71bb9fde28de8cc2cedaf03708315933acc30 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 22 Jun 2022 13:46:39 -0400 Subject: more cleanup in currentuserutils. fixed so that removing items from a list in code will remove them from the UI --- src/client/documents/Documents.ts | 6 +- src/client/util/CurrentUserUtils.ts | 209 ++++++++++----------- .../views/collections/CollectionStackingView.tsx | 3 +- 3 files changed, 104 insertions(+), 114 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d0c7d2436..01cfe90da 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -708,8 +708,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.PRES), new List(), options); } - export function ScriptingDocument(script: Opt, options: DocumentOptions = {}, fieldKey?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script, + export function ScriptingDocument(script: Opt|null, options: DocumentOptions = {}, fieldKey?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script ? script: undefined, { ...options, layout: fieldKey ? ScriptingBox.LayoutString(fieldKey) : undefined }); } @@ -829,7 +829,7 @@ export namespace Docs { const nwid = options._nativeWidth || undefined; const nhght = options._nativeHeight || undefined; if (!nhght && width && height && nwid) options._nativeHeight = Number(nwid) * Number(height) / Number(width); - return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(url) : undefined, options); + return InstanceFromProto(Prototypes.get(DocumentType.WEB), new WebField(url ? url : "http://www.bing.com/"), options); } export function HtmlDocument(html: string, options: DocumentOptions = {}) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index e119828c7..52fbda9a9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -104,6 +104,7 @@ export class CurrentUserUtils { } }); items?.forEach(item => !DocListCast(doc.data).includes(item) && Doc.AddDocToList(Doc.GetProto(doc), "data", item)); + items && DocListCast(doc.data).forEach(item => !items.includes(item) && Doc.RemoveDocFromList(Doc.GetProto(doc), "data", item)); } return doc; } @@ -148,9 +149,9 @@ export class CurrentUserUtils { return this.AssignScripts(assignBtnAndTempOpts(tempBtn, btnOpts, templateOpts) ?? CurrentUserUtils.createToolButton( {...btnOpts, dragFactory: makeTemp(template(templateOpts))}), reqdScripts); }); - const reqdOpts = { + const reqdOpts:DocumentOptions = { title: "Experimental Tools", _xMargin: 0, _showTitle: "title", _chromeHidden: true, - _stayInCollection: true, _hideContextMenu: true, _forceActive: true, system: true, + _stayInCollection: true, _hideContextMenu: true, _forceActive: true, system: true, childDocumentsActive: true, _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, }; const reqdScripts = { dropConverter : "convertToButtons(dragData)" }; @@ -197,17 +198,12 @@ export class CurrentUserUtils { // setup templates for different document types when they are iconified from Document Decorations static setupDefaultIconTemplates(doc: Doc, field="template-icons") { - const templateIconsDoc = DocCast(doc[field]); + const reqdOpts = { title: "icon templates", _height: 75, system: true }; + const templateIconsDoc = this.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.TreeDocument([], reqdOpts)); const makeIconTemplate = (type: DocumentType | undefined, templateField: string, iconTemplate: () => Doc) => { const iconFieldName = "icon" + (type ? "_" + type : ""); - if (!templateIconsDoc?.[iconFieldName]) { - const template = MakeTemplate(iconTemplate(), true, iconFieldName, templateField); - if (templateIconsDoc) { - templateIconsDoc[iconFieldName] = template; - } - return template; - } + return DocCast(templateIconsDoc[iconFieldName] ?? (templateIconsDoc[iconFieldName] = MakeTemplate(iconTemplate(), true, iconFieldName, templateField))) ; }; const deiconifyScript = () => ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }); const labelBox = (extra: object) => Docs.Create.LabelDocument({ @@ -235,68 +231,37 @@ export class CurrentUserUtils { makeIconTemplate("transcription" as any, "transcription", () => labelBox({ _backgroundColor: "orange" })), // makeIconTemplate(DocumentType.PDF, "icon", () => imageBox("http://www.cs.brown.edu/~bcz/noImage.png", {})) ].filter(d => d).map(d => d!); - - const reqdOpts = { title: "icon templates", _height: 75, system: true }; - this.AssignOpts(templateIconsDoc, reqdOpts, iconTemplates) ?? (doc[field] = Docs.Create.TreeDocument(iconTemplates, reqdOpts)); + this.AssignOpts(DocCast(doc[field]), {}, iconTemplates); } - /// initalizes the set of default versions of most document types + /// initalizes the set of "empty" versions of each document type with default fields. e.g.,. emptyNote, emptyPresentation static creatorBtnDescriptors(doc: Doc): { title: string, toolTip: string, icon: string, ignoreClick?: boolean, dragFactory?: Doc, backgroundColor?: string, clickFactory?: Doc, scripts?: { onClick?: string, onDragStart?: string}, funcs?: {onDragStart?:string, hidden?: string}, }[] { - const standardOps = () => ({ _fitWidth: true, system: true, "dragFactory-count": 0, cloneFieldFilter: new List(["system"]) }); - const emptyThings:{key:string, // the field name where the empty thing will be stored - opts:DocumentOptions, // the document options that are required for the empty thing - funcs?:{[key:string]: any}, // computed fields that are rquired for the empth thing - creator:(opts:DocumentOptions)=> any // how to create the empty thing if it doesn't exist - }[] = [ - {key: "emptyPresentation", creator: Docs.Create.PresDocument, opts: { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias" as any, _chromeHidden: true, boxShadow: "0 0" }}, - {key: "emptyCollection", creator: (opts) => Docs.Create.FreeformDocument([], opts), opts: { title: "freeform", _width: 150, _height: 100 }}, - {key: "emptyPane", creator: (opts) => Docs.Create.FreeformDocument([], opts), opts: { title: "Untitled Tab", _backgroundGridShow: true, _width: 500, _height: 800 }}, - {key: "emptyMath", creator: (opts) => Docs.Create.EquationDocument(opts), opts: { title: "Equation", _backgroundGridShow: true, _width: 300, _height: 35 }}, - {key: "emptySlide", creator: (opts) => Docs.Create.TreeDocument([], opts), funcs: {title: 'self.text?.Text'}, opts: { - _viewType: CollectionViewType.Tree, treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true, - "dragFactory-count": undefined, allowOverlayDrop: true, treeViewType: TreeViewType.outline, _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "white" - }}, - {key: "emptyComparison", creator: Docs.Create.ComparisonDocument, opts: { title: "Comparer", _width: 300, _height: 300 }}, - {key: "emptyScript", creator: (opts) => Docs.Create.ScriptingDocument(undefined, opts), opts: { title: "script", _width: 200, _height: 250, }}, - {key: "emptyScreenshot", creator: Docs.Create.ScreenshotDocument, opts: { title: "empty screenshot", _width: 400, _height: 200 }}, - {key: "emptyWebCam", creator: (opts) => Docs.Create.WebCamDocument("", opts), opts: { _width: 400, _height: 200, title: "recording", recording:true, system: true, cloneFieldFilter: new List(["system"]) }}, - {key: "emptyAudio", creator: (opts) => Docs.Create.AudioDocument(nullAudio, opts), opts: { title: "audio recording", x: 200, y: 200, _width: 200, _height: 100, }}, - {key: "emptyNote", creator: (opts) => Docs.Create.TextDocument("", opts), opts: { title: "text note", _width: 200, _autoHeight: true }}, - {key: "emptyButton", creator: Docs.Create.ButtonDocument, opts: { title: "Button", _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, }}, - {key: "emptyWebpage", creator: (opts) => Docs.Create.WebDocument("http://www.bing.com/", opts), opts: { title: "webpage", _nativeWidth: 850, _height: 512, _width: 400, useCors: true, }}, - {key: "emptyMap", creator: (opts) => Docs.Create.MapDocument([], opts), opts: { title: "map", _showSidebar: true, _width: 800, _height: 600, }}, - {key: "emptyDataViz", creator: (opts) => Docs.Create.DataVizDocument(opts), opts: { title: "DataViz", _width: 300, _height: 300 }}, - ]; - - emptyThings.forEach(thing => - this.AssignScripts(this.AssignOpts(DocCast(doc[thing.key]), {...standardOps(), ...thing.opts}) ?? (doc[thing.key] = thing.creator({...standardOps(), ...thing.opts})), undefined, thing.funcs)) - - if (doc.emptyHeader === undefined) { - const json = { - doc: { - type: "doc", - content: [ - { - type: "paragraph", attrs: {}, content: [{ - type: "dashField", - attrs: { fieldKey: "author", docid: "", hideKey: false }, - marks: [{ type: "strong" }] - }, { - type: "dashField", - attrs: { fieldKey: "creationDate", docid: "", hideKey: false }, - marks: [{ type: "strong" }] - }] + const standardOps = (key:string) => ({ title : "Untitled "+ key, _fitWidth: true, system: true, "dragFactory-count": 0, cloneFieldFilter: new List(["system"]) }); + const json = { + doc: { + type: "doc", + content: [ + { + type: "paragraph", attrs: {}, content: [{ + type: "dashField", + attrs: { fieldKey: "author", docid: "", hideKey: false }, + marks: [{ type: "strong" }] + }, { + type: "dashField", + attrs: { fieldKey: "creationDate", docid: "", hideKey: false }, + marks: [{ type: "strong" }] }] - }, - selection: { type: "text", anchor: 1, head: 1 }, - storedMarks: [] - }; - const headerBtnHgt = 10; - const headerTemplate = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), { - ...standardOps(), title: "text", _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, + }] + }, + selection: { type: "text", anchor: 1, head: 1 }, + storedMarks: [] + }; + const headerBtnHgt = 10; + const headerTemplate = (opts:DocumentOptions) => { + const header = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), { ...opts, title: "text", layout: "" + ` ` + @@ -309,28 +274,57 @@ export class CurrentUserUtils { // " " + // " " + // "
"; - Doc.GetProto(headerTemplate).isTemplateDoc = makeTemplate(Doc.GetProto(headerTemplate), true, "headerView"); - doc.emptyHeader = headerTemplate; + Doc.GetProto(header).isTemplateDoc = makeTemplate(Doc.GetProto(header), true, "headerView"); + Doc.GetProto(header).title = "Untitled Header"; + return header; } + const emptyThings:{key:string, // the field name where the empty thing will be stored + opts:DocumentOptions, // the document options that are required for the empty thing + funcs?:{[key:string]: any}, // computed fields that are rquired for the empth thing + creator:(opts:DocumentOptions)=> any // how to create the empty thing if it doesn't exist + }[] = [ + {key: "Note", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _autoHeight: true }}, + {key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 150, _height: 100 }}, + {key: "Equation", creator: opts => Docs.Create.EquationDocument(opts), opts: { _width: 300, _height: 35, _backgroundGridShow: true, }}, + {key: "Webpage", creator: opts => Docs.Create.WebDocument("",opts), opts: { _width: 400, _height: 512, _nativeWidth: 850, useCors: true, }}, + {key: "Comparison", creator: Docs.Create.ComparisonDocument, opts: { _width: 300, _height: 300 }}, + {key: "Audio", creator: opts => Docs.Create.AudioDocument(nullAudio, opts),opts: { _width: 200, _height: 100, }}, + {key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _showSidebar: true, }}, + {key: "Screengrab", creator: Docs.Create.ScreenshotDocument, opts: { _width: 400, _height: 200 }}, + {key: "WebCam", creator: opts => Docs.Create.WebCamDocument("", opts), opts: { _width: 400, _height: 200, title: "recording", recording:true, system: true, cloneFieldFilter: new List(["system"]) }}, + {key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, }}, + {key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }}, + {key: "DataViz", creator: opts => Docs.Create.DataVizDocument(opts), opts: { _width: 300, _height: 300 }}, + {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true,}}, + {key: "Presentation",creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 500, _viewType: CollectionViewType.Stacking, targetDropAction: "alias" as any, _chromeHidden: true, boxShadow: "0 0" }}, + {key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _backgroundGridShow: true, }}, + {key: "Slide", creator: opts => Docs.Create.TreeDocument([], opts), opts: { _width: 300, _height: 200, _viewType: CollectionViewType.Tree, + treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true, + allowOverlayDrop: true, treeViewType: TreeViewType.outline, + backgroundColor: "white", _xMargin: 0, _yMargin: 0, _singleLine: true + }, funcs: {title: 'self.text?.Text'}}, + ]; + + emptyThings.forEach(thing => + this.AssignScripts(this.AssignOpts(DocCast(doc["empty"+thing.key]), {...standardOps(thing.key), ...thing.opts}) ?? (doc["empty"+thing.key] = thing.creator({...standardOps(thing.key), ...thing.opts})), undefined, thing.funcs)) + return [ - { toolTip: "Tap or drag to create a note", title: "Note", icon: "sticky-note", dragFactory: doc.emptyNote as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, }, - { toolTip: "Tap or drag to create a collection", title: "Col", icon: "folder", dragFactory: doc.emptyCollection as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.clickFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, clickFactory: doc.emptyPane as Doc, }, - { toolTip: "Tap or drag to create an equation", title: "Math", icon: "calculator", dragFactory: doc.emptyMath as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.clickFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, }, - { toolTip: "Tap or drag to create a webpage", title: "Web", icon: "globe-asia", dragFactory: doc.emptyWebpage as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, }, - { toolTip: "Tap or drag to create a comparison box", title: "Compare", icon: "columns", dragFactory: doc.emptyComparison as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, }, - { toolTip: "Tap or drag to create an audio recorder", title: "Audio", icon: "microphone", dragFactory: doc.emptyAudio as Doc, scripts: {onClick: 'openInOverlay(copyDragFactory(this.dragFactory))',onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, }, - { toolTip: "Tap or drag to create a map", title: "Map", icon: "map-marker-alt", dragFactory: doc.emptyMap as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, }, - { toolTip: "Tap or drag to create a custom note", title: "Custom", icon: "window-maximize", dragFactory: doc.emptyHeader as Doc, scripts: {onClick: 'openOnRight(delegateDragFactory(this.dragFactory))', onDragStart: '{ return delegateDragFactory(this.dragFactory);}'}, }, - { toolTip: "Tap or drag to create a progressive slide",title: "Slide", icon: "file", dragFactory: doc.emptySlide as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, funcs: { hidden: 'IsNoviceMode()'} }, - { toolTip: "Tap or drag to create a screen grabber", title: "Grab", icon: "photo-video", dragFactory: doc.emptyScreenshot as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, funcs: { hidden: 'IsNoviceMode()'} }, - { toolTip: "Tap or drag to create a WebCam recorder", title: "WebCam", icon: "photo-video", dragFactory: doc.emptyWebCam as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, funcs: { hidden: 'IsNoviceMode()'}}, - { toolTip: "Tap or drag to create a button", title: "Button", icon: "bolt", dragFactory: doc.emptyButton as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, funcs:{ hidden: 'IsNoviceMode()'} }, - { toolTip: "Tap or drag to create a scripting box", title: "Script", icon: "terminal", dragFactory: doc.emptyScript as Doc, scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, funcs: { hidden: 'IsNoviceMode()'}}, - { toolTip: "Tap or drag to create a mobile view", title: "Phone", icon: "mobile", dragFactory: doc.activeMobileMenu as Doc, scripts: {onClick: 'openOnRight(Doc.UserDoc().activeMobileMenu)', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, funcs: {hidden: 'IsNoviceMode()'} }, - { toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "file", dragFactory: doc.emptyDataViz as Doc, scripts: {onClick: 'openOnRight(Doc.UserDoc().activeMobileMenu)', onDragStart: '{ return copyDragFactory(this.dragFactory);}'} }, + { toolTip: "Tap or drag to create a note", title: "Note", icon: "sticky-note", dragFactory: doc.emptyNote as Doc, }, + { toolTip: "Tap or drag to create a collection", title: "Col", icon: "folder", dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab), scripts: { onClick: 'openOnRight(copyDragFactory(this.clickFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, }, + { toolTip: "Tap or drag to create an equation", title: "Math", icon: "calculator", dragFactory: doc.emptyEquation as Doc, }, + { toolTip: "Tap or drag to create a webpage", title: "Web", icon: "globe-asia", dragFactory: doc.emptyWebpage as Doc, }, + { toolTip: "Tap or drag to create a comparison box", title: "Compare", icon: "columns", dragFactory: doc.emptyComparison as Doc, }, + { toolTip: "Tap or drag to create an audio recorder", title: "Audio", icon: "microphone", dragFactory: doc.emptyAudio as Doc, }, + { toolTip: "Tap or drag to create a map", title: "Map", icon: "map-marker-alt", dragFactory: doc.emptyMap as Doc, }, + { toolTip: "Tap or drag to create a screen grabber", title: "Grab", icon: "photo-video", dragFactory: doc.emptyScreengrab as Doc, funcs: { hidden: 'IsNoviceMode()'} }, + { toolTip: "Tap or drag to create a WebCam recorder", title: "WebCam", icon: "photo-video", dragFactory: doc.emptyWebCam as Doc, funcs: { hidden: 'IsNoviceMode()'}}, + { toolTip: "Tap or drag to create a button", title: "Button", icon: "bolt", dragFactory: doc.emptyButton as Doc, funcs: { hidden: 'IsNoviceMode()'} }, + { toolTip: "Tap or drag to create a scripting box", title: "Script", icon: "terminal", dragFactory: doc.emptyScript as Doc, funcs: { hidden: 'IsNoviceMode()'}}, + { toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "file", dragFactory: doc.emptyDataViz as Doc, }, + { toolTip: "Tap or drag to create a data note", title: "DataNote", icon: "window-maximize", dragFactory: doc.emptyHeader as Doc, scripts: {onClick: 'openOnRight(delegateDragFactory(this.dragFactory))', onDragStart: '{ return delegateDragFactory(this.dragFactory);}'}, }, { toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", scripts: {onClick: 'addOverlayWindow("ScriptingRepl", { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" })' } }, - ]; + ].map(tuple => ({scripts: {onClick: 'openOnRight(copyDragFactory(this.dragFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, ...tuple, })) } /// Initalizes the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools @@ -345,9 +339,10 @@ export class CurrentUserUtils { return this.AssignScripts(this.AssignOpts(btn, opts) ?? Docs.Create.FontIconDocument(opts), reqdOpts.scripts, reqdOpts.funcs); }); - const reqdOpts = { + const reqdOpts:DocumentOptions = { title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, system: true, _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, + childDocumentsActive: true }; const reqdScripts = { dropConverter: "convertToButtons(dragData)" }; return this.AssignScripts(this.AssignOpts(dragCreatorDoc, reqdOpts, creatorBtns) ?? Docs.Create.MasonryDocument(creatorBtns, reqdOpts), reqdScripts); @@ -357,34 +352,26 @@ export class CurrentUserUtils { static leftSidebarMenuBtnDescriptions(doc: Doc):{title:string, target:Doc, icon:string, scripts:{[key:string]:any}, funcs?:{[key:string]:any}}[] { const badgeValue = "((len) => len && len !== '0' ? len: undefined)(docList(self.target.data).filter(doc => !docList(self.target.viewed).includes(doc)).length.toString())"; return [ - { title: "Dashboards", target: CurrentUserUtils.MyDashboards, icon: "desktop", scripts:{onClick: 'selectMainMenu(self)'} }, - { title: "Search", target: CurrentUserUtils.MySearcher, icon: "search", scripts:{onClick: 'selectMainMenu(self)'} }, - { title: "Files", target: CurrentUserUtils.MyFilesystem, icon: "folder-open", scripts:{onClick: 'selectMainMenu(self)'} }, - { title: "Tools", target: CurrentUserUtils.MyTools, icon: "wrench", scripts:{onClick: 'selectMainMenu(self)'}, funcs: {hidden: "IsNoviceMode()"} }, - { title: "Imports", target: CurrentUserUtils.MyImports, icon: "upload", scripts:{onClick: 'selectMainMenu(self)'} }, - { title: "Recently Closed", target: CurrentUserUtils.MyRecentlyClosed, icon: "archive", scripts:{onClick: 'selectMainMenu(self)'} }, - { title: "Shared with me", target: CurrentUserUtils.MySharedDocs, icon: "users", scripts:{onClick: 'selectMainMenu(self)'}, funcs:{badgeValue:badgeValue}}, - { title: "Trails", target: CurrentUserUtils.MyTrails, icon: "pres-trail", scripts:{onClick: 'selectMainMenu(self)'} }, - { title: "User Doc", target: CurrentUserUtils.MyUserDocView, icon: "address-card",scripts:{onClick: 'selectMainMenu(self)'}, funcs: {hidden: "IsNoviceMode()"} }, - ]; + { title: "Dashboards", target: this.setupDashboards(doc, "myDashboards"), icon: "desktop", }, + { title: "Search", target: this.setupSearcher(doc, "mySearcher"), icon: "search", }, + { title: "Files", target: this.setupFilesystem(doc, "myFilesystem"), icon: "folder-open", }, + { title: "Tools", target: this.setupToolsBtnPanel(doc, "myTools"), icon: "wrench", funcs: {hidden: "IsNoviceMode()"} }, + { title: "Imports", target: this.setupImportSidebar(doc, "myImports"), icon: "upload", }, + { title: "Recently Closed", target: this.setupRecentlyClosed(doc, "myRecentlyClosed"), icon: "archive", }, + { title: "Shared Docs", target: this.MySharedDocs, icon: "users", funcs:{badgeValue:badgeValue}}, + { title: "Trails", target: this.setupTrails(doc, "myTrails"), icon: "pres-trail", }, + { title: "User Doc View", target: this.setupUserDocView(doc, "myUserDocView"), icon: "address-card",funcs: {hidden: "IsNoviceMode()"} }, + ].map(tuple => ({...tuple, scripts:{onClick: 'selectMainMenu(self)'}})); } - /// setup the left sidebar container and panels that can be displayed within it + /// the empty panel that is filled with whichever left menu button's panel has been selected static setupLeftSidebarPanel(doc: Doc, field="myLeftSidebarPanel") { this.AssignOpts(DocCast(doc[field]), {}) ?? (doc[field] = ((doc:Doc) => {doc.system = true; return doc;})(new Doc())); - CurrentUserUtils.setupSearcher(doc, "mySearcher"); - CurrentUserUtils.setupToolsBtnPanel(doc, "myTools"); - CurrentUserUtils.setupImportSidebar(doc, "myImports"); - CurrentUserUtils.setupDashboards(doc, "myDashboards"); - CurrentUserUtils.setupTrails(doc, "myTrails"); - CurrentUserUtils.setupFilesystem(doc, "myFilesystem"); - CurrentUserUtils.setupRecentlyClosedDocs(doc, "myRecentlyClosed"); - CurrentUserUtils.setupUserDocView(doc, "myUserDocView"); } /// Initializes the left sidebar menu buttons and the panels they open up static setupLeftSidebarMenu(doc: Doc, field="myLeftSidebarMenu") { - this.setupLeftSidebarPanel(doc); // the tools/panels opened up by the menu buttons + this.setupLeftSidebarPanel(doc); const myLeftSidebarMenu = DocCast(doc[field]); const menuBtns = CurrentUserUtils.leftSidebarMenuBtnDescriptions(doc).map(({ title, target, icon, scripts, funcs }) => { const btnDoc = myLeftSidebarMenu ? DocListCast(myLeftSidebarMenu.data).find(doc => doc.title === title) : undefined; @@ -520,7 +507,7 @@ export class CurrentUserUtils { dontRegisterView: true, backgroundColor: "dimgray", ignoreClick: true, title: "Search Panel", system: true, childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, _searchDoc: true, }; - this.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.SearchDocument(reqdOpts)); + return this.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.SearchDocument(reqdOpts)); } /// Initializes the panel of draggable tools that is opened from the left sidebar. @@ -532,7 +519,7 @@ export class CurrentUserUtils { title: "My Tools", system: true, ignoreClick: true, boxShadow: "0 0", _showTitle: "title", _width: 500, _yMargin: 20, _lockedPosition: true, _forceActive: true, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, }; - this.AssignOpts(myTools, reqdToolOps, [creatorBtns, templateBtns]) ?? (doc[field] = Docs.Create.StackingDocument([creatorBtns, templateBtns], reqdToolOps)); + return this.AssignOpts(myTools, reqdToolOps, [creatorBtns, templateBtns]) ?? (doc[field] = Docs.Create.StackingDocument([creatorBtns, templateBtns], reqdToolOps)); } /// initializes the left sidebar dashboard pane @@ -595,6 +582,7 @@ export class CurrentUserUtils { if (Cast(myTrails.contextMenuScripts, listSpec(ScriptField), null)?.length !== contextMenuScripts.length) { myTrails.contextMenuScripts = new List(contextMenuScripts.map(script => ScriptField.MakeFunction(script)!)); } + return myTrails; } /// initializes the left sidebar File system pane @@ -624,10 +612,11 @@ export class CurrentUserUtils { if (Cast(myFilesystem.childContextMenuScripts, listSpec(ScriptField), null)?.length !== childContextMenuScripts.length) { myFilesystem.childContextMenuScripts = new List(childContextMenuScripts.map(script => ScriptField.MakeFunction(script)!)); } + return myFilesystem; } /// initializes the panel displaying docs that have been recently closed - static setupRecentlyClosedDocs(doc: Doc, field:string) { + static setupRecentlyClosed(doc: Doc, field:string) { const reqdOpts:DocumentOptions = { _showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, title: "My Recently Closed", buttonMenu: true, childHideLinkButton: true, treeViewHideTitle: true, childDropAction: "alias", system: true, treeViewTruncateTitleWidth: 150, ignoreClick: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", @@ -651,6 +640,7 @@ export class CurrentUserUtils { if (!Cast(recentlyClosed.contextMenuScripts, listSpec(ScriptField),null)?.find((script) => script.script.originalScript === clearAll("self"))) { recentlyClosed.contextMenuScripts = new List([ScriptField.MakeScript(clearAll("self"))!]) } + return recentlyClosed; } /// creates a new, empty filter doc @@ -674,7 +664,7 @@ export class CurrentUserUtils { treeViewHideTitle: true, treeViewTruncateTitleWidth: 150 }; if (!doc[field]) this.AssignOpts(doc, {treeViewOpen: true, treeViewExpandedView: "fields" }) - this.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.TreeDocument([doc], reqdOpts)); + return this.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.TreeDocument([doc], reqdOpts)); } static linearButtonList = (title: string, opts: DocumentOptions, docs: Doc[]) => Docs.Create.LinearDocument(docs, { @@ -903,7 +893,7 @@ export class CurrentUserUtils { buttonText: "Import", icon: "upload", system: true }; const reqdBtnScripts = { onClick: "importDocument()" }; const newImportBtn = this.AssignOpts(DocCast(myImports.buttonMenuDoc), reqdBtnOpts) ?? (myImports.buttonMenuDoc = Docs.Create.FontIconDocument(reqdBtnOpts)); - this.AssignScripts(newImportBtn, reqdBtnScripts); + return this.AssignScripts(newImportBtn, reqdBtnScripts); } static setupClickEditorTemplates(doc: Doc) { @@ -1055,7 +1045,6 @@ export class CurrentUserUtils { } 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 ? (CurrentUserUtils.ActiveDashboard = doc) : (CurrentUserUtils.GuestDashboard = doc); } const state = CurrentUserUtils._urlState; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 684c919bd..4e8c14039 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -229,6 +229,7 @@ export class CollectionStackingView extends CollectionSubView this.props.isSelected() || this.props.isContentActive(); + isChildContentActive = () => this.props.isDocumentActive?.() && (this.props.childDocumentsActive?.() || BoolCast(this.rootDoc.childDocumentsActive)); getDisplayDoc(doc: Doc, width: () => number) { const dataDoc = (!doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS) ? undefined : this.props.DataDoc; const height = () => this.getDocHeight(doc); @@ -245,7 +246,7 @@ export class CollectionStackingView extends CollectionSubView