diff options
author | Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com> | 2022-06-30 10:16:41 -0700 |
---|---|---|
committer | Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com> | 2022-06-30 10:16:41 -0700 |
commit | a01f3541a40f119dbfd73236dbd5f99de9d78ff7 (patch) | |
tree | 2813c26bebc1c5c0116ff7c492061dc6420cf4e1 /src | |
parent | 8d88e7418ec0fb2a4afe71417fa1eb34c1e1060f (diff) |
added .prettierignore file
Note that .prettierignore is formatted the same way as .gitignore
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 2735 |
1 files changed, 2085 insertions, 650 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2a0702a58..a7b24c426 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1,43 +1,61 @@ -import { computed, observable, reaction } from "mobx"; +import { computed, observable, reaction } from 'mobx'; import * as rp from 'request-promise'; -import { DataSym, Doc, DocListCast, DocListCastAsync, Opt } from "../../fields/Doc"; -import { Id } from "../../fields/FieldSymbols"; -import { InkTool } from "../../fields/InkField"; -import { List } from "../../fields/List"; -import { PrefetchProxy } from "../../fields/Proxy"; -import { RichTextField } from "../../fields/RichTextField"; -import { listSpec } from "../../fields/Schema"; -import { ComputedField, ScriptField } from "../../fields/ScriptField"; -import { Cast, DateCast, DocCast, FieldValue, NumCast, PromiseValue, ScriptCast, StrCast } from "../../fields/Types"; -import { ImageField, nullAudio } from "../../fields/URLField"; -import { SharingPermissions } from "../../fields/util"; -import { OmitKeys, Utils } from "../../Utils"; -import { DocServer } from "../DocServer"; -import { Docs, DocumentOptions, DocUtils, FInfo } from "../documents/Documents"; -import { DocumentType } from "../documents/DocumentTypes"; -import { CollectionDockingView } from "../views/collections/CollectionDockingView"; -import { CollectionFreeFormView } from "../views/collections/collectionFreeForm"; -import { TreeViewType } from "../views/collections/CollectionTreeView"; -import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; -import { TreeView } from "../views/collections/TreeView"; -import { Colors } from "../views/global/globalEnums"; -import { MainView } from "../views/MainView"; -import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox"; -import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView"; -import { DocumentView } from "../views/nodes/DocumentView"; -import { OverlayView } from "../views/OverlayView"; -import { DocumentManager } from "./DocumentManager"; -import { DragManager } from "./DragManager"; -import { makeTemplate, MakeTemplate } from "./DropConverter"; -import { HistoryUtil } from "./History"; -import { LinkManager } from "./LinkManager"; -import { ScriptingGlobals } from "./ScriptingGlobals"; -import { SearchUtil } from "./SearchUtil"; -import { SelectionManager } from "./SelectionManager"; -import { ColorScheme } from "./SettingsManager"; -import { SharingManager } from "./SharingManager"; -import { SnappingManager } from "./SnappingManager"; -import { UndoManager } from "./UndoManager"; +import { + DataSym, + Doc, + DocListCast, + DocListCastAsync, + Opt, +} from '../../fields/Doc'; +import { Id } from '../../fields/FieldSymbols'; +import { InkTool } from '../../fields/InkField'; +import { List } from '../../fields/List'; +import { PrefetchProxy } from '../../fields/Proxy'; +import { RichTextField } from '../../fields/RichTextField'; +import { listSpec } from '../../fields/Schema'; +import { ComputedField, ScriptField } from '../../fields/ScriptField'; +import { + Cast, + DateCast, + DocCast, + FieldValue, + NumCast, + PromiseValue, + ScriptCast, + StrCast, +} from '../../fields/Types'; +import { ImageField, nullAudio } from '../../fields/URLField'; +import { SharingPermissions } from '../../fields/util'; +import { OmitKeys, Utils } from '../../Utils'; +import { DocServer } from '../DocServer'; +import { Docs, DocumentOptions, DocUtils, FInfo } from '../documents/Documents'; +import { DocumentType } from '../documents/DocumentTypes'; +import { CollectionDockingView } from '../views/collections/CollectionDockingView'; +import { CollectionFreeFormView } from '../views/collections/collectionFreeForm'; +import { TreeViewType } from '../views/collections/CollectionTreeView'; +import { + CollectionView, + CollectionViewType, +} from '../views/collections/CollectionView'; +import { TreeView } from '../views/collections/TreeView'; +import { Colors } from '../views/global/globalEnums'; +import { MainView } from '../views/MainView'; +import { ButtonType, NumButtonType } from '../views/nodes/button/FontIconBox'; +import { CollectionFreeFormDocumentView } from '../views/nodes/CollectionFreeFormDocumentView'; +import { DocumentView } from '../views/nodes/DocumentView'; +import { OverlayView } from '../views/OverlayView'; +import { DocumentManager } from './DocumentManager'; +import { DragManager } from './DragManager'; +import { makeTemplate, MakeTemplate } from './DropConverter'; +import { HistoryUtil } from './History'; +import { LinkManager } from './LinkManager'; +import { ScriptingGlobals } from './ScriptingGlobals'; +import { SearchUtil } from './SearchUtil'; +import { SelectionManager } from './SelectionManager'; +import { ColorScheme } from './SettingsManager'; +import { SharingManager } from './SharingManager'; +import { SnappingManager } from './SnappingManager'; +import { UndoManager } from './UndoManager'; interface Button { // DocumentOptions fields a button can set @@ -55,21 +73,29 @@ interface Button { buttonText?: string; // fields that do not correspond to DocumentOption fields - scripts?: { script?: string; onClick?: string; } - funcs?: { [key:string]: string }; + scripts?: { script?: string; onClick?: string }; + funcs?: { [key: string]: string }; subMenu?: Button[]; } -export let resolvedPorts: { server: number, socket: number }; +export let resolvedPorts: { server: number; socket: number }; export class CurrentUserUtils { private static curr_id: string; //TODO tfs: these should be temporary... private static mainDocId: string | undefined; - public static get id() { return this.curr_id; } - public static get MainDocId() { return this.mainDocId; } - public static set MainDocId(id: string | undefined) { this.mainDocId = id; } - @computed public static get UserDocument() { return Doc.UserDoc(); } + public static get id() { + return this.curr_id; + } + public static get MainDocId() { + return this.mainDocId; + } + public static set MainDocId(id: string | undefined) { + this.mainDocId = id; + } + @computed public static get UserDocument() { + return Doc.UserDoc(); + } @observable public static GuestTarget: Doc | undefined; @observable public static GuestDashboard: Doc | undefined; @@ -78,151 +104,393 @@ export class CurrentUserUtils { @observable public static headerBarHeight: number = 0; @observable public static searchPanelWidth: number = 0; - static AssignScripts(doc:Doc, scripts?:{ [key: string]: string;}, funcs?:{[key:string]: string}) { - scripts && Object.keys(scripts).map(key => { - if (ScriptCast(doc[key])?.script.originalScript !== scripts[key] && scripts[key]) { - doc[key] = ScriptField.MakeScript(scripts[key], { dragData: DragManager.DocumentDragData.name, value:"any", scriptContext: "any", documentView:Doc.name}, {"_readOnly_": true}); - } - }); - funcs && Object.keys(funcs).map(key => { - const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); - if (ScriptCast(cfield)?.script.originalScript !== funcs[key] && funcs[key]) { - doc[key] = ComputedField.MakeFunction(funcs[key], { dragData: DragManager.DocumentDragData.name }, {"_readOnly_": true}); - } - }); + static AssignScripts( + doc: Doc, + scripts?: { [key: string]: string }, + funcs?: { [key: string]: string } + ) { + scripts && + Object.keys(scripts).map((key) => { + if ( + ScriptCast(doc[key])?.script.originalScript !== + scripts[key] && + scripts[key] + ) { + doc[key] = ScriptField.MakeScript( + scripts[key], + { + dragData: DragManager.DocumentDragData.name, + value: 'any', + scriptContext: 'any', + documentView: Doc.name, + }, + { _readOnly_: true } + ); + } + }); + funcs && + Object.keys(funcs).map((key) => { + const cfield = ComputedField.WithoutComputed(() => + FieldValue(doc[key]) + ); + if ( + ScriptCast(cfield)?.script.originalScript !== funcs[key] && + funcs[key] + ) { + doc[key] = ComputedField.MakeFunction( + funcs[key], + { dragData: DragManager.DocumentDragData.name }, + { _readOnly_: true } + ); + } + }); return doc; } - static AssignOpts(doc:Doc|undefined, reqdOpts:DocumentOptions, items?:Doc[]) { + static AssignOpts( + doc: Doc | undefined, + reqdOpts: DocumentOptions, + items?: Doc[] + ) { if (doc) { - const compareValues = (val1:any, val2:any) => { - if (val1 instanceof List && val2 instanceof List && val1.length === val2.length) { - return !val1.some(v => !val2.includes(v)) || !val2.some(v => val1.includes(v)); + const compareValues = (val1: any, val2: any) => { + if ( + val1 instanceof List && + val2 instanceof List && + val1.length === val2.length + ) { + return ( + !val1.some((v) => !val2.includes(v)) || + !val2.some((v) => val1.includes(v)) + ); } return val1 === val2; - } - Object.entries(reqdOpts).forEach(pair => { - const targetDoc = pair[0].startsWith("_") ? doc : Doc.GetProto(doc as Doc); - if (!Object.getOwnPropertyNames(targetDoc).includes(pair[0].replace(/^_/,"")) || - !compareValues(pair[1], targetDoc[pair[0]])) { + }; + Object.entries(reqdOpts).forEach((pair) => { + const targetDoc = pair[0].startsWith('_') + ? doc + : Doc.GetProto(doc as Doc); + if ( + !Object.getOwnPropertyNames(targetDoc).includes( + pair[0].replace(/^_/, '') + ) || + !compareValues(pair[1], targetDoc[pair[0]]) + ) { targetDoc[pair[0]] = pair[1]; } }); - 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)); + 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; } - static AssignDocField(doc:Doc, field:string, creator:(reqdOpts:DocumentOptions, items?:Doc[]) => Doc, reqdOpts:DocumentOptions, items?: Doc[], scripts?:{[key:string]:string}, funcs?:{[key:string]:string}) { - return this.AssignScripts(this.AssignOpts(DocCast(doc[field]), reqdOpts, items) ?? (doc[field] = creator(reqdOpts, items)), scripts, funcs); + static AssignDocField( + doc: Doc, + field: string, + creator: (reqdOpts: DocumentOptions, items?: Doc[]) => Doc, + reqdOpts: DocumentOptions, + items?: Doc[], + scripts?: { [key: string]: string }, + funcs?: { [key: string]: string } + ) { + return this.AssignScripts( + this.AssignOpts(DocCast(doc[field]), reqdOpts, items) ?? + (doc[field] = creator(reqdOpts, items)), + scripts, + funcs + ); } // initializes experimental advanced template views - slideView, headerView - static setupExperimentalTemplateButtons(doc: Doc, tempDocs?:Doc) { - const requiredTypeNameFields:{btnOpts:DocumentOptions, templateOpts:DocumentOptions, template:(opts:DocumentOptions) => Doc}[] = [ + static setupExperimentalTemplateButtons(doc: Doc, tempDocs?: Doc) { + const requiredTypeNameFields: { + btnOpts: DocumentOptions; + templateOpts: DocumentOptions; + template: (opts: DocumentOptions) => Doc; + }[] = [ { - btnOpts: { title: "slide", icon: "address-card" }, - templateOpts: { _width: 400, _height: 300, title: "slideView", childDocumentsActive: true, _xMargin: 3, _yMargin: 3, system: true }, - template: (opts:DocumentOptions) => Docs.Create.MultirowDocument( - [ - Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }), - Docs.Create.TextDocument("", { title: "text", _fitWidth:true, _height: 100, system: true, _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize) }) - ], opts) + btnOpts: { title: 'slide', icon: 'address-card' }, + templateOpts: { + _width: 400, + _height: 300, + title: 'slideView', + childDocumentsActive: true, + _xMargin: 3, + _yMargin: 3, + system: true, + }, + template: (opts: DocumentOptions) => + Docs.Create.MultirowDocument( + [ + Docs.Create.MulticolumnDocument([], { + title: 'data', + _height: 200, + system: true, + }), + Docs.Create.TextDocument('', { + title: 'text', + _fitWidth: true, + _height: 100, + system: true, + _fontFamily: StrCast(Doc.UserDoc()._fontFamily), + _fontSize: StrCast(Doc.UserDoc()._fontSize), + }), + ], + opts + ), }, { - btnOpts: { title: "mobile", icon: "mobile" }, - templateOpts: { title: "NEW MOBILE BUTTON", onClick: undefined, }, - template: (opts:DocumentOptions) => this.mobileButton(opts, - [this.createToolButton({ ignoreClick: true, icon: "mobile", backgroundColor: "transparent" }), - this.mobileTextContainer({}, - [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")]) - ] - ) + btnOpts: { title: 'mobile', icon: 'mobile' }, + templateOpts: { + title: 'NEW MOBILE BUTTON', + onClick: undefined, + }, + template: (opts: DocumentOptions) => + this.mobileButton(opts, [ + this.createToolButton({ + ignoreClick: true, + icon: 'mobile', + backgroundColor: 'transparent', + }), + this.mobileTextContainer({}, [ + this.mobileButtonText({}, 'NEW MOBILE BUTTON'), + this.mobileButtonInfo( + {}, + 'You can customize this button and make it your own.' + ), + ]), + ]), }, ]; - const requiredTypes = requiredTypeNameFields.map(({ btnOpts, template, templateOpts }) => { - const tempBtn = DocListCast(tempDocs?.data)?.find(doc => doc.title === btnOpts.title); - const reqdScripts = { onDragStart: '{ return copyDragFactory(this.dragFactory); }' }; - const assignBtnAndTempOpts = (templateBtn:Opt<Doc>, btnOpts:DocumentOptions, templateOptions:DocumentOptions) => { - if (templateBtn) { - this.AssignOpts(templateBtn,btnOpts); - this.AssignDocField(templateBtn, "dragFactory", opts => template(opts), templateOptions); - } - return templateBtn; - }; - const makeTemp = (doc:Doc) => { - doc.isTemplateDoc = makeTemplate(doc); - return doc; + const requiredTypes = requiredTypeNameFields.map( + ({ btnOpts, template, templateOpts }) => { + const tempBtn = DocListCast(tempDocs?.data)?.find( + (doc) => doc.title === btnOpts.title + ); + const reqdScripts = { + onDragStart: + '{ return copyDragFactory(this.dragFactory); }', + }; + const assignBtnAndTempOpts = ( + templateBtn: Opt<Doc>, + btnOpts: DocumentOptions, + templateOptions: DocumentOptions + ) => { + if (templateBtn) { + this.AssignOpts(templateBtn, btnOpts); + this.AssignDocField( + templateBtn, + 'dragFactory', + (opts) => template(opts), + templateOptions + ); + } + return templateBtn; + }; + const makeTemp = (doc: Doc) => { + doc.isTemplateDoc = makeTemplate(doc); + return doc; + }; + return this.AssignScripts( + assignBtnAndTempOpts(tempBtn, btnOpts, templateOpts) ?? + this.createToolButton({ + ...btnOpts, + dragFactory: makeTemp(template(templateOpts)), + }), + reqdScripts + ); } - return this.AssignScripts(assignBtnAndTempOpts(tempBtn, btnOpts, templateOpts) ?? this.createToolButton( {...btnOpts, dragFactory: makeTemp(template(templateOpts))}), reqdScripts); - }); + ); - const reqdOpts:DocumentOptions = { - title: "Experimental Tools", _xMargin: 0, _showTitle: "title", _chromeHidden: 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 reqdOpts: DocumentOptions = { + title: 'Experimental Tools', + _xMargin: 0, + _showTitle: 'title', + _chromeHidden: 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)" }; - const reqdFuncs = { hidden: "IsNoviceMode()" }; - return this.AssignScripts(this.AssignOpts(tempDocs, reqdOpts, requiredTypes) ?? Docs.Create.MasonryDocument(requiredTypes, reqdOpts), reqdScripts, reqdFuncs); + const reqdScripts = { dropConverter: 'convertToButtons(dragData)' }; + const reqdFuncs = { hidden: 'IsNoviceMode()' }; + return this.AssignScripts( + this.AssignOpts(tempDocs, reqdOpts, requiredTypes) ?? + Docs.Create.MasonryDocument(requiredTypes, reqdOpts), + reqdScripts, + reqdFuncs + ); } /// Initializes templates that can be applied to notes - static setupNoteTemplates(doc: Doc, field="template-notes") { + static setupNoteTemplates(doc: Doc, field = 'template-notes') { const tempNotes = DocCast(doc[field]); - const reqdTempOpts:DocumentOptions[] = [ - { noteType: "Note", backgroundColor: "yellow", icon: "sticky-note"}, - { noteType: "Idea", backgroundColor: "pink", icon: "lightbulb" }, - { noteType: "Topic", backgroundColor: "lightblue", icon: "book-open" }]; - const reqdNoteList = reqdTempOpts.map(opts => { - const reqdOpts = {...opts, title: "text", system: true}; - const noteType = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.noteType === opts.noteType): undefined; - const makeTemp = (doc:Doc, noteType?:string) => { - doc.isTemplateDoc = makeTemplate(doc, true, noteType??"Note"); + const reqdTempOpts: DocumentOptions[] = [ + { + noteType: 'Note', + backgroundColor: 'yellow', + icon: 'sticky-note', + }, + { noteType: 'Idea', backgroundColor: 'pink', icon: 'lightbulb' }, + { + noteType: 'Topic', + backgroundColor: 'lightblue', + icon: 'book-open', + }, + ]; + const reqdNoteList = reqdTempOpts.map((opts) => { + const reqdOpts = { ...opts, title: 'text', system: true }; + const noteType = tempNotes + ? DocListCast(tempNotes.data).find( + (doc) => doc.noteType === opts.noteType + ) + : undefined; + const makeTemp = (doc: Doc, noteType?: string) => { + doc.isTemplateDoc = makeTemplate(doc, true, noteType ?? 'Note'); return doc; - } - return this.AssignOpts(noteType, reqdOpts) ?? makeTemp(Docs.Create.TextDocument("",reqdOpts), opts.noteType); + }; + return ( + this.AssignOpts(noteType, reqdOpts) ?? + makeTemp(Docs.Create.TextDocument('', reqdOpts), opts.noteType) + ); }); - const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, system: true }; - return this.AssignOpts(tempNotes, reqdOpts, reqdNoteList) ?? (doc[field] = Docs.Create.TreeDocument(reqdNoteList, reqdOpts)); + const reqdOpts: DocumentOptions = { + title: 'Note Layouts', + _height: 75, + system: true, + }; + return ( + this.AssignOpts(tempNotes, reqdOpts, reqdNoteList) ?? + (doc[field] = Docs.Create.TreeDocument(reqdNoteList, reqdOpts)) + ); } /// Initializes collection of templates for notes and click functions - static setupDocTemplates(doc: Doc, field="myTemplates") { - this.AssignDocField(doc, "presElement", opts => Docs.Create.PresElementBoxDocument(opts), { title: "pres element template", type: DocumentType.PRESELEMENT, _fitWidth: true, _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data"}); + static setupDocTemplates(doc: Doc, field = 'myTemplates') { + this.AssignDocField( + doc, + 'presElement', + (opts) => Docs.Create.PresElementBoxDocument(opts), + { + title: 'pres element template', + type: DocumentType.PRESELEMENT, + _fitWidth: true, + _xMargin: 0, + isTemplateDoc: true, + isTemplateForField: 'data', + } + ); const templates = [ DocCast(doc.presElement), CurrentUserUtils.setupNoteTemplates(doc), - CurrentUserUtils.setupClickEditorTemplates(doc) + CurrentUserUtils.setupClickEditorTemplates(doc), ]; - const reqdOpts = { title: "template layouts", _xMargin: 0, system: true, }; - const reqdScripts = { dropConverter: "convertToButtons(dragData)" }; - return this.AssignDocField(doc, field, (opts,items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, templates, reqdScripts); + const reqdOpts = { + title: 'template layouts', + _xMargin: 0, + system: true, + }; + const reqdScripts = { dropConverter: 'convertToButtons(dragData)' }; + return this.AssignDocField( + doc, + field, + (opts, items) => Docs.Create.TreeDocument(items ?? [], opts), + reqdOpts, + templates, + reqdScripts + ); } // setup templates for different document types when they are iconified from Document Decorations - static setupDefaultIconTemplates(doc: Doc, field="template-icons") { - 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, opts:DocumentOptions) => { - const iconFieldName = "icon" + (type ? "_" + type : ""); + static setupDefaultIconTemplates(doc: Doc, field = 'template-icons') { + 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, + opts: DocumentOptions + ) => { + const iconFieldName = 'icon' + (type ? '_' + type : ''); const curIcon = DocCast(templateIconsDoc[iconFieldName]); let creator = labelBox; switch (opts.iconTemplate) { - case DocumentType.IMG : creator = imageBox; break; - case DocumentType.FONTICON: creator = fontBox; break; + case DocumentType.IMG: + creator = imageBox; + break; + case DocumentType.FONTICON: + creator = fontBox; + break; } - const allopts = {system: true, ...opts}; - return this.AssignScripts( (curIcon?.iconTemplate === opts.iconTemplate ? - this.AssignOpts(curIcon, allopts):undefined) ?? ((templateIconsDoc[iconFieldName] = MakeTemplate(creator(allopts), true, iconFieldName, templateField))), - {onClick:"deiconifyView(documentView)"}); + const allopts = { system: true, ...opts }; + return this.AssignScripts( + (curIcon?.iconTemplate === opts.iconTemplate + ? this.AssignOpts(curIcon, allopts) + : undefined) ?? + (templateIconsDoc[iconFieldName] = MakeTemplate( + creator(allopts), + true, + iconFieldName, + templateField + )), + { onClick: 'deiconifyView(documentView)' } + ); }; - const labelBox = (opts: DocumentOptions, data?:string) => Docs.Create.LabelDocument({ - textTransform: "unset", letterSpacing: "unset", _singleLine: false, _minFontSize: 14, _maxFontSize: 24, borderRounding: "5px", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts - }); - const imageBox = (opts: DocumentOptions, url?:string) => Docs.Create.ImageDocument(url ?? "http://www.cs.brown.edu/~bcz/noImage.png", { "icon-nativeWidth": 360 / 4, "icon-nativeHeight": 270 / 4, iconTemplate:DocumentType.IMG, _width: 360 / 4, _height: 270 / 4, _showTitle: "title", ...opts }); - const fontBox = (opts:DocumentOptions, data?:string) => Docs.Create.FontIconDocument({ _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts }); + const labelBox = (opts: DocumentOptions, data?: string) => + Docs.Create.LabelDocument({ + textTransform: 'unset', + letterSpacing: 'unset', + _singleLine: false, + _minFontSize: 14, + _maxFontSize: 24, + borderRounding: '5px', + _width: 150, + _height: 70, + _xPadding: 10, + _yPadding: 10, + ...opts, + }); + const imageBox = (opts: DocumentOptions, url?: string) => + Docs.Create.ImageDocument( + url ?? 'http://www.cs.brown.edu/~bcz/noImage.png', + { + 'icon-nativeWidth': 360 / 4, + 'icon-nativeHeight': 270 / 4, + iconTemplate: DocumentType.IMG, + _width: 360 / 4, + _height: 270 / 4, + _showTitle: 'title', + ...opts, + } + ); + const fontBox = (opts: DocumentOptions, data?: string) => + Docs.Create.FontIconDocument({ + _nativeHeight: 30, + _nativeWidth: 30, + _width: 30, + _height: 30, + ...opts, + }); + // prettier-ignore const iconTemplates = [ makeIconTemplate(undefined, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "dimgray"}), makeIconTemplate(DocumentType.AUDIO, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "lightgreen"}), @@ -242,48 +510,88 @@ export class CurrentUserUtils { /// initalizes the set of "empty<DocType>" 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}, + 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 = (key:string) => ({ title : "Untitled "+ key, _fitWidth: true, system: true, "dragFactory-count": 0, cloneFieldFilter: new List<string>(["system"]) }); + const standardOps = (key: string) => ({ + title: 'Untitled ' + key, + _fitWidth: true, + system: true, + 'dragFactory-count': 0, + cloneFieldFilter: new List<string>(['system']), + }); const json = { doc: { - type: "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" }] - }] - }] + 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: [] + 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: - "<HTMLdiv transformOrigin='top left' width='{100/scale}%' height='{100/scale}%' transform='scale({scale})'>" + - ` <FormattedTextBox {...props} dontScale='true' fieldKey={'text'} height='calc(100% - ${headerBtnHgt}px - {this._headerHeight||0}px)'/>` + - " <FormattedTextBox {...props} dontScale='true' fieldKey={'header'} dontSelectOnLoad='true' ignoreAutoHeight='true' fontSize='{this._headerFontSize||9}px' height='{(this._headerHeight||0)}px' background='{this._headerColor || MySharedDocs().userColor||`lightGray`}' />" + - ` <HTMLdiv fontSize='${headerBtnHgt - 1}px' height='${headerBtnHgt}px' background='yellow' onClick={‘(this._headerHeight=scale*Math.min(Math.max(0,this._height-30),this._headerHeight===0?50:0)) + (this._autoHeightMargins=this._headerHeight ? this._headerHeight+${headerBtnHgt}:0)’} >Metadata</HTMLdiv>` + - "</HTMLdiv>" - }, "header"); + const headerTemplate = (opts: DocumentOptions) => { + const header = Docs.Create.RTFDocument( + new RichTextField(JSON.stringify(json), ''), + { + ...opts, + title: 'text', + layout: + "<HTMLdiv transformOrigin='top left' width='{100/scale}%' height='{100/scale}%' transform='scale({scale})'>" + + ` <FormattedTextBox {...props} dontScale='true' fieldKey={'text'} height='calc(100% - ${headerBtnHgt}px - {this._headerHeight||0}px)'/>` + + " <FormattedTextBox {...props} dontScale='true' fieldKey={'header'} dontSelectOnLoad='true' ignoreAutoHeight='true' fontSize='{this._headerFontSize||9}px' height='{(this._headerHeight||0)}px' background='{this._headerColor || MySharedDocs().userColor||`lightGray`}' />" + + ` <HTMLdiv fontSize='${ + headerBtnHgt - 1 + }px' height='${headerBtnHgt}px' background='yellow' onClick={‘(this._headerHeight=scale*Math.min(Math.max(0,this._height-30),this._headerHeight===0?50:0)) + (this._autoHeightMargins=this._headerHeight ? this._headerHeight+${headerBtnHgt}:0)’} >Metadata</HTMLdiv>` + + '</HTMLdiv>', + }, + 'header' + ); // "<div style={'height:100%'}>" + // " <FormattedTextBox {...props} fieldKey={'header'} dontSelectOnLoad={'true'} ignoreAutoHeight={'true'} pointerEvents='{this._headerPointerEvents||`none`}' fontSize='{this._headerFontSize}px' height='{this._headerHeight}px' background='{this._headerColor||this.target.mySharedDocs.userColor}' />" + // " <FormattedTextBox {...props} fieldKey={'text'} position='absolute' top='{(this._headerHeight)*scale}px' height='calc({100/scale}% - {this._headerHeight}px)'/>" + // "</div>"; - Doc.GetProto(header).isTemplateDoc = makeTemplate(Doc.GetProto(header), true, "headerView"); - Doc.GetProto(header).title = "Untitled Header"; - return header; - } + Doc.GetProto(header).isTemplateDoc = makeTemplate( + Doc.GetProto(header), + true, + 'headerView' + ); + Doc.GetProto(header).title = 'Untitled Header'; + return header; + }; + // prettier-ignore 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 @@ -311,8 +619,18 @@ export class CurrentUserUtils { }, funcs: {title: 'self.text?.Text'}}, ]; - emptyThings.forEach(thing => this.AssignDocField(doc, "empty"+thing.key, (opts) => thing.creator(opts), {...standardOps(thing.key), ...thing.opts}, undefined, undefined, thing.funcs)); - + emptyThings.forEach((thing) => + this.AssignDocField( + doc, + 'empty' + thing.key, + (opts) => thing.creator(opts), + { ...standardOps(thing.key), ...thing.opts }, + undefined, + undefined, + thing.funcs + ) + ); + // prettier-ignore return [ { 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);}'}, }, @@ -332,29 +650,82 @@ export class CurrentUserUtils { } /// Initalizes the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools - static setupCreatorButtons(doc: Doc, dragCreatorDoc?:Doc):Doc { - const creatorBtns = CurrentUserUtils.creatorBtnDescriptors(doc).map((reqdOpts) => { - const btn = dragCreatorDoc ? DocListCast(dragCreatorDoc.data).find(doc => doc.title === reqdOpts.title): undefined; - const opts:DocumentOptions = {...OmitKeys(reqdOpts, ["funcs", "scripts", "backgroundColor"]).omit, - _nativeWidth: 50, _nativeHeight: 50, _width: 35, _height: 35, _hideContextMenu: true, _stayInCollection: true, _dropAction: "alias", - btnType: ButtonType.ToolButton, backgroundColor: reqdOpts.backgroundColor ?? Colors.DARK_GRAY, color: Colors.WHITE, system: true, - _removeDropProperties: new List<string>(["_stayInCollection"]), + static setupCreatorButtons(doc: Doc, dragCreatorDoc?: Doc): Doc { + const creatorBtns = CurrentUserUtils.creatorBtnDescriptors(doc).map( + (reqdOpts) => { + const btn = dragCreatorDoc + ? DocListCast(dragCreatorDoc.data).find( + (doc) => doc.title === reqdOpts.title + ) + : undefined; + const opts: DocumentOptions = { + ...OmitKeys(reqdOpts, [ + 'funcs', + 'scripts', + 'backgroundColor', + ]).omit, + _nativeWidth: 50, + _nativeHeight: 50, + _width: 35, + _height: 35, + _hideContextMenu: true, + _stayInCollection: true, + _dropAction: 'alias', + btnType: ButtonType.ToolButton, + backgroundColor: + reqdOpts.backgroundColor ?? Colors.DARK_GRAY, + color: Colors.WHITE, + system: true, + _removeDropProperties: new List<string>([ + '_stayInCollection', + ]), }; - return this.AssignScripts(this.AssignOpts(btn, opts) ?? Docs.Create.FontIconDocument(opts), reqdOpts.scripts, reqdOpts.funcs); - }); + return this.AssignScripts( + this.AssignOpts(btn, opts) ?? + Docs.Create.FontIconDocument(opts), + reqdOpts.scripts, + reqdOpts.funcs + ); + } + ); - 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 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); + const reqdScripts = { dropConverter: 'convertToButtons(dragData)' }; + return this.AssignScripts( + this.AssignOpts(dragCreatorDoc, reqdOpts, creatorBtns) ?? + Docs.Create.MasonryDocument(creatorBtns, reqdOpts), + reqdScripts + ); } /// returns descriptions needed to buttons for the left sidebar to open up panes displaying different collections of documents - 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())"; + 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())"; + // prettier-ignore return [ { title: "Dashboards", target: this.setupDashboards(doc, "myDashboards"), icon: "desktop", }, { title: "Search", target: this.setupSearcher(doc, "mySearcher"), icon: "search", }, @@ -369,40 +740,110 @@ export class CurrentUserUtils { } /// the empty panel that is filled with whichever left menu button's panel has been selected - static setupLeftSidebarPanel(doc: Doc, field="myLeftSidebarPanel") { - this.AssignDocField(doc, field, (opts) => ((doc:Doc) => {doc.system = true; return doc;})(new Doc()), {system:true}); + static setupLeftSidebarPanel(doc: Doc, field = 'myLeftSidebarPanel') { + this.AssignDocField( + doc, + field, + (opts) => + ((doc: Doc) => { + doc.system = true; + return doc; + })(new Doc()), + { system: true } + ); } /// Initializes the left sidebar menu buttons and the panels they open up - static setupLeftSidebarMenu(doc: Doc, field="myLeftSidebarMenu") { + static setupLeftSidebarMenu(doc: Doc, field = 'myLeftSidebarMenu') { 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; - const reqdBtnOpts:DocumentOptions = { - title, icon, target, btnType: ButtonType.MenuButton, system: true, dontUndo: true, dontRegisterView: true, - _width: 60, _height: 60, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, _dropAction: "alias", - _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]), + const menuBtns = CurrentUserUtils.leftSidebarMenuBtnDescriptions( + doc + ).map(({ title, target, icon, scripts, funcs }) => { + const btnDoc = myLeftSidebarMenu + ? DocListCast(myLeftSidebarMenu.data).find( + (doc) => doc.title === title + ) + : undefined; + const reqdBtnOpts: DocumentOptions = { + title, + icon, + target, + btnType: ButtonType.MenuButton, + system: true, + dontUndo: true, + dontRegisterView: true, + _width: 60, + _height: 60, + _stayInCollection: true, + _hideContextMenu: true, + _chromeHidden: true, + _dropAction: 'alias', + _removeDropProperties: new List<string>([ + 'dropAction', + '_stayInCollection', + ]), }; - return this.AssignScripts(this.AssignOpts(btnDoc, reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), scripts, funcs); + return this.AssignScripts( + this.AssignOpts(btnDoc, reqdBtnOpts) ?? + Docs.Create.FontIconDocument(reqdBtnOpts), + scripts, + funcs + ); }); - const reqdStackOpts:DocumentOptions ={ - title: "menuItemPanel", childDropAction: "alias", backgroundColor: Colors.DARK_GRAY, boxShadow: "rgba(0,0,0,0)", dontRegisterView: true, ignoreClick: true, - _chromeHidden: true, _gridGap: 0, _yMargin: 0, _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, system: true + const reqdStackOpts: DocumentOptions = { + title: 'menuItemPanel', + childDropAction: 'alias', + backgroundColor: Colors.DARK_GRAY, + boxShadow: 'rgba(0,0,0,0)', + dontRegisterView: true, + ignoreClick: true, + _chromeHidden: true, + _gridGap: 0, + _yMargin: 0, + _yPadding: 0, + _xMargin: 0, + _autoHeight: false, + _width: 60, + _columnWidth: 60, + _lockedPosition: true, + system: true, }; - return this.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdStackOpts, menuBtns, { dropConverter: "convertToButtons(dragData)" }); + return this.AssignDocField( + doc, + field, + (opts, items) => Docs.Create.StackingDocument(items ?? [], opts), + reqdStackOpts, + menuBtns, + { dropConverter: 'convertToButtons(dragData)' } + ); } // Sets up mobile menu if it is undefined creates a new one, otherwise returns existing menu - static setupActiveMobileMenu(doc: Doc, field="activeMobileMenu") { - const reqdOpts = { _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true, _chromeHidden: true,}; - this.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(this.setupMobileButtons(), opts), reqdOpts); + static setupActiveMobileMenu(doc: Doc, field = 'activeMobileMenu') { + const reqdOpts = { + _width: 980, + ignoreClick: true, + _lockedPosition: false, + title: 'home', + _yMargin: 100, + system: true, + _chromeHidden: true, + }; + this.AssignDocField( + doc, + field, + (opts, items) => + Docs.Create.StackingDocument(this.setupMobileButtons(), opts), + reqdOpts + ); } // Sets up mobile buttons for inside mobile menu static setupMobileButtons(doc?: Doc, buttons?: string[]) { return []; + // prettier-ignore const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, backgroundColor?: string, info: string, dragFactory?: Doc }[] = [ { title: "DASHBOARDS", icon: "bars", click: 'switchToMobileLibrary()', backgroundColor: "lightgrey", info: "Access your Dashboards 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." }, @@ -412,45 +853,97 @@ export class CurrentUserUtils { { title: "SETTINGS", icon: "cog", click: 'openMobileSettings()', backgroundColor: "lightgrey", info: "Change your password, log out, or manage your account security." } ]; // returns a list of mobile buttons - return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => - this.mobileButton({ - title: data.title, - _lockedPosition: true, - onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, - backgroundColor: data.backgroundColor, system: true - }, - [this.createToolButton({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", system: true, btnType: ButtonType.ClickButton, }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])]) - ); + return docProtoData + .filter((d) => !buttons || !buttons.includes(d.title)) + .map((data) => + this.mobileButton( + { + title: data.title, + _lockedPosition: true, + onClick: data.click + ? ScriptField.MakeScript(data.click) + : undefined, + backgroundColor: data.backgroundColor, + system: true, + }, + [ + this.createToolButton({ + ignoreClick: true, + icon: data.icon, + backgroundColor: 'rgba(0,0,0,0)', + system: true, + btnType: ButtonType.ClickButton, + }), + this.mobileTextContainer({}, [ + this.mobileButtonText({}, data.title), + this.mobileButtonInfo({}, data.info), + ]), + ] + ) + ); } // sets up the main document for the mobile button - static mobileButton = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MulticolumnDocument(docs, { - ...opts, - _removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15, - borderRounding: "5px", boxShadow: "0 0", system: true - }) as any as Doc + static mobileButton = (opts: DocumentOptions, docs: Doc[]) => + Docs.Create.MulticolumnDocument(docs, { + ...opts, + _removeDropProperties: new List<string>(['dropAction']), + _nativeWidth: 900, + _nativeHeight: 250, + _width: 900, + _height: 250, + _yMargin: 15, + borderRounding: '5px', + boxShadow: '0 0', + system: true, + }) as any as Doc; // sets up the text container for the information contained within the mobile button - static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MultirowDocument(docs, { - ...opts, - _removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 450, _nativeHeight: 250, _width: 450, _height: 250, _yMargin: 25, - backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", ignoreClick: true, system: true - }) as any as Doc + static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => + Docs.Create.MultirowDocument(docs, { + ...opts, + _removeDropProperties: new List<string>(['dropAction']), + _nativeWidth: 450, + _nativeHeight: 250, + _width: 450, + _height: 250, + _yMargin: 25, + backgroundColor: 'rgba(0,0,0,0)', + borderRounding: '0', + boxShadow: '0 0', + ignoreClick: true, + system: true, + }) as any as Doc; // Sets up the title of the button - static mobileButtonText = (opts: DocumentOptions, buttonTitle: string) => Docs.Create.TextDocument(buttonTitle, { - ...opts, - title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", system: true - }) as any as Doc + static mobileButtonText = (opts: DocumentOptions, buttonTitle: string) => + Docs.Create.TextDocument(buttonTitle, { + ...opts, + title: buttonTitle, + _fontSize: '37px', + _xMargin: 0, + _yMargin: 0, + ignoreClick: true, + backgroundColor: 'rgba(0,0,0,0)', + system: true, + }) as any as Doc; // Sets up the description of the button - static mobileButtonInfo = (opts: DocumentOptions, buttonInfo: string) => Docs.Create.TextDocument(buttonInfo, { - ...opts, - title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true - }) as any as Doc - + static mobileButtonInfo = (opts: DocumentOptions, buttonInfo: string) => + Docs.Create.TextDocument(buttonInfo, { + ...opts, + title: 'info', + _fontSize: '25px', + _xMargin: 0, + _yMargin: 0, + ignoreClick: true, + backgroundColor: 'rgba(0,0,0,0)', + _dimMagnitude: 2, + system: true, + }) as any as Doc; static setupThumbButtons(doc: Doc) { + // prettier-ignore const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, pointerDown?: string, pointerUp?: string, clipboard?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [ { title: "use pen", icon: "pen-nib", pointerUp: "resetPen()", pointerDown: 'setPen(2, this.backgroundColor)', backgroundColor: "blue" }, { title: "use highlighter", icon: "highlighter", pointerUp: "resetPen()", pointerDown: 'setPen(20, this.backgroundColor)', backgroundColor: "yellow" }, @@ -458,29 +951,58 @@ export class CurrentUserUtils { { title: "interpret text", icon: "font", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('inktotext')", backgroundColor: "orange" }, { title: "ignore gestures", icon: "signature", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('ignoregesture')", backgroundColor: "green" }, ]; - return docProtoData.map(data => Docs.Create.FontIconDocument({ - _nativeWidth: 10, _nativeHeight: 10, _width: 10, _height: 10, title: data.title, icon: data.icon, - _dropAction: data.pointerDown ? "copy" : undefined, - ignoreClick: data.ignoreClick, - onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, - clipboard: data.clipboard, - onPointerUp: data.pointerUp ? ScriptField.MakeScript(data.pointerUp) : undefined, - onPointerDown: data.pointerDown ? ScriptField.MakeScript(data.pointerDown) : undefined, - backgroundColor: data.backgroundColor, - _removeDropProperties: new List<string>(["dropAction"]), - dragFactory: data.dragFactory, - system: true - })); + return docProtoData.map((data) => + Docs.Create.FontIconDocument({ + _nativeWidth: 10, + _nativeHeight: 10, + _width: 10, + _height: 10, + title: data.title, + icon: data.icon, + _dropAction: data.pointerDown ? 'copy' : undefined, + ignoreClick: data.ignoreClick, + onDragStart: data.drag + ? ScriptField.MakeFunction(data.drag) + : undefined, + clipboard: data.clipboard, + onPointerUp: data.pointerUp + ? ScriptField.MakeScript(data.pointerUp) + : undefined, + onPointerDown: data.pointerDown + ? ScriptField.MakeScript(data.pointerDown) + : undefined, + backgroundColor: data.backgroundColor, + _removeDropProperties: new List<string>(['dropAction']), + dragFactory: data.dragFactory, + system: true, + }) + ); } static setupThumbDoc(userDoc: Doc) { if (!userDoc.thumbDoc) { - const thumbDoc = Docs.Create.LinearDocument(CurrentUserUtils.setupThumbButtons(userDoc), { - _width: 100, _height: 50, ignoreClick: true, _lockedPosition: true, title: "buttons", - _autoHeight: true, _yMargin: 5, linearViewIsExpanded: true, backgroundColor: "white", system: true - }); + const thumbDoc = Docs.Create.LinearDocument( + CurrentUserUtils.setupThumbButtons(userDoc), + { + _width: 100, + _height: 50, + ignoreClick: true, + _lockedPosition: true, + title: 'buttons', + _autoHeight: true, + _yMargin: 5, + linearViewIsExpanded: true, + backgroundColor: 'white', + system: true, + } + ); thumbDoc.inkToTextDoc = Docs.Create.LinearDocument([], { - _width: 300, _height: 25, _autoHeight: true, linearViewIsExpanded: true, flexDirection: "column", system: true + _width: 300, + _height: 25, + _autoHeight: true, + linearViewIsExpanded: true, + flexDirection: 'column', + system: true, }); userDoc.thumbDoc = thumbDoc; } @@ -488,154 +1010,451 @@ export class CurrentUserUtils { } static setupMobileInkingDoc(userDoc: Doc) { - return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white", system: true }); + return Docs.Create.FreeformDocument([], { + title: 'Mobile Inking', + backgroundColor: 'white', + system: true, + }); } static setupMobileUploadDoc(userDoc: Doc) { // const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" }) - const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", { - title: "Upload Images From the Web", _lockedPosition: true, system: true - }); + const webDoc = Docs.Create.WebDocument( + 'https://www.britannica.com/biography/Miles-Davis', + { + title: 'Upload Images From the Web', + _lockedPosition: true, + system: true, + } + ); const uploadDoc = Docs.Create.StackingDocument([], { - title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true, _chromeHidden: true, + title: 'Mobile Upload Collection', + backgroundColor: 'white', + _lockedPosition: true, + system: true, + _chromeHidden: true, }); return Docs.Create.StackingDocument([webDoc, uploadDoc], { - _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true, _chromeHidden: true, + _width: screen.width, + _lockedPosition: true, + title: 'Upload', + _autoHeight: true, + _yMargin: 80, + backgroundColor: 'lightgray', + system: true, + _chromeHidden: true, }); } /// Search option on the left side button panel - static setupSearcher(doc: Doc, field:string) { - return this.AssignDocField(doc, field, (opts, items) => Docs.Create.SearchDocument(opts), { - dontRegisterView: true, backgroundColor: "dimgray", ignoreClick: true, title: "Search Panel", system: true, childDropAction: "alias", - _lockedPosition: true, _viewType: CollectionViewType.Schema, _searchDoc: true, }); + static setupSearcher(doc: Doc, field: string) { + return this.AssignDocField( + doc, + field, + (opts, items) => Docs.Create.SearchDocument(opts), + { + dontRegisterView: true, + backgroundColor: 'dimgray', + ignoreClick: true, + title: 'Search Panel', + system: true, + childDropAction: 'alias', + _lockedPosition: true, + _viewType: CollectionViewType.Schema, + _searchDoc: true, + } + ); } /// Initializes the panel of draggable tools that is opened from the left sidebar. - static setupToolsBtnPanel(doc: Doc, field:string) { + static setupToolsBtnPanel(doc: Doc, field: string) { const myTools = DocCast(doc[field]); - const creatorBtns = CurrentUserUtils.setupCreatorButtons(doc, DocListCast(myTools?.data)?.length ? DocListCast(myTools.data)[0]:undefined); - const templateBtns = CurrentUserUtils.setupExperimentalTemplateButtons(doc,DocListCast(myTools?.data)?.length > 1 ? DocListCast(myTools.data)[1]:undefined); - const reqdToolOps:DocumentOptions = { - 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, + const creatorBtns = CurrentUserUtils.setupCreatorButtons( + doc, + DocListCast(myTools?.data)?.length + ? DocListCast(myTools.data)[0] + : undefined + ); + const templateBtns = CurrentUserUtils.setupExperimentalTemplateButtons( + doc, + DocListCast(myTools?.data)?.length > 1 + ? DocListCast(myTools.data)[1] + : undefined + ); + const reqdToolOps: DocumentOptions = { + 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, }; - return this.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdToolOps, [creatorBtns, templateBtns]); + return this.AssignDocField( + doc, + field, + (opts, items) => Docs.Create.StackingDocument(items ?? [], opts), + reqdToolOps, + [creatorBtns, templateBtns] + ); } /// initializes the left sidebar dashboard pane - static setupDashboards(doc: Doc, field:string) { + static setupDashboards(doc: Doc, field: string) { var myDashboards = DocCast(doc[field]); const newDashboard = `createNewDashboard()`; - const reqdBtnOpts:DocumentOptions = { _forceActive: true, _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, - title: "new dashboard", btnType: ButtonType.ClickButton, toolTip: "Create new dashboard", buttonText: "New trail", icon: "plus", system: true }; - const reqdBtnScript = {onClick: newDashboard,} - const newDashboardButton = this.AssignScripts(this.AssignOpts(DocCast(myDashboards?.buttonMenuDoc), reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), reqdBtnScript); - - const reqdOpts:DocumentOptions = { - title: "My Dashboards", childHideLinkButton: true, freezeChildren: "remove|add", treeViewHideTitle: true, boxShadow: "0 0", childDontRegisterViews: true, - targetDropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, system: true, treeViewTruncateTitleWidth: 150, ignoreClick: true, - buttonMenu: true, buttonMenuDoc: newDashboardButton, childDropAction: "alias", - _showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true, - contextMenuLabels: new List<string>(["Create New Dashboard"]), - contextMenuIcons: new List<string>(["plus"]), - childContextMenuLabels: new List<string>(["Toggle Dark Theme", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard"]),// entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters - childContextMenuIcons: new List<string>(["chalkboard", "tv", "camera", "users", "times"]), // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters - explainer: "This is your collection of dashboards. A dashboard represents the tab configuration of your workspace. To manage documents as folders, go to the Files." + const reqdBtnOpts: DocumentOptions = { + _forceActive: true, + _width: 30, + _height: 30, + _stayInCollection: true, + _hideContextMenu: true, + title: 'new dashboard', + btnType: ButtonType.ClickButton, + toolTip: 'Create new dashboard', + buttonText: 'New trail', + icon: 'plus', + system: true, + }; + const reqdBtnScript = { onClick: newDashboard }; + const newDashboardButton = this.AssignScripts( + this.AssignOpts( + DocCast(myDashboards?.buttonMenuDoc), + reqdBtnOpts + ) ?? Docs.Create.FontIconDocument(reqdBtnOpts), + reqdBtnScript + ); + + const reqdOpts: DocumentOptions = { + title: 'My Dashboards', + childHideLinkButton: true, + freezeChildren: 'remove|add', + treeViewHideTitle: true, + boxShadow: '0 0', + childDontRegisterViews: true, + targetDropAction: 'same', + treeViewType: TreeViewType.fileSystem, + isFolder: true, + system: true, + treeViewTruncateTitleWidth: 150, + ignoreClick: true, + buttonMenu: true, + buttonMenuDoc: newDashboardButton, + childDropAction: 'alias', + _showTitle: 'title', + _height: 400, + _gridGap: 5, + _forceActive: true, + _lockedPosition: true, + contextMenuLabels: new List<string>(['Create New Dashboard']), + contextMenuIcons: new List<string>(['plus']), + childContextMenuLabels: new List<string>([ + 'Toggle Dark Theme', + 'Toggle Comic Mode', + 'Snapshot Dashboard', + 'Share Dashboard', + 'Remove Dashboard', + ]), // entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters + childContextMenuIcons: new List<string>([ + 'chalkboard', + 'tv', + 'camera', + 'users', + 'times', + ]), // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters + explainer: + 'This is your collection of dashboards. A dashboard represents the tab configuration of your workspace. To manage documents as folders, go to the Files.', }; - myDashboards = this.AssignDocField(doc, field, (opts) => Docs.Create.TreeDocument([], opts), reqdOpts); + myDashboards = this.AssignDocField( + doc, + field, + (opts) => Docs.Create.TreeDocument([], opts), + reqdOpts + ); const toggleDarkTheme = `this.colorScheme = this.colorScheme ? undefined : "${ColorScheme.Dark}"`; const contextMenuScripts = [newDashboard]; - const childContextMenuScripts = [toggleDarkTheme, `toggleComicMode()`, `snapshotDashboard()`, `shareDashboard(self)`, 'removeDashboard(self)']; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuFilters - const childContextMenuFilters = ['!IsNoviceMode()', '!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts - if (Cast(myDashboards.contextMenuScripts, listSpec(ScriptField), null)?.length !== contextMenuScripts.length) { - myDashboards.contextMenuScripts = new List<ScriptField>(contextMenuScripts.map(script => ScriptField.MakeFunction(script)!)); - } - if (Cast(myDashboards.childContextMenuScripts, listSpec(ScriptField), null)?.length !== childContextMenuScripts.length) { - myDashboards.childContextMenuScripts = new List<ScriptField>(childContextMenuScripts.map(script => ScriptField.MakeFunction(script)!)); - } - if (Cast(myDashboards.childContextMenuFilters, listSpec(ScriptField), null)?.length !== childContextMenuFilters.length) { - myDashboards.childContextMenuFilters = new List<ScriptField>(childContextMenuFilters.map(script => !script ? script: ScriptField.MakeFunction(script)!)); + const childContextMenuScripts = [ + toggleDarkTheme, + `toggleComicMode()`, + `snapshotDashboard()`, + `shareDashboard(self)`, + 'removeDashboard(self)', + ]; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuFilters + const childContextMenuFilters = [ + '!IsNoviceMode()', + '!IsNoviceMode()', + '!IsNoviceMode()', + undefined as any, + undefined as any, + ]; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts + if ( + Cast(myDashboards.contextMenuScripts, listSpec(ScriptField), null) + ?.length !== contextMenuScripts.length + ) { + myDashboards.contextMenuScripts = new List<ScriptField>( + contextMenuScripts.map( + (script) => ScriptField.MakeFunction(script)! + ) + ); + } + if ( + Cast( + myDashboards.childContextMenuScripts, + listSpec(ScriptField), + null + )?.length !== childContextMenuScripts.length + ) { + myDashboards.childContextMenuScripts = new List<ScriptField>( + childContextMenuScripts.map( + (script) => ScriptField.MakeFunction(script)! + ) + ); + } + if ( + Cast( + myDashboards.childContextMenuFilters, + listSpec(ScriptField), + null + )?.length !== childContextMenuFilters.length + ) { + myDashboards.childContextMenuFilters = new List<ScriptField>( + childContextMenuFilters.map((script) => + !script ? script : ScriptField.MakeFunction(script)! + ) + ); } return myDashboards; } /// initializes the left sidebar Trails pane - static setupTrails(doc: Doc, field:string) { + static setupTrails(doc: Doc, field: string) { var myTrails = DocCast(doc[field]); - const reqdBtnOpts:DocumentOptions = { _forceActive: true, _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, - title: "New trail", toolTip: "Create new trail", btnType: ButtonType.ClickButton, buttonText: "New trail", icon: "plus", system: true }; - const reqdBtnScript = {onClick: `createNewPresentation()`}; - const newTrailButton = this.AssignScripts(this.AssignOpts(DocCast(myTrails?.buttonMenuDoc), reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), reqdBtnScript); - - const reqdOpts:DocumentOptions = { - title: "My Trails", _showTitle: "title", _height: 100, - treeViewHideTitle: true, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newTrailButton, - contextMenuIcons: new List<string>(["plus"]), - contextMenuLabels: new List<string>(["Create New Trail"]), - _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, - explainer: "All of the trails that you have created will appear here." + const reqdBtnOpts: DocumentOptions = { + _forceActive: true, + _width: 30, + _height: 30, + _stayInCollection: true, + _hideContextMenu: true, + title: 'New trail', + toolTip: 'Create new trail', + btnType: ButtonType.ClickButton, + buttonText: 'New trail', + icon: 'plus', + system: true, }; - myTrails = this.AssignDocField(doc, field, (opts) => Docs.Create.TreeDocument([], opts), reqdOpts); + const reqdBtnScript = { onClick: `createNewPresentation()` }; + const newTrailButton = this.AssignScripts( + this.AssignOpts(DocCast(myTrails?.buttonMenuDoc), reqdBtnOpts) ?? + Docs.Create.FontIconDocument(reqdBtnOpts), + reqdBtnScript + ); + + const reqdOpts: DocumentOptions = { + title: 'My Trails', + _showTitle: 'title', + _height: 100, + treeViewHideTitle: true, + _fitWidth: true, + _gridGap: 5, + _forceActive: true, + childDropAction: 'alias', + treeViewTruncateTitleWidth: 150, + ignoreClick: true, + buttonMenu: true, + buttonMenuDoc: newTrailButton, + contextMenuIcons: new List<string>(['plus']), + contextMenuLabels: new List<string>(['Create New Trail']), + _lockedPosition: true, + boxShadow: '0 0', + childDontRegisterViews: true, + targetDropAction: 'same', + system: true, + explainer: + 'All of the trails that you have created will appear here.', + }; + myTrails = this.AssignDocField( + doc, + field, + (opts) => Docs.Create.TreeDocument([], opts), + reqdOpts + ); const contextMenuScripts = [reqdBtnScript.onClick]; - if (Cast(myTrails.contextMenuScripts, listSpec(ScriptField), null)?.length !== contextMenuScripts.length) { - myTrails.contextMenuScripts = new List<ScriptField>(contextMenuScripts.map(script => ScriptField.MakeFunction(script)!)); + if ( + Cast(myTrails.contextMenuScripts, listSpec(ScriptField), null) + ?.length !== contextMenuScripts.length + ) { + myTrails.contextMenuScripts = new List<ScriptField>( + contextMenuScripts.map( + (script) => ScriptField.MakeFunction(script)! + ) + ); } return myTrails; } /// initializes the left sidebar File system pane - static setupFilesystem(doc: Doc, field:string) { + static setupFilesystem(doc: Doc, field: string) { var myFilesystem = DocCast(doc[field]); - const myFileOrphans = this.AssignDocField(doc, "myFileOrphans", (opts) => Docs.Create.TreeDocument([], opts), { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); - + const myFileOrphans = this.AssignDocField( + doc, + 'myFileOrphans', + (opts) => Docs.Create.TreeDocument([], opts), + { + title: 'Unfiled', + _stayInCollection: true, + system: true, + isFolder: true, + } + ); + const newFolder = `makeTopLevelFolder()`; const newFolderOpts: DocumentOptions = { - _forceActive: true, _stayInCollection: true, _hideContextMenu: true, _width: 30, _height: 30, - title: "New folder", btnType: ButtonType.ClickButton, toolTip: "Create new folder", buttonText: "New folder", icon: "folder-plus", system: true + _forceActive: true, + _stayInCollection: true, + _hideContextMenu: true, + _width: 30, + _height: 30, + title: 'New folder', + btnType: ButtonType.ClickButton, + toolTip: 'Create new folder', + buttonText: 'New folder', + icon: 'folder-plus', + system: true, }; - const newFolderScript = { onClick: newFolder}; - const newFolderButton = this.AssignScripts(this.AssignOpts(DocCast(myFilesystem?.buttonMenuDoc), newFolderOpts) ?? Docs.Create.FontIconDocument(newFolderOpts), newFolderScript); - - const reqdOpts:DocumentOptions = { _showTitle: "title", _height: 100, _gridGap: 5, _forceActive: true, _lockedPosition: true, - title: "My Documents", buttonMenu: true, buttonMenuDoc: newFolderButton, treeViewHideTitle: true, targetDropAction: "proto", system: true, - isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true, boxShadow: "0 0", childDontRegisterViews: true, - treeViewTruncateTitleWidth: 150, ignoreClick: true, childDropAction: "alias", - childContextMenuLabels: new List<string>(["Create new folder"]), - childContextMenuIcons: new List<string>(["plus"]), - explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." + const newFolderScript = { onClick: newFolder }; + const newFolderButton = this.AssignScripts( + this.AssignOpts( + DocCast(myFilesystem?.buttonMenuDoc), + newFolderOpts + ) ?? Docs.Create.FontIconDocument(newFolderOpts), + newFolderScript + ); + + const reqdOpts: DocumentOptions = { + _showTitle: 'title', + _height: 100, + _gridGap: 5, + _forceActive: true, + _lockedPosition: true, + title: 'My Documents', + buttonMenu: true, + buttonMenuDoc: newFolderButton, + treeViewHideTitle: true, + targetDropAction: 'proto', + system: true, + isFolder: true, + treeViewType: TreeViewType.fileSystem, + childHideLinkButton: true, + boxShadow: '0 0', + childDontRegisterViews: true, + treeViewTruncateTitleWidth: 150, + ignoreClick: true, + childDropAction: 'alias', + childContextMenuLabels: new List<string>(['Create new folder']), + childContextMenuIcons: new List<string>(['plus']), + explainer: + 'This is your file manager where you can create folders to keep track of documents independently of your dashboard.', }; - myFilesystem = this.AssignDocField(doc, field, (opts, items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, [myFileOrphans]); + myFilesystem = this.AssignDocField( + doc, + field, + (opts, items) => Docs.Create.TreeDocument(items ?? [], opts), + reqdOpts, + [myFileOrphans] + ); const childContextMenuScripts = [newFolder]; - if (Cast(myFilesystem.childContextMenuScripts, listSpec(ScriptField), null)?.length !== childContextMenuScripts.length) { - myFilesystem.childContextMenuScripts = new List<ScriptField>(childContextMenuScripts.map(script => ScriptField.MakeFunction(script)!)); + if ( + Cast( + myFilesystem.childContextMenuScripts, + listSpec(ScriptField), + null + )?.length !== childContextMenuScripts.length + ) { + myFilesystem.childContextMenuScripts = new List<ScriptField>( + childContextMenuScripts.map( + (script) => ScriptField.MakeFunction(script)! + ) + ); } return myFilesystem; } /// initializes the panel displaying docs that have been recently closed - 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", - contextMenuLabels: new List<string>(["Empty recently closed"]), - contextMenuIcons:new List<string>(["trash"]), - explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list." + 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', + contextMenuLabels: new List<string>(['Empty recently closed']), + contextMenuIcons: new List<string>(['trash']), + explainer: + 'Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list.', + }; + const recentlyClosed = this.AssignDocField( + doc, + field, + (opts) => Docs.Create.TreeDocument([], opts), + reqdOpts + ); + + const clearAll = (target: string) => + `getProto(${target}).data = new List([])`; + const clearBtnsOpts: DocumentOptions = { + _width: 30, + _height: 30, + _forceActive: true, + _stayInCollection: true, + _hideContextMenu: true, + title: 'Empty', + target: recentlyClosed, + btnType: ButtonType.ClickButton, + buttonText: 'Empty', + icon: 'trash', + system: true, + toolTip: 'Empty recently closed', }; - const recentlyClosed = this.AssignDocField(doc, field, (opts) => Docs.Create.TreeDocument([], opts), reqdOpts); - - const clearAll = (target:string) => `getProto(${target}).data = new List([])`; - const clearBtnsOpts:DocumentOptions = { _width: 30, _height: 30, _forceActive: true, _stayInCollection: true, _hideContextMenu: true, - title: "Empty", target: recentlyClosed, btnType: ButtonType.ClickButton, buttonText: "Empty", icon: "trash", system: true, - toolTip: "Empty recently closed",}; - const clearDocsButton = this.AssignDocField(recentlyClosed, "clearDocsBtn", (opts) => Docs.Create.FontIconDocument(opts), clearBtnsOpts, undefined, {onClick: clearAll("self.target")}); - - if (recentlyClosed.buttonMenuDoc !== clearDocsButton) Doc.GetProto(recentlyClosed).buttonMenuDoc = clearDocsButton; - - if (!Cast(recentlyClosed.contextMenuScripts, listSpec(ScriptField),null)?.find((script) => script.script.originalScript === clearAll("self"))) { - recentlyClosed.contextMenuScripts = new List<ScriptField>([ScriptField.MakeScript(clearAll("self"))!]) + const clearDocsButton = this.AssignDocField( + recentlyClosed, + 'clearDocsBtn', + (opts) => Docs.Create.FontIconDocument(opts), + clearBtnsOpts, + undefined, + { onClick: clearAll('self.target') } + ); + + if (recentlyClosed.buttonMenuDoc !== clearDocsButton) + Doc.GetProto(recentlyClosed).buttonMenuDoc = clearDocsButton; + + if ( + !Cast( + recentlyClosed.contextMenuScripts, + listSpec(ScriptField), + null + )?.find( + (script) => script.script.originalScript === clearAll('self') + ) + ) { + recentlyClosed.contextMenuScripts = new List<ScriptField>([ + ScriptField.MakeScript(clearAll('self'))!, + ]); } return recentlyClosed; } @@ -643,60 +1462,184 @@ export class CurrentUserUtils { /// creates a new, empty filter doc static createFilterDoc() { const clearAll = `getProto(self).data = new List([])`; - const reqdOpts:DocumentOptions = { - _lockedPosition: true, _autoHeight: true, _fitWidth: true, _height: 150, _xPadding: 5, _yPadding: 5, _gridGap: 5, _forceActive: true, - title: "Unnamed Filter", filterBoolean: "AND", boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", ignoreClick: true, system: true, - childDropAction: "none", treeViewHideTitle: true, treeViewTruncateTitleWidth: 150, - childContextMenuLabels: new List<string>(["Clear All"]), - childContextMenuScripts: new List<ScriptField>([ScriptField.MakeFunction(clearAll)!]), + const reqdOpts: DocumentOptions = { + _lockedPosition: true, + _autoHeight: true, + _fitWidth: true, + _height: 150, + _xPadding: 5, + _yPadding: 5, + _gridGap: 5, + _forceActive: true, + title: 'Unnamed Filter', + filterBoolean: 'AND', + boxShadow: '0 0', + childDontRegisterViews: true, + targetDropAction: 'same', + ignoreClick: true, + system: true, + childDropAction: 'none', + treeViewHideTitle: true, + treeViewTruncateTitleWidth: 150, + childContextMenuLabels: new List<string>(['Clear All']), + childContextMenuScripts: new List<ScriptField>([ + ScriptField.MakeFunction(clearAll)!, + ]), }; return Docs.Create.FilterDocument(reqdOpts); } /// initializes the left sidebar panel view of the UserDoc - static setupUserDocView(doc: Doc, field:string) { - const reqdOpts:DocumentOptions = { - _lockedPosition: true, _gridGap: 5, _forceActive: true, title: Doc.CurrentUserEmail +"-view", - boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", ignoreClick: true, system: true, - treeViewHideTitle: true, treeViewTruncateTitleWidth: 150 + static setupUserDocView(doc: Doc, field: string) { + const reqdOpts: DocumentOptions = { + _lockedPosition: true, + _gridGap: 5, + _forceActive: true, + title: Doc.CurrentUserEmail + '-view', + boxShadow: '0 0', + childDontRegisterViews: true, + targetDropAction: 'same', + ignoreClick: true, + system: true, + treeViewHideTitle: true, + treeViewTruncateTitleWidth: 150, }; - if (!doc[field]) this.AssignOpts(doc, {treeViewOpen: true, treeViewExpandedView: "fields" }); - return this.AssignDocField(doc, field, (opts, items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, [doc]); + if (!doc[field]) + this.AssignOpts(doc, { + treeViewOpen: true, + treeViewExpandedView: 'fields', + }); + return this.AssignDocField( + doc, + field, + (opts, items) => Docs.Create.TreeDocument(items ?? [], opts), + reqdOpts, + [doc] + ); } - static linearButtonList = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.LinearDocument(docs, { - ...opts, _gridGap: 0, _xMargin: 5, _yMargin: 5, boxShadow: "0 0", _forceActive: true, - dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), - _lockedPosition: true, system: true, flexDirection: "row" - }) + static linearButtonList = (opts: DocumentOptions, docs: Doc[]) => + Docs.Create.LinearDocument(docs, { + ...opts, + _gridGap: 0, + _xMargin: 5, + _yMargin: 5, + boxShadow: '0 0', + _forceActive: true, + dropConverter: ScriptField.MakeScript( + 'convertToButtons(dragData)', + { + dragData: DragManager.DocumentDragData.name, + } + ), + _lockedPosition: true, + system: true, + flexDirection: 'row', + }); - static createToolButton = (opts: DocumentOptions) => Docs.Create.FontIconDocument({ - btnType: ButtonType.ToolButton, _forceActive: true, _dropAction: "alias", _hideContextMenu: true, - _removeDropProperties: new List<string>(["_dropAction", "_hideContextMenu", "stayInCollection"]), - _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true, ...opts, - }) + static createToolButton = (opts: DocumentOptions) => + Docs.Create.FontIconDocument({ + btnType: ButtonType.ToolButton, + _forceActive: true, + _dropAction: 'alias', + _hideContextMenu: true, + _removeDropProperties: new List<string>([ + '_dropAction', + '_hideContextMenu', + 'stayInCollection', + ]), + _nativeWidth: 40, + _nativeHeight: 40, + _width: 40, + _height: 40, + system: true, + ...opts, + }); /// initializes the required buttons in the expanding button menu at the bottom of the Dash window - static setupDockedButtons(doc: Doc, field="myDockedBtns") { + static setupDockedButtons(doc: Doc, field = 'myDockedBtns') { const dockedBtns = DocCast(doc[field]); - const dockBtn = (opts: DocumentOptions, scripts: {[key:string]:string}) => - this.AssignScripts(this.AssignOpts(DocListCast(dockedBtns?.data)?.find(doc => doc.title === opts.title), opts) ?? - CurrentUserUtils.createToolButton(opts), scripts); - - const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet - { scripts: { onClick: "undo()"}, opts: { title: "undo", icon: "undo-alt", toolTip: "Click to undo" }}, - { scripts: { onClick: "redo()"}, opts: { title: "redo", icon: "redo-alt", toolTip: "Click to redo" }} + const dockBtn = ( + opts: DocumentOptions, + scripts: { [key: string]: string } + ) => + this.AssignScripts( + this.AssignOpts( + DocListCast(dockedBtns?.data)?.find( + (doc) => doc.title === opts.title + ), + opts + ) ?? CurrentUserUtils.createToolButton(opts), + scripts + ); + + const btnDescs = [ + // setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet + { + scripts: { onClick: 'undo()' }, + opts: { + title: 'undo', + icon: 'undo-alt', + toolTip: 'Click to undo', + }, + }, + { + scripts: { onClick: 'redo()' }, + opts: { + title: 'redo', + icon: 'redo-alt', + toolTip: 'Click to redo', + }, + }, ]; - const btns = btnDescs.map(desc => dockBtn({_width: 30, _height: 30, dontUndo: true, _stayInCollection: true, ...desc.opts}, desc.scripts)); + const btns = btnDescs.map((desc) => + dockBtn( + { + _width: 30, + _height: 30, + dontUndo: true, + _stayInCollection: true, + ...desc.opts, + }, + desc.scripts + ) + ); const dockBtnsReqdOpts = { - title: "docked buttons", _height: 40, flexGap: 0, linearViewFloating: true, - childDontRegisterViews: true, linearViewIsExpanded: true, linearViewExpandable: true, ignoreClick: true + title: 'docked buttons', + _height: 40, + flexGap: 0, + linearViewFloating: true, + childDontRegisterViews: true, + linearViewIsExpanded: true, + linearViewExpandable: true, + ignoreClick: true, }; - reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "redo")!).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); - reaction(() => UndoManager.undoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "undo")!).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true }); - return this.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), dockBtnsReqdOpts, btns); + reaction( + () => UndoManager.redoStack.slice(), + () => + (Doc.GetProto( + btns.find((btn) => btn.title === 'redo')! + ).opacity = UndoManager.CanRedo() ? 1 : 0.4), + { fireImmediately: true } + ); + reaction( + () => UndoManager.undoStack.slice(), + () => + (Doc.GetProto( + btns.find((btn) => btn.title === 'undo')! + ).opacity = UndoManager.CanUndo() ? 1 : 0.4), + { fireImmediately: true } + ); + return this.AssignDocField( + doc, + field, + (opts, items) => this.linearButtonList(opts, items ?? []), + dockBtnsReqdOpts, + btns + ); } + // prettier-ignore static textTools():Button[] { return [ { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true, scripts: {script: 'setFont(value, _readOnly_)'}, @@ -719,6 +1662,7 @@ export class CurrentUserUtils { ]; } + // prettier-ignore static inkTools():Button[] { return [ { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", scripts: {onClick:'{ return setActiveTool("pen", _readOnly_);}' }}, @@ -734,10 +1678,22 @@ export class CurrentUserUtils { ]; } - static schemaTools():Button[] { - return [{ title: "Show preview", toolTip: "Show preview of selected document", btnType: ButtonType.ToggleButton, buttonText: "Show Preview", icon: "eye", scripts:{ onClick: '{return toggleSchemaPreview(_readOnly_);}'}, }]; + static schemaTools(): Button[] { + return [ + { + title: 'Show preview', + toolTip: 'Show preview of selected document', + btnType: ButtonType.ToggleButton, + buttonText: 'Show Preview', + icon: 'eye', + scripts: { + onClick: '{return toggleSchemaPreview(_readOnly_);}', + }, + }, + ]; } + // prettier-ignore static webTools() { return [ { title: "Back", toolTip: "Go back", btnType: ButtonType.ClickButton, icon: "arrow-left", scripts: { onClick: '{ return webBack(_readOnly_); }' }}, @@ -747,6 +1703,7 @@ export class CurrentUserUtils { ]; } + // prettier-ignore static contextMenuTools():Button[] { return [ { btnList: new List<string>([CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Tree, @@ -768,260 +1725,570 @@ export class CurrentUserUtils { } /// initializes a context menu button for the top bar context menu - static setupContextMenuButton(params:Button, btnDoc?:Doc) { - const reqdOpts:DocumentOptions = { - ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, - backgroundColor: params.scripts?.onClick ? undefined: "transparent", /// a bit hacky. if an onClick is specified, then assume a toggle uses onClick to get the backgroundColor (see below). Otherwise, assume a transparent background - color: Colors.WHITE, system: true, dontUndo: true, - _nativeWidth: params.width ?? 30, _width: params.width ?? 30, - _height: 30, _nativeHeight: 30, - _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, - _dropAction: "alias", _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]), + static setupContextMenuButton(params: Button, btnDoc?: Doc) { + const reqdOpts: DocumentOptions = { + ...OmitKeys(params, ['scripts', 'funcs', 'subMenu']).omit, + backgroundColor: params.scripts?.onClick + ? undefined + : 'transparent', /// a bit hacky. if an onClick is specified, then assume a toggle uses onClick to get the backgroundColor (see below). Otherwise, assume a transparent background + color: Colors.WHITE, + system: true, + dontUndo: true, + _nativeWidth: params.width ?? 30, + _width: params.width ?? 30, + _height: 30, + _nativeHeight: 30, + _stayInCollection: true, + _hideContextMenu: true, + _lockedPosition: true, + _dropAction: 'alias', + _removeDropProperties: new List<string>([ + 'dropAction', + '_stayInCollection', + ]), }; - const reqdFuncs:{[key:string]:any} = { + const reqdFuncs: { [key: string]: any } = { ...params.funcs, - backgroundColor: params.scripts?.onClick /// a bit hacky. if onClick is set, then we assume it returns a color value when queried with '_readOnly_'. This will be true for toggle buttons, but not generally - } - return this.AssignScripts(this.AssignOpts(btnDoc, reqdOpts) ?? Docs.Create.FontIconDocument(reqdOpts), params.scripts, reqdFuncs); + backgroundColor: params.scripts?.onClick, /// a bit hacky. if onClick is set, then we assume it returns a color value when queried with '_readOnly_'. This will be true for toggle buttons, but not generally + }; + return this.AssignScripts( + this.AssignOpts(btnDoc, reqdOpts) ?? + Docs.Create.FontIconDocument(reqdOpts), + params.scripts, + reqdFuncs + ); } /// Initializes all the default buttons for the top bar context menu - static setupContextMenuButtons(doc: Doc, field="myContextMenuBtns") { - const reqdCtxtOpts = { title: "context menu buttons", flexGap: 0, childDontRegisterViews: true, linearViewIsExpanded: true, ignoreClick: true, linearViewExpandable: false, _height: 35 }; - const ctxtMenuBtnsDoc = this.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), reqdCtxtOpts, undefined); - const ctxtMenuBtns = CurrentUserUtils.contextMenuTools().map(params => { - const menuBtnDoc = DocListCast(ctxtMenuBtnsDoc?.data).find(doc => doc.title === params.title); - if (!params.subMenu) { - return this.setupContextMenuButton(params, menuBtnDoc); - } else { - const reqdSubMenuOpts = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, - childDontRegisterViews: true, flexGap: 0, _height: 30, ignoreClick: true, - linearViewSubMenu: true, linearViewExpandable: true, }; - return this.AssignScripts(this.AssignOpts(menuBtnDoc, reqdSubMenuOpts) ?? - (ctxtMenuBtnsDoc[StrCast(params.title)]= this.linearButtonList(reqdSubMenuOpts, params.subMenu.map(sub => - this.setupContextMenuButton(sub, DocListCast(menuBtnDoc?.data).find(doc => doc.title === sub.title)) - ))), undefined, params.funcs); + static setupContextMenuButtons(doc: Doc, field = 'myContextMenuBtns') { + const reqdCtxtOpts = { + title: 'context menu buttons', + flexGap: 0, + childDontRegisterViews: true, + linearViewIsExpanded: true, + ignoreClick: true, + linearViewExpandable: false, + _height: 35, + }; + const ctxtMenuBtnsDoc = this.AssignDocField( + doc, + field, + (opts, items) => this.linearButtonList(opts, items ?? []), + reqdCtxtOpts, + undefined + ); + const ctxtMenuBtns = CurrentUserUtils.contextMenuTools().map( + (params) => { + const menuBtnDoc = DocListCast(ctxtMenuBtnsDoc?.data).find( + (doc) => doc.title === params.title + ); + if (!params.subMenu) { + return this.setupContextMenuButton(params, menuBtnDoc); + } else { + const reqdSubMenuOpts = { + ...OmitKeys(params, ['scripts', 'funcs', 'subMenu']) + .omit, + childDontRegisterViews: true, + flexGap: 0, + _height: 30, + ignoreClick: true, + linearViewSubMenu: true, + linearViewExpandable: true, + }; + return this.AssignScripts( + this.AssignOpts(menuBtnDoc, reqdSubMenuOpts) ?? + (ctxtMenuBtnsDoc[StrCast(params.title)] = + this.linearButtonList( + reqdSubMenuOpts, + params.subMenu.map((sub) => + this.setupContextMenuButton( + sub, + DocListCast(menuBtnDoc?.data).find( + (doc) => doc.title === sub.title + ) + ) + ) + )), + undefined, + params.funcs + ); + } } - }); + ); return this.AssignOpts(ctxtMenuBtnsDoc, reqdCtxtOpts, ctxtMenuBtns); } /// collection of documents rendered in the overlay layer above all tabs and other UI - static setupOverlays(doc: Doc, field = "myOverlayDocs") { - return this.AssignDocField(doc, field, (opts) => Docs.Create.FreeformDocument([], opts), { title: "overlay documents", backgroundColor: "#aca3a6", system: true }); + static setupOverlays(doc: Doc, field = 'myOverlayDocs') { + return this.AssignDocField( + doc, + field, + (opts) => Docs.Create.FreeformDocument([], opts), + { + title: 'overlay documents', + backgroundColor: '#aca3a6', + system: true, + } + ); } - static setupPublished(doc:Doc, field = "myPublishedDocs") { - return this.AssignDocField(doc, field, (opts) => Docs.Create.TreeDocument([], opts), { title: "published docs", backgroundColor: "#aca3a6", system: true }); + static setupPublished(doc: Doc, field = 'myPublishedDocs') { + return this.AssignDocField( + doc, + field, + (opts) => Docs.Create.TreeDocument([], opts), + { + title: 'published docs', + backgroundColor: '#aca3a6', + system: true, + } + ); } - + /// The database of all links on all documents static setupLinkDocs(doc: Doc, linkDatabaseId: string) { if (!(Docs.newAccount ? undefined : DocCast(doc.myLinkDatabase))) { const linkDocs = new Doc(linkDatabaseId, true); - linkDocs.title = "LINK DATABASE: " + Doc.CurrentUserEmail; + linkDocs.title = 'LINK DATABASE: ' + Doc.CurrentUserEmail; linkDocs.author = Doc.CurrentUserEmail; linkDocs.data = new List<Doc>([]); - linkDocs["acl-Public"] = SharingPermissions.Augment; + linkDocs['acl-Public'] = SharingPermissions.Augment; doc.myLinkDatabase = new PrefetchProxy(linkDocs); } } /// Shared documents option on the left side button panel - // A user's sharing document is where all documents that are shared to that user are placed. + // A user's sharing document is where all documents that are shared to that user are placed. // When the user views one of these documents, it will be added to the sharing documents 'viewed' list field // The sharing document also stores the user's color value which helps distinguish shared documents from personal documents static setupSharedDocs(doc: Doc, sharingDocumentId: string) { const addToDashboards = ScriptField.MakeScript(`addToDashboards(self)`); - const dashboardFilter = ScriptField.MakeFunction(`doc._viewType === '${CollectionViewType.Docking}'`, { doc: Doc.name }); - const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(scriptContext.props.treeView.props.Document, 'viewed', documentView.rootDoc);}"; - - const sharedScripts = { treeViewChildDoubleClick: dblClkScript, } - const sharedDocOpts:DocumentOptions = { - title: "My Shared Docs", - userColor: "rgb(202, 202, 202)", - childContextMenuFilters: new List<ScriptField>([dashboardFilter!,]), - childContextMenuScripts: new List<ScriptField>([addToDashboards!,]), - childContextMenuLabels: new List<string>(["Add to Dashboards",]), - childContextMenuIcons: new List<string>(["user-plus",]), - "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, - childDropAction: "alias", system: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 50, _gridGap: 15, + const dashboardFilter = ScriptField.MakeFunction( + `doc._viewType === '${CollectionViewType.Docking}'`, + { doc: Doc.name } + ); + const dblClkScript = + "{scriptContext.openLevel(documentView); addDocToList(scriptContext.props.treeView.props.Document, 'viewed', documentView.rootDoc);}"; + + const sharedScripts = { treeViewChildDoubleClick: dblClkScript }; + const sharedDocOpts: DocumentOptions = { + title: 'My Shared Docs', + userColor: 'rgb(202, 202, 202)', + childContextMenuFilters: new List<ScriptField>([dashboardFilter!]), + childContextMenuScripts: new List<ScriptField>([addToDashboards!]), + childContextMenuLabels: new List<string>(['Add to Dashboards']), + childContextMenuIcons: new List<string>(['user-plus']), + 'acl-Public': SharingPermissions.Augment, + '_acl-Public': SharingPermissions.Augment, + childDropAction: 'alias', + system: true, + contentPointerEvents: 'all', + childLimitHeight: 0, + _yMargin: 50, + _gridGap: 15, // NOTE: treeViewHideTitle & _showTitle is for a TreeView's editable title, _showTitle is for DocumentViews title bar - _showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, - explainer: "This is where documents or dashboards that other users have shared with you will appear. To share a document or dashboard right click and select 'Share'" + _showTitle: 'title', + treeViewHideTitle: true, + ignoreClick: true, + _lockedPosition: true, + boxShadow: '0 0', + _chromeHidden: true, + dontRegisterView: true, + explainer: + "This is where documents or dashboards that other users have shared with you will appear. To share a document or dashboard right click and select 'Share'", }; - - this.AssignDocField(doc, "mySharedDocs", opts => Docs.Create.TreeDocument([], opts, sharingDocumentId + "layout", sharingDocumentId), sharedDocOpts, undefined, sharedScripts); + + this.AssignDocField( + doc, + 'mySharedDocs', + (opts) => + Docs.Create.TreeDocument( + [], + opts, + sharingDocumentId + 'layout', + sharingDocumentId + ), + sharedDocOpts, + undefined, + sharedScripts + ); } - /// Import option on the left side button panel - static setupImportSidebar(doc: Doc, field:string) { - const reqdOpts:DocumentOptions = { - title: "My Imports", _forceActive: true, buttonMenu: true, ignoreClick: true, _showTitle: "title", - _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, - childDropAction: "copy", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true, - dontRegisterView: true, explainer: "This is where documents that are Imported into Dash will go." + /// Import option on the left side button panel + static setupImportSidebar(doc: Doc, field: string) { + const reqdOpts: DocumentOptions = { + title: 'My Imports', + _forceActive: true, + buttonMenu: true, + ignoreClick: true, + _showTitle: 'title', + _stayInCollection: true, + _hideContextMenu: true, + childLimitHeight: 0, + childDropAction: 'copy', + _autoHeight: true, + _yMargin: 50, + _gridGap: 15, + boxShadow: '0 0', + _lockedPosition: true, + system: true, + _chromeHidden: true, + dontRegisterView: true, + explainer: + 'This is where documents that are Imported into Dash will go.', }; - const myImports = this.AssignDocField(doc, field, (opts) => Docs.Create.StackingDocument([], opts), reqdOpts); - - const reqdBtnOpts:DocumentOptions = { _forceActive: true, toolTip: "Import from computer", - _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Import", btnType: ButtonType.ClickButton, - buttonText: "Import", icon: "upload", system: true }; - this.AssignDocField(myImports, "buttonMenuDoc", (opts) => Docs.Create.FontIconDocument(opts), reqdBtnOpts, undefined, { onClick: "importDocument()" }); + const myImports = this.AssignDocField( + doc, + field, + (opts) => Docs.Create.StackingDocument([], opts), + reqdOpts + ); + + const reqdBtnOpts: DocumentOptions = { + _forceActive: true, + toolTip: 'Import from computer', + _width: 30, + _height: 30, + _stayInCollection: true, + _hideContextMenu: true, + title: 'Import', + btnType: ButtonType.ClickButton, + buttonText: 'Import', + icon: 'upload', + system: true, + }; + this.AssignDocField( + myImports, + 'buttonMenuDoc', + (opts) => Docs.Create.FontIconDocument(opts), + reqdBtnOpts, + undefined, + { onClick: 'importDocument()' } + ); return myImports; } static setupClickEditorTemplates(doc: Doc) { - if (doc["clickFuncs-child"] === undefined) { + if (doc['clickFuncs-child'] === undefined) { // to use this function, select it from the context menu of a collection. then edit the onChildClick script. Add two Doc variables: 'target' and 'thisContainer', then assign 'target' to some target collection. After that, clicking on any document in the initial collection will open it in the target - const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript( - "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self]))) ", - { thisContainer: Doc.name }), { - title: "Click to open in target", _width: 300, _height: 200, - targetScriptKey: "onChildClick", system: true - }); - - const openDetail = Docs.Create.ScriptingDocument(ScriptField.MakeScript( "openOnRight(self.doubleClickView)", {}), - { title: "Double click to open doubleClickView", _width: 300, _height: 200, targetScriptKey: "onChildDoubleClick", system: true }); + const openInTarget = Docs.Create.ScriptingDocument( + ScriptField.MakeScript( + 'docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self]))) ', + { thisContainer: Doc.name } + ), + { + title: 'Click to open in target', + _width: 300, + _height: 200, + targetScriptKey: 'onChildClick', + system: true, + } + ); + + const openDetail = Docs.Create.ScriptingDocument( + ScriptField.MakeScript('openOnRight(self.doubleClickView)', {}), + { + title: 'Double click to open doubleClickView', + _width: 300, + _height: 200, + targetScriptKey: 'onChildDoubleClick', + system: true, + } + ); - doc["clickFuncs-child"] = Docs.Create.TreeDocument([openInTarget, openDetail], { title: "on Child Click function templates", system: true }); + doc['clickFuncs-child'] = Docs.Create.TreeDocument( + [openInTarget, openDetail], + { title: 'on Child Click function templates', system: true } + ); } // this is equivalent to using PrefetchProxies to make sure all the childClickFuncs have been retrieved. - PromiseValue(Cast(doc["clickFuncs-child"], Doc)).then(func => func && PromiseValue(func.data).then(DocListCast)); + PromiseValue(Cast(doc['clickFuncs-child'], Doc)).then( + (func) => func && PromiseValue(func.data).then(DocListCast) + ); if (doc.clickFuncs === undefined) { - const onClick = Docs.Create.ScriptingDocument(undefined, { - title: "onClick", "onClick-rawScript": "console.log('click')", - isTemplateDoc: true, isTemplateForField: "onClick", _width: 300, _height: 200, system: true - }, "onClick"); - const onChildClick = Docs.Create.ScriptingDocument(undefined, { - title: "onChildClick", "onChildClick-rawScript": "console.log('child click')", - isTemplateDoc: true, isTemplateForField: "onChildClick", _width: 300, _height: 200, system: true - }, "onChildClick"); - const onDoubleClick = Docs.Create.ScriptingDocument(undefined, { - title: "onDoubleClick", "onDoubleClick-rawScript": "console.log('double click')", - isTemplateDoc: true, isTemplateForField: "onDoubleClick", _width: 300, _height: 200, system: true - }, "onDoubleClick"); - const onChildDoubleClick = Docs.Create.ScriptingDocument(undefined, { - title: "onChildDoubleClick", "onChildDoubleClick-rawScript": "console.log('child double click')", - isTemplateDoc: true, isTemplateForField: "onChildDoubleClick", _width: 300, _height: 200, system: true - }, "onChildDoubleClick"); - const onCheckedClick = Docs.Create.ScriptingDocument(undefined, { - title: "onCheckedClick", "onCheckedClick-rawScript": "console.log(heading + checked + containingTreeView)", - "onCheckedClick-params": new List<string>(["heading", "checked", "containingTreeView"]), isTemplateDoc: true, - isTemplateForField: "onCheckedClick", _width: 300, _height: 200, system: true - }, "onCheckedClick"); - doc.clickFuncs = Docs.Create.TreeDocument([onClick, onChildClick, onDoubleClick, onCheckedClick], { title: "onClick funcs", system: true }); + const onClick = Docs.Create.ScriptingDocument( + undefined, + { + title: 'onClick', + 'onClick-rawScript': "console.log('click')", + isTemplateDoc: true, + isTemplateForField: 'onClick', + _width: 300, + _height: 200, + system: true, + }, + 'onClick' + ); + const onChildClick = Docs.Create.ScriptingDocument( + undefined, + { + title: 'onChildClick', + 'onChildClick-rawScript': "console.log('child click')", + isTemplateDoc: true, + isTemplateForField: 'onChildClick', + _width: 300, + _height: 200, + system: true, + }, + 'onChildClick' + ); + const onDoubleClick = Docs.Create.ScriptingDocument( + undefined, + { + title: 'onDoubleClick', + 'onDoubleClick-rawScript': "console.log('double click')", + isTemplateDoc: true, + isTemplateForField: 'onDoubleClick', + _width: 300, + _height: 200, + system: true, + }, + 'onDoubleClick' + ); + const onChildDoubleClick = Docs.Create.ScriptingDocument( + undefined, + { + title: 'onChildDoubleClick', + 'onChildDoubleClick-rawScript': + "console.log('child double click')", + isTemplateDoc: true, + isTemplateForField: 'onChildDoubleClick', + _width: 300, + _height: 200, + system: true, + }, + 'onChildDoubleClick' + ); + const onCheckedClick = Docs.Create.ScriptingDocument( + undefined, + { + title: 'onCheckedClick', + 'onCheckedClick-rawScript': + 'console.log(heading + checked + containingTreeView)', + 'onCheckedClick-params': new List<string>([ + 'heading', + 'checked', + 'containingTreeView', + ]), + isTemplateDoc: true, + isTemplateForField: 'onCheckedClick', + _width: 300, + _height: 200, + system: true, + }, + 'onCheckedClick' + ); + doc.clickFuncs = Docs.Create.TreeDocument( + [onClick, onChildClick, onDoubleClick, onCheckedClick], + { title: 'onClick funcs', system: true } + ); } - PromiseValue(Cast(doc.clickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast)); + PromiseValue(Cast(doc.clickFuncs, Doc)).then( + (func) => func && PromiseValue(func.data).then(DocListCast) + ); return doc.clickFuncs as Doc; } - /// Updates the UserDoc to have all required fields, docs, etc. No changes should need to be /// written to the server if the code hasn't changed. However, choices need to be made for each Doc/field /// whether to revert to "default" values, or to leave them as the user/system last set them. - static updateUserDocument(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) { - this.AssignDocField(doc, "globalGroupDatabase", () => Docs.Prototypes.MainGroupDocument(), {}); - reaction(() => DateCast(DocCast(doc.globalGroupDatabase)["data-lastModified"]), + static updateUserDocument( + doc: Doc, + sharingDocumentId: string, + linkDatabaseId: string + ) { + this.AssignDocField( + doc, + 'globalGroupDatabase', + () => Docs.Prototypes.MainGroupDocument(), + {} + ); + reaction( + () => + DateCast(DocCast(doc.globalGroupDatabase)['data-lastModified']), async () => { - const groups = await DocListCastAsync(DocCast(doc.globalGroupDatabase).data); - const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(Doc.CurrentUserEmail)) || []; - SnappingManager.SetCachedGroups(["Public", ...mygroups?.map(g => StrCast(g.title))]); - }, { fireImmediately: true }); + const groups = await DocListCastAsync( + DocCast(doc.globalGroupDatabase).data + ); + const mygroups = + groups?.filter((group) => + JSON.parse(StrCast(group.members)).includes( + Doc.CurrentUserEmail + ) + ) || []; + SnappingManager.SetCachedGroups([ + 'Public', + ...mygroups?.map((g) => StrCast(g.title)), + ]); + }, + { fireImmediately: true } + ); doc.system ?? (doc.system = true); doc.title ?? (doc.title = Doc.CurrentUserEmail); Doc.noviceMode ?? (Doc.noviceMode = true); doc._raiseWhenDragged ?? (doc._raiseWhenDragged = true); doc._showLabel ?? (doc._showLabel = true); - doc.textAlign ?? (doc.textAlign = "left"); - doc.activeInkColor ?? (doc.activeInkColor = "rgb(0, 0, 0)");; + doc.textAlign ?? (doc.textAlign = 'left'); + doc.activeInkColor ?? (doc.activeInkColor = 'rgb(0, 0, 0)'); doc.activeInkWidth ?? (doc.activeInkWidth = 1); - doc.activeInkBezier ?? (doc.activeInkBezier = "0"); - doc.activeFillColor ?? (doc.activeFillColor = ""); - doc.activeArrowStart ?? (doc.activeArrowStart = ""); - doc.activeArrowEnd ?? (doc.activeArrowEnd = ""); - doc.activeDash ?? (doc.activeDash == "0"); - doc.fontSize ?? (doc.fontSize = "12px"); - doc.fontFamily ?? (doc.fontFamily = "Arial"); - doc.fontColor ?? (doc.fontColor = "black"); - doc.fontHighlight ?? (doc.fontHighlight = ""); + doc.activeInkBezier ?? (doc.activeInkBezier = '0'); + doc.activeFillColor ?? (doc.activeFillColor = ''); + doc.activeArrowStart ?? (doc.activeArrowStart = ''); + doc.activeArrowEnd ?? (doc.activeArrowEnd = ''); + doc.activeDash ?? doc.activeDash == '0'; + doc.fontSize ?? (doc.fontSize = '12px'); + doc.fontFamily ?? (doc.fontFamily = 'Arial'); + doc.fontColor ?? (doc.fontColor = 'black'); + doc.fontHighlight ?? (doc.fontHighlight = ''); doc.defaultAclPrivate ?? (doc.defaultAclPrivate = false); doc.savedFilters ?? (doc.savedFilters = new List<Doc>()); doc.filterDocCount = 0; - doc.freezeChildren = "remove|add"; + doc.freezeChildren = 'remove|add'; this.setupLinkDocs(doc, linkDatabaseId); - this.setupSharedDocs(doc, sharingDocumentId); // sets up the right sidebar collection for mobile upload documents and sharing - this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon + this.setupSharedDocs(doc, sharingDocumentId); // sets up the right sidebar collection for mobile upload documents and sharing + this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile - this.setupOverlays(doc); // sets up the overlay panel where documents and other widgets can be added to float over the rest of the dashboard - this.setupPublished(doc); // sets up the list doc of all docs that have been published (meaning that they can be auto-linked by typing their title into another text box) + this.setupOverlays(doc); // sets up the overlay panel where documents and other widgets can be added to float over the rest of the dashboard + this.setupPublished(doc); // sets up the list doc of all docs that have been published (meaning that they can be auto-linked by typing their title into another text box) this.setupContextMenuButtons(doc); // set up the row of buttons at the top of the dashboard that change depending on what is selected - this.setupDockedButtons(doc); // the bottom bar of font icons + this.setupDockedButtons(doc); // the bottom bar of font icons this.setupLeftSidebarMenu(doc); // the left-side column of buttons that open their contents in a flyout panel on the left this.setupDocTemplates(doc); // sets up the template menu of templates this.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption - this.AssignDocField(doc, "globalScriptDatabase", (opts) => Docs.Prototypes.MainScriptDocument(), {}); - this.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "header bar", system: true }); // drop down panel at top of dashboard for stashing documents - + this.AssignDocField( + doc, + 'globalScriptDatabase', + (opts) => Docs.Prototypes.MainScriptDocument(), + {} + ); + this.AssignDocField( + doc, + 'myHeaderBar', + (opts) => Docs.Create.MulticolumnDocument([], opts), + { title: 'header bar', system: true } + ); // drop down panel at top of dashboard for stashing documents + if (doc.activeDashboard instanceof Doc) { // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss) - doc.activeDashboard.colorScheme = doc.activeDashboard.colorScheme === ColorScheme.Light ? undefined : doc.activeDashboard.colorScheme; + doc.activeDashboard.colorScheme = + doc.activeDashboard.colorScheme === ColorScheme.Light + ? undefined + : doc.activeDashboard.colorScheme; } new LinkManager(); DocServer.UPDATE_SERVER_CACHE(); return doc; } - static setupFieldInfos(doc:Doc, field="fieldInfos") { - const fieldInfoOpts = { title: "Field Infos", system: true}; // bcz: all possible document options have associated field infos which are stored onn the FieldInfos document **except for title and system which are used as part of the definition of the fieldInfos object - const infos = this.AssignDocField(doc, field, opts => Doc.assign(new Doc(), opts as any), fieldInfoOpts); + static setupFieldInfos(doc: Doc, field = 'fieldInfos') { + const fieldInfoOpts = { title: 'Field Infos', system: true }; // bcz: all possible document options have associated field infos which are stored onn the FieldInfos document **except for title and system which are used as part of the definition of the fieldInfos object + const infos = this.AssignDocField( + doc, + field, + (opts) => Doc.assign(new Doc(), opts as any), + fieldInfoOpts + ); const entries = Object.entries(new DocumentOptions()); - entries.forEach(pair => { + entries.forEach((pair) => { if (!Array.from(Object.keys(fieldInfoOpts)).includes(pair[0])) { const options = pair[1] as FInfo; - const opts:DocumentOptions = { system: true, title: pair[0], ...OmitKeys(options, ["values"]).omit, fieldIsLayout: pair[0].startsWith("_")}; + const opts: DocumentOptions = { + system: true, + title: pair[0], + ...OmitKeys(options, ['values']).omit, + fieldIsLayout: pair[0].startsWith('_'), + }; switch (options.fieldType) { - case "boolean": opts.fieldValues = new List<boolean>(options.values as any); break; - case "number": opts.fieldValues = new List<number>(options.values as any); break; - case "Doc": opts.fieldValues = new List<Doc>(options.values as any); break; - default: opts.fieldValues = new List<string>(options.values as any); break;// string, pointerEvents, dimUnit, dropActionType + case 'boolean': + opts.fieldValues = new List<boolean>( + options.values as any + ); + break; + case 'number': + opts.fieldValues = new List<number>( + options.values as any + ); + break; + case 'Doc': + opts.fieldValues = new List<Doc>(options.values as any); + break; + default: + opts.fieldValues = new List<string>( + options.values as any + ); + break; // string, pointerEvents, dimUnit, dropActionType } - this.AssignDocField(infos, pair[0], opts => Doc.assign(new Doc(), OmitKeys(opts,["values"]).omit), opts); + this.AssignDocField( + infos, + pair[0], + (opts) => + Doc.assign(new Doc(), OmitKeys(opts, ['values']).omit), + opts + ); } }); } public static async loadCurrentUser() { - return rp.get(Utils.prepend("/getCurrentUser")).then(async response => { - if (response) { - const result: { id: string, email: string, cacheDocumentIds: string } = JSON.parse(response); - Doc.CurrentUserEmail = result.email; - resolvedPorts = JSON.parse(await (await fetch("/resolvedPorts")).text()); - DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, result.email); - result.cacheDocumentIds && (await DocServer.GetRefFields(result.cacheDocumentIds.split(";"))); - return result; - } else { - throw new Error("There should be a user! Why does Dash think there isn't one?"); - } - }); + return rp + .get(Utils.prepend('/getCurrentUser')) + .then(async (response) => { + if (response) { + const result: { + id: string; + email: string; + cacheDocumentIds: string; + } = JSON.parse(response); + Doc.CurrentUserEmail = result.email; + resolvedPorts = JSON.parse( + await (await fetch('/resolvedPorts')).text() + ); + DocServer.init( + window.location.protocol, + window.location.hostname, + resolvedPorts.socket, + result.email + ); + result.cacheDocumentIds && + (await DocServer.GetRefFields( + result.cacheDocumentIds.split(';') + )); + return result; + } else { + throw new Error( + "There should be a user! Why does Dash think there isn't one?" + ); + } + }); } public static async loadUserDocument(id: string) { this.curr_id = id; - await rp.get(Utils.prepend("/getUserDocumentIds")).then(ids => { - const { userDocumentId, sharingDocumentId, linkDatabaseId } = JSON.parse(ids); - if (userDocumentId !== "guest") { - return DocServer.GetRefField(userDocumentId).then(async field => { - Docs.newAccount = !(field instanceof Doc); - await Docs.Prototypes.initialize(); - const userDoc = Docs.newAccount ? new Doc(userDocumentId, true) : field as Doc; - Docs.newAccount &&(userDoc.activePage = "home"); - return this.updateUserDocument(Doc.SetUserDoc(userDoc), sharingDocumentId, linkDatabaseId); - }); + await rp.get(Utils.prepend('/getUserDocumentIds')).then((ids) => { + const { userDocumentId, sharingDocumentId, linkDatabaseId } = + JSON.parse(ids); + if (userDocumentId !== 'guest') { + return DocServer.GetRefField(userDocumentId).then( + async (field) => { + Docs.newAccount = !(field instanceof Doc); + await Docs.Prototypes.initialize(); + const userDoc = Docs.newAccount + ? new Doc(userDocumentId, true) + : (field as Doc); + Docs.newAccount && (userDoc.activePage = 'home'); + return this.updateUserDocument( + Doc.SetUserDoc(userDoc), + sharingDocumentId, + linkDatabaseId + ); + } + ); } else { - throw new Error("There should be a user id! Why does Dash think there isn't one?"); + throw new Error( + "There should be a user id! Why does Dash think there isn't one?" + ); } }); } @@ -1030,25 +2297,31 @@ export class CurrentUserUtils { /// opens a dashboard as the ActiveDashboard (and adds the dashboard to the users list of dashboards if it's not already there). /// this also sets the readonly state of the dashboard based on the current mode of dash (from its url) - public static openDashboard = (doc: Doc|undefined, fromHistory = false) => { + public static openDashboard = ( + doc: Doc | undefined, + fromHistory = false + ) => { if (!doc) return false; CurrentUserUtils.MainDocId = doc[Id]; - Doc.AddDocToList(CurrentUserUtils.MyDashboards, "data", doc); + Doc.AddDocToList(CurrentUserUtils.MyDashboards, 'data', doc); // this has the side-effect of setting the main container since we're assigning the active/guest dashboard - Doc.UserDoc() ? (CurrentUserUtils.ActiveDashboard = doc) : (CurrentUserUtils.GuestDashboard = doc); - + Doc.UserDoc() + ? (CurrentUserUtils.ActiveDashboard = doc) + : (CurrentUserUtils.GuestDashboard = doc); + const state = CurrentUserUtils._urlState; if (state.sharing === true && !Doc.UserDoc()) { DocServer.Control.makeReadOnly(); } else { - fromHistory || HistoryUtil.pushState({ - type: "doc", - docId: doc[Id], - readonly: state.readonly, - nro: state.nro, - sharing: false, - }); + 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) { @@ -1056,7 +2329,11 @@ export class CurrentUserUtils { DocServer.Control.makeReadOnly(); } CollectionView.SetSafeMode(true); - } else if (state.nro || state.nro === null || state.readonly === false) { + } else if ( + state.nro || + state.nro === null || + state.readonly === false + ) { } else if (doc.readOnly) { DocServer.Control.makeReadOnly(); } else { @@ -1065,15 +2342,15 @@ export class CurrentUserUtils { } return true; - } + }; public static importDocument = () => { - const input = document.createElement("input"); - input.type = "file"; + const input = document.createElement('input'); + input.type = 'file'; input.multiple = true; - input.accept = ".zip, application/pdf, video/*, image/*, audio/*"; - input.onchange = async _e => { - const upload = Utils.prepend("/uploadDoc"); + input.accept = '.zip, application/pdf, video/*, image/*, audio/*'; + input.onchange = async (_e) => { + const upload = Utils.prepend('/uploadDoc'); const formData = new FormData(); const file = input.files?.[0]; if (file?.type === 'application/zip') { @@ -1082,38 +2359,69 @@ export class CurrentUserUtils { // setTimeout(() => SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs => // docs.docs.forEach(d => LinkManager.Instance.addLink(d))), 2000); // need to give solr some time to update so that this query will find any link docs we've added. // } - const list = Cast(CurrentUserUtils.MyImports.data, listSpec(Doc), null); + const list = Cast( + CurrentUserUtils.MyImports.data, + listSpec(Doc), + null + ); doc instanceof Doc && list?.splice(0, 0, doc); } else if (input.files && input.files.length !== 0) { const disposer = OverlayView.ShowSpinner(); - const results = await DocUtils.uploadFilesToDocs(Array.from(input.files || []), {}); + const results = await DocUtils.uploadFilesToDocs( + Array.from(input.files || []), + {} + ); if (results.length !== input.files?.length) { - alert("Error uploading files - possibly due to unsupported file types"); + alert( + 'Error uploading files - possibly due to unsupported file types' + ); } - const list = Cast(CurrentUserUtils.MyImports.data, listSpec(Doc), null); + const list = Cast( + CurrentUserUtils.MyImports.data, + listSpec(Doc), + null + ); list?.splice(0, 0, ...results); disposer(); } else { - console.log("No file selected"); + console.log('No file selected'); } }; input.click(); + }; + + public static snapshotDashboard() { + return CollectionDockingView.TakeSnapshot( + CurrentUserUtils.ActiveDashboard + ); } - - public static snapshotDashboard() { return CollectionDockingView.TakeSnapshot(CurrentUserUtils.ActiveDashboard); } - public static closeActiveDashboard = () => { CurrentUserUtils.ActiveDashboard = undefined; } + public static closeActiveDashboard = () => { + CurrentUserUtils.ActiveDashboard = undefined; + }; - public static removeDashboard = async (dashboard:Doc) => { - const dashboards = await DocListCastAsync(CurrentUserUtils.MyDashboards.data); + public static removeDashboard = async (dashboard: Doc) => { + const dashboards = await DocListCastAsync( + CurrentUserUtils.MyDashboards.data + ); if (dashboards?.length) { - if (dashboard === CurrentUserUtils.ActiveDashboard) CurrentUserUtils.openDashboard(dashboards.find(doc => doc !== dashboard)); - Doc.RemoveDocFromList(CurrentUserUtils.MyDashboards, "data", dashboard); - if (!dashboards.length) CurrentUserUtils.ActivePage = "home"; + if (dashboard === CurrentUserUtils.ActiveDashboard) + CurrentUserUtils.openDashboard( + dashboards.find((doc) => doc !== dashboard) + ); + Doc.RemoveDocFromList( + CurrentUserUtils.MyDashboards, + 'data', + dashboard + ); + if (!dashboards.length) CurrentUserUtils.ActivePage = 'home'; } - } + }; public static createNewDashboard = (id?: string, name?: string) => { - const presentation = Doc.MakeCopy(Doc.UserDoc().emptyPresentation as Doc, true); + const presentation = Doc.MakeCopy( + Doc.UserDoc().emptyPresentation as Doc, + true + ); const dashboards = CurrentUserUtils.MyDashboards; const dashboardCount = DocListCast(dashboards.data).length + 1; const freeformOptions: DocumentOptions = { @@ -1125,84 +2433,211 @@ export class CurrentUserUtils { _backgroundGridShow: true, title: `Untitled Tab 1`, }; - const title = name ? name : `Dashboard ${dashboardCount}` - const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); - const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: title }, id, "row"); + const title = name ? name : `Dashboard ${dashboardCount}`; + const freeformDoc = + CurrentUserUtils.GuestTarget || + Docs.Create.FreeformDocument([], freeformOptions); + const dashboardDoc = Docs.Create.StandardCollectionDockingDocument( + [{ doc: freeformDoc, initialWidth: 600 }], + { title: title }, + id, + 'row' + ); freeformDoc.context = dashboardDoc; // switching the tabs from the datadoc to the regular doc const dashboardTabs = DocListCast(dashboardDoc[DataSym].data); dashboardDoc.data = new List<Doc>(dashboardTabs); - dashboardDoc["pane-count"] = 1; + dashboardDoc['pane-count'] = 1; CurrentUserUtils.ActivePresentation = presentation; - Doc.AddDocToList(dashboards, "data", dashboardDoc); - // open this new dashboard + Doc.AddDocToList(dashboards, 'data', dashboardDoc); + // open this new dashboard CurrentUserUtils.ActiveDashboard = dashboardDoc; - CurrentUserUtils.ActivePage = "dashboard"; - } - - public static GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, maxHeight?: number, backgroundColor?: string) { - const tbox = Docs.Create.TextDocument("", { - _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, docMaxAutoHeight: maxHeight, backgroundColor: backgroundColor, - _width: width || 200, _height: 35, x: x, y: y, _fitWidth: true, _autoHeight: true, title + CurrentUserUtils.ActivePage = 'dashboard'; + }; + + public static GetNewTextDoc( + title: string, + x: number, + y: number, + width?: number, + height?: number, + noMargins?: boolean, + annotationOn?: Doc, + maxHeight?: number, + backgroundColor?: string + ) { + const tbox = Docs.Create.TextDocument('', { + _xMargin: noMargins ? 0 : undefined, + _yMargin: noMargins ? 0 : undefined, + annotationOn, + docMaxAutoHeight: maxHeight, + backgroundColor: backgroundColor, + _width: width || 200, + _height: 35, + x: x, + y: y, + _fitWidth: true, + _autoHeight: true, + title, }); const template = Doc.UserDoc().defaultTextLayout; if (template instanceof Doc) { tbox._width = NumCast(template._width); - tbox.layoutKey = "layout_" + StrCast(template.title); + tbox.layoutKey = 'layout_' + StrCast(template.title); Doc.GetProto(tbox)[StrCast(tbox.layoutKey)] = template; } return tbox; } - public static get MyUserDocView() { return DocCast(Doc.UserDoc().myUserDocView); } - public static get MyDockedBtns() { return DocCast(Doc.UserDoc().myDockedBtns); } - public static get MySearcher() { return DocCast(Doc.UserDoc().mySearcher); } - public static get MyFilesystem() { return DocCast(Doc.UserDoc().myFilesystem); } - public static get MyHeaderBar() { return DocCast(Doc.UserDoc().myHeaderBar); } - public static get MyTools() { return DocCast(Doc.UserDoc().myTools); } - public static get MyDashboards() { return DocCast(Doc.UserDoc().myDashboards); } - public static get MyFileOrphans() { return DocCast(Doc.UserDoc().myFileOrphans); } - public static get MyTemplates() { return DocCast(Doc.UserDoc().myTemplates); } - public static get MyLeftSidebarMenu() { return DocCast(Doc.UserDoc().myLeftSidebarMenu); } - public static get MyLeftSidebarPanel() { return DocCast(Doc.UserDoc().myLeftSidebarPanel); } - public static get MySharedDocs() { return DocCast(Doc.UserDoc().mySharedDocs); } - public static get MyTrails() { return DocCast(Doc.UserDoc().myTrails); } - public static get MyImports() { return DocCast(Doc.UserDoc().myImports); } - public static get MyContextMenuBtns() { return DocCast(Doc.UserDoc().myContextMenuBtns); } - public static get MyRecentlyClosed() { return DocCast(Doc.UserDoc().myRecentlyClosed); } - public static get MyOverlayDocs() { return DocCast(Doc.UserDoc().myOverlayDocs); } - public static get MyPublishedDocs() { return DocCast(Doc.UserDoc().myPublishedDocs); } - public static get ActiveDashboard() { return DocCast(Doc.UserDoc().activeDashboard); } - public static set ActiveDashboard(val:Doc|undefined) { Doc.UserDoc().activeDashboard = val; } - public static get ActivePresentation() { return DocCast(Doc.UserDoc().activePresentation); } - public static set ActivePresentation(val) { Doc.UserDoc().activePresentation = val; } - public static get ActivePage() { return StrCast(Doc.UserDoc().activePage); } - public static set ActivePage(val) { Doc.UserDoc().activePage = val; } - public static set ActiveTool(tool: InkTool) { Doc.UserDoc().activeTool = tool; } - public static get ActiveTool(): InkTool { return StrCast(Doc.UserDoc().activeTool, InkTool.None) as InkTool; } + public static get MyUserDocView() { + return DocCast(Doc.UserDoc().myUserDocView); + } + public static get MyDockedBtns() { + return DocCast(Doc.UserDoc().myDockedBtns); + } + public static get MySearcher() { + return DocCast(Doc.UserDoc().mySearcher); + } + public static get MyFilesystem() { + return DocCast(Doc.UserDoc().myFilesystem); + } + public static get MyHeaderBar() { + return DocCast(Doc.UserDoc().myHeaderBar); + } + public static get MyTools() { + return DocCast(Doc.UserDoc().myTools); + } + public static get MyDashboards() { + return DocCast(Doc.UserDoc().myDashboards); + } + public static get MyFileOrphans() { + return DocCast(Doc.UserDoc().myFileOrphans); + } + public static get MyTemplates() { + return DocCast(Doc.UserDoc().myTemplates); + } + public static get MyLeftSidebarMenu() { + return DocCast(Doc.UserDoc().myLeftSidebarMenu); + } + public static get MyLeftSidebarPanel() { + return DocCast(Doc.UserDoc().myLeftSidebarPanel); + } + public static get MySharedDocs() { + return DocCast(Doc.UserDoc().mySharedDocs); + } + public static get MyTrails() { + return DocCast(Doc.UserDoc().myTrails); + } + public static get MyImports() { + return DocCast(Doc.UserDoc().myImports); + } + public static get MyContextMenuBtns() { + return DocCast(Doc.UserDoc().myContextMenuBtns); + } + public static get MyRecentlyClosed() { + return DocCast(Doc.UserDoc().myRecentlyClosed); + } + public static get MyOverlayDocs() { + return DocCast(Doc.UserDoc().myOverlayDocs); + } + public static get MyPublishedDocs() { + return DocCast(Doc.UserDoc().myPublishedDocs); + } + public static get ActiveDashboard() { + return DocCast(Doc.UserDoc().activeDashboard); + } + public static set ActiveDashboard(val: Doc | undefined) { + Doc.UserDoc().activeDashboard = val; + } + public static get ActivePresentation() { + return DocCast(Doc.UserDoc().activePresentation); + } + public static set ActivePresentation(val) { + Doc.UserDoc().activePresentation = val; + } + public static get ActivePage() { + return StrCast(Doc.UserDoc().activePage); + } + public static set ActivePage(val) { + Doc.UserDoc().activePage = val; + } + public static set ActiveTool(tool: InkTool) { + Doc.UserDoc().activeTool = tool; + } + public static get ActiveTool(): InkTool { + return StrCast(Doc.UserDoc().activeTool, InkTool.None) as InkTool; + } } -ScriptingGlobals.add(function MySharedDocs() { return CurrentUserUtils.MySharedDocs; }, "document containing all shared Docs"); -ScriptingGlobals.add(function IsNoviceMode() { return Doc.noviceMode; }, "is Dash in novice mode"); -ScriptingGlobals.add(function toggleComicMode() { Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; }, "switches between comic and normal document rendering"); -ScriptingGlobals.add(function snapshotDashboard() { CurrentUserUtils.snapshotDashboard(); }, "creates a snapshot copy of a dashboard"); -ScriptingGlobals.add(function createNewDashboard() { return CurrentUserUtils.createNewDashboard(); }, "creates a new dashboard when called"); -ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance.createNewPresentation(); }, "creates a new presentation when called"); -ScriptingGlobals.add(function createNewFolder() { return MainView.Instance.createNewFolder(); }, "creates a new folder in myFiles when called"); -ScriptingGlobals.add(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, "returns all the links to the document or its annotations", "(doc: any)"); -ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.importDocument(); }, "imports files from device directly into the import sidebar"); -ScriptingGlobals.add(function shareDashboard(dashboard: Doc) { SharingManager.Instance.open(undefined, dashboard); }, "opens sharing dialog for Dashboard"); -ScriptingGlobals.add(function removeDashboard(dashboard: Doc) { CurrentUserUtils.removeDashboard(dashboard); }, "Remove Dashboard from Dashboards"); -ScriptingGlobals.add(function addToDashboards(dashboard: Doc) { CurrentUserUtils.openDashboard( Doc.MakeAlias(dashboard)); }, "adds Dashboard to set of Dashboards"); -ScriptingGlobals.add(function selectedDocumentType(docType?: DocumentType, colType?: CollectionViewType, checkContext?: boolean) { - let selected = (sel => checkContext ? DocCast(sel?.context) : sel)(SelectionManager.SelectedSchemaDoc() ?? SelectionManager.Docs().lastElement()); - return docType ? selected?.type === docType : colType ? selected?.viewType === colType : true; +ScriptingGlobals.add(function MySharedDocs() { + return CurrentUserUtils.MySharedDocs; +}, 'document containing all shared Docs'); +ScriptingGlobals.add(function IsNoviceMode() { + return Doc.noviceMode; +}, 'is Dash in novice mode'); +ScriptingGlobals.add(function toggleComicMode() { + Doc.UserDoc().renderStyle = + Doc.UserDoc().renderStyle === 'comic' ? undefined : 'comic'; +}, 'switches between comic and normal document rendering'); +ScriptingGlobals.add(function snapshotDashboard() { + CurrentUserUtils.snapshotDashboard(); +}, 'creates a snapshot copy of a dashboard'); +ScriptingGlobals.add(function createNewDashboard() { + return CurrentUserUtils.createNewDashboard(); +}, 'creates a new dashboard when called'); +ScriptingGlobals.add(function createNewPresentation() { + return MainView.Instance.createNewPresentation(); +}, 'creates a new presentation when called'); +ScriptingGlobals.add(function createNewFolder() { + return MainView.Instance.createNewFolder(); +}, 'creates a new folder in myFiles when called'); +ScriptingGlobals.add( + function links(doc: any) { + return new List(LinkManager.Instance.getAllRelatedLinks(doc)); + }, + 'returns all the links to the document or its annotations', + '(doc: any)' +); +ScriptingGlobals.add(function importDocument() { + return CurrentUserUtils.importDocument(); +}, 'imports files from device directly into the import sidebar'); +ScriptingGlobals.add(function shareDashboard(dashboard: Doc) { + SharingManager.Instance.open(undefined, dashboard); +}, 'opens sharing dialog for Dashboard'); +ScriptingGlobals.add(function removeDashboard(dashboard: Doc) { + CurrentUserUtils.removeDashboard(dashboard); +}, 'Remove Dashboard from Dashboards'); +ScriptingGlobals.add(function addToDashboards(dashboard: Doc) { + CurrentUserUtils.openDashboard(Doc.MakeAlias(dashboard)); +}, 'adds Dashboard to set of Dashboards'); +ScriptingGlobals.add(function selectedDocumentType( + docType?: DocumentType, + colType?: CollectionViewType, + checkContext?: boolean +) { + let selected = ((sel) => (checkContext ? DocCast(sel?.context) : sel))( + SelectionManager.SelectedSchemaDoc() ?? + SelectionManager.Docs().lastElement() + ); + return docType + ? selected?.type === docType + : colType + ? selected?.viewType === colType + : true; }); ScriptingGlobals.add(function makeTopLevelFolder() { TreeView._editTitleOnLoad = { id: Utils.GenerateGuid(), parent: undefined }; - const opts = { title: "Untitled folder", _stayInCollection: true, isFolder: true }; - return Doc.AddDocToList(CurrentUserUtils.MyFilesystem, "data", Docs.Create.TreeDocument([], opts, TreeView._editTitleOnLoad.id)); -});
\ No newline at end of file + const opts = { + title: 'Untitled folder', + _stayInCollection: true, + isFolder: true, + }; + return Doc.AddDocToList( + CurrentUserUtils.MyFilesystem, + 'data', + Docs.Create.TreeDocument([], opts, TreeView._editTitleOnLoad.id) + ); +}); |