aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
authorAubrey Li <Aubrey-Li>2021-09-15 14:41:24 -0400
committerAubrey Li <Aubrey-Li>2021-09-15 14:41:24 -0400
commiteb63330e172935343767d0dcc7ffad9bfa1a75c4 (patch)
tree031bf155df50200f9652e881aec18002bc9e399e /src/client/util
parentb7a88c6292c2e7bfffc3cdc4f7c7037922b3de25 (diff)
parent8386ad690c10d5c76bbd1b4f85314514b7f11b55 (diff)
merge master into trails-aubrey
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CurrentUserUtils.ts516
-rw-r--r--src/client/util/DocumentManager.ts60
-rw-r--r--src/client/util/DragManager.ts16
-rw-r--r--src/client/util/HypothesisUtils.ts2
-rw-r--r--src/client/util/InteractionUtils.tsx10
-rw-r--r--src/client/util/LinkManager.ts38
-rw-r--r--src/client/util/Scripting.ts12
-rw-r--r--src/client/util/SelectionManager.ts14
-rw-r--r--src/client/util/SettingsManager.scss5
9 files changed, 504 insertions, 169 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index b4e6d9be9..f40cae676 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -22,6 +22,7 @@ import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMu
import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
import { Colors } from "../views/global/globalEnums";
import { MainView } from "../views/MainView";
+import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox";
import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
import { LabelBox } from "../views/nodes/LabelBox";
import { OverlayView } from "../views/OverlayView";
@@ -37,7 +38,25 @@ import { ColorScheme } from "./SettingsManager";
import { SharingManager } from "./SharingManager";
import { SnappingManager } from "./SnappingManager";
import { UndoManager } from "./UndoManager";
-
+import { TreeView } from "../views/collections/TreeView";
+
+interface Button {
+ title?: string;
+ toolTip?: string;
+ icon?: string;
+ btnType?: ButtonType;
+ click?: string;
+ numBtnType?: NumButtonType;
+ numBtnMin?: number;
+ numBtnMax?: number;
+ switchToggle?: boolean;
+ script?: string;
+ checkResult?: string;
+ width?: number;
+ list?: string[];
+ ignoreClick?: boolean;
+ buttonText?: string;
+}
export let resolvedPorts: { server: number, socket: number };
const headerViewVersion = "0.1";
@@ -66,16 +85,17 @@ export class CurrentUserUtils {
title: "NEW MOBILE BUTTON",
onClick: undefined,
},
- [this.ficon({
+ [this.createToolButton({
ignoreClick: true,
icon: "mobile",
+ btnType: ButtonType.ToolButton,
backgroundColor: "transparent"
}),
this.mobileTextContainer({},
[this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])]);
- doc["template-mobile-button"] = CurrentUserUtils.ficon({
+ doc["template-mobile-button"] = CurrentUserUtils.createToolButton({
onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
- dragFactory: new PrefetchProxy(queryTemplate) as any as Doc, title: "mobile button", icon: "mobile"
+ dragFactory: new PrefetchProxy(queryTemplate) as any as Doc, title: "mobile button", icon: "mobile", btnType: ButtonType.ToolButton,
});
}
@@ -83,14 +103,15 @@ export class CurrentUserUtils {
const slideTemplate = Docs.Create.MultirowDocument(
[
Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }),
- Docs.Create.TextDocument("", { title: "text", _height: 100, system: true })
+ Docs.Create.TextDocument("", { title: "text", _height: 100, system: true, _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize) })
],
{ _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true }
);
slideTemplate.isTemplateDoc = makeTemplate(slideTemplate);
- doc["template-button-slides"] = CurrentUserUtils.ficon({
+ doc["template-button-slides"] = CurrentUserUtils.createToolButton({
onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
- dragFactory: new PrefetchProxy(slideTemplate) as any as Doc, title: "presentation slide", icon: "address-card"
+ dragFactory: new PrefetchProxy(slideTemplate) as any as Doc, title: "presentation slide", icon: "address-card",
+ btnType: ButtonType.ToolButton
});
}
@@ -134,9 +155,10 @@ export class CurrentUserUtils {
};
linkTemplate.header = new RichTextField(JSON.stringify(rtf2), "");
- doc["template-button-link"] = CurrentUserUtils.ficon({
+ doc["template-button-link"] = CurrentUserUtils.createToolButton({
onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
- dragFactory: new PrefetchProxy(linkTemplate) as any as Doc, title: "link view", icon: "window-maximize", system: true
+ dragFactory: new PrefetchProxy(linkTemplate) as any as Doc, title: "link view", icon: "window-maximize", system: true,
+ btnType: ButtonType.ToolButton
});
}
@@ -165,9 +187,10 @@ export class CurrentUserUtils {
const box = MulticolumnDocument([/*no, */ yes, name], { title: "value", _width: 120, _height: 35, system: true });
box.isTemplateDoc = makeTemplate(box, true, "switch");
- doc["template-button-switch"] = CurrentUserUtils.ficon({
+ doc["template-button-switch"] = CurrentUserUtils.createToolButton({
onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
- dragFactory: new PrefetchProxy(box) as any as Doc, title: "data switch", icon: "toggle-on", system: true
+ dragFactory: new PrefetchProxy(box) as any as Doc, title: "data switch", icon: "toggle-on", system: true,
+ btnType: ButtonType.ToolButton
});
}
@@ -214,9 +237,13 @@ export class CurrentUserUtils {
short.title = "A Short Description";
long.title = "Long Description";
- doc["template-button-detail"] = CurrentUserUtils.ficon({
+ doc["template-button-detail"] = CurrentUserUtils.createToolButton({
onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
- dragFactory: new PrefetchProxy(detailView) as any as Doc, title: "detailView", icon: "window-maximize", system: true
+ dragFactory: new PrefetchProxy(detailView) as any as Doc,
+ title: "detailView",
+ icon: "window-maximize",
+ system: true,
+ btnType: ButtonType.ToolButton,
});
}
@@ -231,7 +258,7 @@ export class CurrentUserUtils {
doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, {
title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", _chromeHidden: true,
hidden: ComputedField.MakeFunction("IsNoviceMode()") as any,
- _stayInCollection: true, _hideContextMenu: true,
+ _stayInCollection: true, _hideContextMenu: true, _forceActive: true,
_autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
}));
@@ -248,37 +275,47 @@ export class CurrentUserUtils {
// setup the different note type skins
static setupNoteTemplates(doc: Doc) {
if (doc["template-note-Note"] === undefined) {
- const noteView = Docs.Create.TextDocument("", { title: "text", isTemplateDoc: true, backgroundColor: "yellow", system: true });
+ const noteView = Docs.Create.TextDocument("", {
+ title: "text", isTemplateDoc: true, backgroundColor: "yellow", system: true, icon: "sticky-note",
+ _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
+ });
noteView.isTemplateDoc = makeTemplate(noteView, true, "Note");
doc["template-note-Note"] = new PrefetchProxy(noteView);
}
if (doc["template-note-Idea"] === undefined) {
- const noteView = Docs.Create.TextDocument("", { title: "text", backgroundColor: "pink", system: true });
+ const noteView = Docs.Create.TextDocument("", {
+ title: "text", backgroundColor: "pink", system: true, icon: "lightbulb",
+ _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
+ });
noteView.isTemplateDoc = makeTemplate(noteView, true, "Idea");
doc["template-note-Idea"] = new PrefetchProxy(noteView);
}
if (doc["template-note-Topic"] === undefined) {
- const noteView = Docs.Create.TextDocument("", { title: "text", backgroundColor: "lightblue", system: true });
- noteView.isTemplateDoc = makeTemplate(noteView, true, "Topic");
- doc["template-note-Topic"] = new PrefetchProxy(noteView);
- }
- if (doc["template-note-Todo"] === undefined) {
const noteView = Docs.Create.TextDocument("", {
- title: "text", backgroundColor: "orange", _autoHeight: false, _height: 100, _showCaption: "caption",
- layout: FormattedTextBox.LayoutString("Todo"), caption: RichTextField.DashField("taskStatus"), system: true
+ title: "text", backgroundColor: "lightblue", system: true, icon: "book-open",
+ _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
});
- noteView.isTemplateDoc = makeTemplate(noteView, true, "Todo");
- doc["template-note-Todo"] = new PrefetchProxy(noteView);
- }
- const taskStatusValues = [
- { title: "todo", _backgroundColor: "blue", color: "white", system: true },
- { title: "in progress", _backgroundColor: "yellow", color: "black", system: true },
- { title: "completed", _backgroundColor: "green", color: "white", system: true }
- ];
- if (doc.fieldTypes === undefined) {
- doc.fieldTypes = Docs.Create.TreeDocument([], { title: "field enumerations", system: true });
- DocUtils.addFieldEnumerations(Doc.GetProto(doc["template-note-Todo"] as any as Doc), "taskStatus", taskStatusValues);
+ noteView.isTemplateDoc = makeTemplate(noteView, true, "Topic");
+ doc["template-note-Topic"] = new PrefetchProxy(noteView);
}
+ // if (doc["template-note-Todo"] === undefined) {
+ // const noteView = Docs.Create.TextDocument("", {
+ // title: "text", backgroundColor: "orange", _autoHeight: false, _height: 100, _showCaption: "caption",
+ // layout: FormattedTextBox.LayoutString("Todo"), caption: RichTextField.DashField("taskStatus"), system: true,
+ // _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
+ // });
+ // noteView.isTemplateDoc = makeTemplate(noteView, true, "Todo");
+ // doc["template-note-Todo"] = new PrefetchProxy(noteView);
+ // }
+ // const taskStatusValues = [
+ // { title: "todo", _backgroundColor: "blue", color: "white", system: true },
+ // { title: "in progress", _backgroundColor: "yellow", color: "black", system: true },
+ // { title: "completed", _backgroundColor: "green", color: "white", system: true }
+ // ];
+ // if (doc.fieldTypes === undefined) {
+ // doc.fieldTypes = Docs.Create.TreeDocument([], { title: "field enumerations", system: true });
+ // DocUtils.addFieldEnumerations(Doc.GetProto(doc["template-note-Todo"] as any as Doc), "taskStatus", taskStatusValues);
+ // }
if (doc["template-notes"] === undefined) {
doc["template-notes"] = new PrefetchProxy(Docs.Create.TreeDocument([doc["template-note-Note"] as any as Doc, doc["template-note-Idea"] as any as Doc, doc["template-note-Topic"] as any as Doc], // doc["template-note-Todo"] as any as Doc],
@@ -380,11 +417,11 @@ export class CurrentUserUtils {
((doc.emptyCollection as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyPane === undefined) {
- doc.emptyPane = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, _width: 500, _height: 800, title: "Untitled Tab", system: true, cloneFieldFilter: new List<string>(["system"]) });
+ doc.emptyPane = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _backgroundGridShow: true, _nativeHeight: undefined, _width: 500, _height: 800, title: "Untitled Tab", system: true, cloneFieldFilter: new List<string>(["system"]) });
((doc.emptyPane as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptySlide === undefined) {
- const textDoc = Docs.Create.TreeDocument([], { title: "Slide", _viewType: CollectionViewType.Tree, _fontSize: "20px", treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "transparent", system: true, cloneFieldFilter: new List<string>(["system"]) });
+ const textDoc = Docs.Create.TreeDocument([], { title: "Slide", _viewType: CollectionViewType.Tree, _fontSize: "20px", _autoHeight: true, treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "transparent", system: true, cloneFieldFilter: new List<string>(["system"]) });
Doc.GetProto(textDoc).title = ComputedField.MakeFunction('self.text?.Text');
FormattedTextBox.SelectOnLoad = textDoc[Id];
doc.emptySlide = textDoc;
@@ -410,16 +447,16 @@ export class CurrentUserUtils {
storedMarks: []
};
const headerTemplate = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), {
- title: "text", version: headerViewVersion, target: doc, _height: 70, _headerPointerEvents: "all",
+ title: "text", version: headerViewVersion, _height: 70, _headerPointerEvents: "all",
_headerHeight: 12, _headerFontSize: 9, _autoHeight: true, system: true, _fitWidth: true,
cloneFieldFilter: new List<string>(["system"])
}, "header");
const headerBtnHgt = 10;
headerTemplate[DataSym].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}px)'/>` +
- " <FormattedTextBox {...props} dontScale='true' fieldKey={'header'} dontSelectOnLoad='true' ignoreAutoHeight='true' fontSize='{this._headerFontSize}px' height='{(this._headerHeight||1)}px' background='{this._headerColor ||this.target.mySharedDocs.userColor||`lightGray`}' />" +
- ` <HTMLdiv fontSize='${headerBtnHgt - 1}px' height='${headerBtnHgt}px' background='yellow' onClick={‘(this._headerHeight=scale*Math.min(Math.max(1,this._height-30),this._headerHeight===1?50:1)) && (this._autoHeightMargins=this._headerHeight+${headerBtnHgt})’} >Metadata</HTMLdiv>` +
+ ` <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>";
// "<div style={'height:100%'}>" +
@@ -431,25 +468,29 @@ export class CurrentUserUtils {
((doc.emptyHeader as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyComparison === undefined) {
- doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "compare", _width: 300, _height: 300, system: true, cloneFieldFilter: new List<string>(["system"]) });
+ doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "comparison box", _width: 300, _height: 300, system: true, cloneFieldFilter: new List<string>(["system"]) });
}
if (doc.emptyScript === undefined) {
doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250, title: "script", system: true, cloneFieldFilter: new List<string>(["system"]) });
((doc.emptyScript as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyScreenshot === undefined) {
- doc.emptyScreenshot = Docs.Create.ScreenshotDocument("empty screenshot", { _fitWidth: true, _width: 400, _height: 200, system: true, cloneFieldFilter: new List<string>(["system"]) });
+ doc.emptyScreenshot = Docs.Create.ScreenshotDocument("empty screenshot", { _fitWidth: true, title: "empty screenshot", _width: 400, _height: 200, system: true, cloneFieldFilter: new List<string>(["system"]) });
}
if (doc.emptyWall === undefined) {
doc.emptyWall = Docs.Create.ScreenshotDocument("", { _fitWidth: true, _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List<string>(["system"]) });
(doc.emptyWall as Doc).videoWall = true;
}
if (doc.emptyAudio === undefined) {
- doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "audio recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
+ doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, _height: 100, title: "audio recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
((doc.emptyAudio as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyNote === undefined) {
- doc.emptyNote = Docs.Create.TextDocument("", { _width: 200, title: "text note", _autoHeight: true, system: true, cloneFieldFilter: new List<string>(["system"]) });
+ doc.emptyNote = Docs.Create.TextDocument("", {
+ _width: 200, title: "text note", _autoHeight: true, system: true,
+ _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
+ cloneFieldFilter: new List<string>(["system"])
+ });
((doc.emptyNote as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyImage === undefined) {
@@ -460,7 +501,7 @@ export class CurrentUserUtils {
((doc.emptyButton as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyWebpage === undefined) {
- doc.emptyWebpage = Docs.Create.WebDocument("", { title: "webpage", _nativeWidth: 850, _height: 512, _width: 400, useCors: true, system: true, cloneFieldFilter: new List<string>(["system"]) });
+ doc.emptyWebpage = Docs.Create.WebDocument("http://www.bing.com/", { title: "webpage", _nativeWidth: 850, _height: 512, _width: 400, useCors: true, system: true, cloneFieldFilter: new List<string>(["system"]) });
}
if (doc.emptyMap === undefined) {
doc.emptyMap = Docs.Create.MapDocument([], { title: "map", _showSidebar: true, _width: 800, _height: 600, system: true, cloneFieldFilter: new List<string>(["system"]) });
@@ -473,10 +514,10 @@ export class CurrentUserUtils {
{ toolTip: "Tap to create a note in a new pane, drag for a note", title: "Note", icon: "sticky-note", click: 'openOnRight(copyDragFactory(this.clickFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyNote as Doc, noviceMode: true, clickFactory: doc.emptyNote as Doc, },
{ toolTip: "Tap to create a collection in a new pane, drag for a collection", title: "Col", icon: "folder", click: 'openOnRight(copyDragFactory(this.clickFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyCollection as Doc, noviceMode: true, clickFactory: doc.emptyPane as Doc, },
{ toolTip: "Tap to create a webpage in a new pane, drag for a webpage", title: "Web", icon: "globe-asia", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyWebpage as Doc, noviceMode: true },
- { toolTip: "Tap to create a progressive slide", title: "Slide", icon: "file", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySlide as Doc, noviceMode: true },
+ { toolTip: "Tap to create a progressive slide", title: "Slide", icon: "file", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySlide as Doc },
{ toolTip: "Tap to create a cat image in a new pane, drag for a cat image", title: "Image", icon: "cat", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyImage as Doc },
{ toolTip: "Tap to create a comparison box in a new pane, drag for a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyComparison as Doc, noviceMode: true },
- { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc, noviceMode: true },
+ { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc },
{ toolTip: "Tap to create a videoWall", title: "Wall", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyWall as Doc },
{ toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true },
{ toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc },
@@ -507,11 +548,13 @@ export class CurrentUserUtils {
icon,
title,
toolTip,
+ btnType: ButtonType.ToolButton,
ignoreClick,
_dropAction: "alias",
onDragStart: drag ? ScriptField.MakeFunction(drag) : undefined,
onClick: click ? ScriptField.MakeScript(click) : undefined,
- backgroundColor,
+ backgroundColor: backgroundColor ? backgroundColor : Colors.DARK_GRAY,
+ color: Colors.WHITE,
_hideContextMenu: true,
_removeDropProperties: new List<string>(["_stayInCollection"]),
_stayInCollection: true,
@@ -524,7 +567,7 @@ export class CurrentUserUtils {
if (dragCreatorSet === undefined) {
doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, {
title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true,
- _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
+ _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
}));
} else {
@@ -537,31 +580,31 @@ export class CurrentUserUtils {
return [
{ title: "Dashboards", target: Cast(doc.myDashboards, Doc, null), icon: "desktop", click: 'selectMainMenu(self)' },
{ title: "Search", target: Cast(doc.mySearchPanel, Doc, null), icon: "search", click: 'selectMainMenu(self)' },
- { title: "My Files", target: Cast(doc.myFilesystem, Doc, null), icon: "file", click: 'selectMainMenu(self)' },
- { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' },
- { title: "Import", target: Cast(doc.myImportPanel, Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
+ { title: "Files", target: Cast(doc.myFilesystem, Doc, null), icon: "folder-open", click: 'selectMainMenu(self)' },
+ { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)', hidden: "IsNoviceMode()" },
+ { title: "Imports", target: Cast(doc.myImportDocs, Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
{ title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' },
- { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc },
- { title: "Pres. Trails", target: Cast(doc.myPresentations, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' },
- // { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' },
- // { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' },
- { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' },
+ { title: "Shared with me", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc },
+ { title: "Trails", target: Cast(doc.myTrails, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' },
+ { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)', hidden: "IsNoviceMode()" },
];
}
static async setupMenuPanel(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) {
if (doc.menuStack === undefined) {
await this.setupSharingSidebar(doc, sharingDocumentId, linkDatabaseId); // sets up the right sidebar collection for mobile upload documents and sharing
- const menuBtns = (await CurrentUserUtils.menuBtnDescriptions(doc)).map(({ title, target, icon, click, watchedDocuments }) =>
+ const menuBtns = (await CurrentUserUtils.menuBtnDescriptions(doc)).map(({ title, target, icon, click, watchedDocuments, hidden }) =>
Docs.Create.FontIconDocument({
icon,
- iconShape: "square",
+ btnType: ButtonType.MenuButton,
_stayInCollection: true,
_hideContextMenu: true,
+ _chromeHidden: true,
system: true,
dontUndo: true,
title,
target,
+ hidden: hidden ? ComputedField.MakeFunction("IsNoviceMode()") as any : undefined,
_dropAction: "alias",
_removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
_width: 60,
@@ -576,8 +619,6 @@ export class CurrentUserUtils {
this.searchBtn = menuBtn;
}
});
- // hack -- last button is assumed to be the userDoc
- menuBtns[menuBtns.length - 1].hidden = ComputedField.MakeFunction("IsNoviceMode()");
menuBtns.forEach(menuBtn => {
if (menuBtn.title === "Search") {
@@ -633,7 +674,7 @@ export class CurrentUserUtils {
// SEts up mobile buttons for inside mobile menu
static setupMobileButtons(doc?: Doc, buttons?: string[]) {
- const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, activePen?: Doc, backgroundColor?: string, info: string, dragFactory?: Doc }[] = [
+ 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." },
{ title: "MOBILE UPLOAD", icon: "mobile", click: 'switchToMobileUploadCollection()', backgroundColor: "lightgrey", info: "Access the collection of your mobile uploads." },
@@ -649,7 +690,7 @@ export class CurrentUserUtils {
onClick: data.click ? ScriptField.MakeScript(data.click) : undefined,
backgroundColor: data.backgroundColor, system: true
},
- [this.ficon({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", system: true }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])])
+ [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)])])
);
}
@@ -758,8 +799,8 @@ export class CurrentUserUtils {
}
if (doc.myTools === undefined) {
- const toolsStack = new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc, doc.myColorPicker as Doc], {
- title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _forceActive: true,
+ const toolsStack = new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc], {
+ title: "My Tools", _showTitle: "title", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _forceActive: true,
system: true, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, boxShadow: "0 0",
})) as any as Doc;
@@ -771,69 +812,90 @@ export class CurrentUserUtils {
// setup dashboards library item
await doc.myDashboards;
if (doc.myDashboards === undefined) {
+ const newDashboard = ScriptField.MakeScript(`createNewDashboard(Doc.UserDoc())`);
+ const newDashboardButton: Doc = Docs.Create.FontIconDocument({ onClick: newDashboard, _forceActive: true, toolTip: "Create new dashboard", _stayInCollection: true, _hideContextMenu: true, title: "new dashboard", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true });
doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], {
title: "My Dashboards", _showTitle: "title", _height: 400, childHideLinkButton: true,
treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
- treeViewTruncateTitleWidth: 150, ignoreClick: true,
- _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true
+ treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newDashboardButton,
+ _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true,
+ 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 newDashboard = ScriptField.MakeScript(`createNewDashboard(Doc.UserDoc())`);
- const toggleTheme = ScriptField.MakeScript(`Doc.UserDoc().darkScheme = !Doc.UserDoc().darkScheme`);
- const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
- const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`);
+ // const toggleTheme = ScriptField.MakeScript(`Doc.UserDoc().darkScheme = !Doc.UserDoc().darkScheme`);
+ // const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
+ // const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`);
const shareDashboard = ScriptField.MakeScript(`shareDashboard(self)`);
const removeDashboard = ScriptField.MakeScript('removeDashboard(self)');
- (doc.myDashboards as any as Doc).childContextMenuScripts = new List<ScriptField>([newDashboard!, toggleTheme!, toggleComic!, snapshotDashboard!, shareDashboard!, removeDashboard!]);
- (doc.myDashboards as any as Doc).childContextMenuLabels = new List<string>(["Create New Dashboard", "Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard"]);
+ (doc.myDashboards as any as Doc).childContextMenuScripts = new List<ScriptField>([newDashboard!, shareDashboard!, removeDashboard!]);
+ (doc.myDashboards as any as Doc).childContextMenuLabels = new List<string>(["Create New Dashboard", "Share Dashboard", "Remove Dashboard"]);
+ (doc.myDashboards as any as Doc).childContextMenuIcons = new List<string>(["plus", "user-friends", "times"]);
+ // (doc.myDashboards as any as Doc).childContextMenuScripts = new List<ScriptField>([newDashboard!, toggleTheme!, toggleComic!, snapshotDashboard!, shareDashboard!, removeDashboard!]);
+ // (doc.myDashboards as any as Doc).childContextMenuLabels = new List<string>(["Create New Dashboard", "Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard"]);
}
return doc.myDashboards as any as Doc;
}
static async setupPresentations(doc: Doc) {
- await doc.myPresentations;
- if (doc.myPresentations === undefined) {
- doc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], {
+ await doc.myTrails;
+ if (doc.myTrails === undefined) {
+ const newTrail = ScriptField.MakeScript(`createNewPresentation()`);
+ const newTrailButton: Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "Create new trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true });
+ doc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], {
title: "My Trails", _showTitle: "title", _height: 100,
- treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
- treeViewTruncateTitleWidth: 150, ignoreClick: true,
- _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
+ treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias",
+ treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newTrailButton,
+ _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true,
+ explainer: "All of the trails that you have created will appear here."
}));
- const newPresentations = ScriptField.MakeScript(`createNewPresentation()`);
- (doc.myPresentations as any as Doc).contextMenuScripts = new List<ScriptField>([newPresentations!]);
- (doc.myPresentations as any as Doc).contextMenuLabels = new List<string>(["Create New Presentation"]);
- const presentations = doc.myPresentations as any as Doc;
+ (doc.myTrails as any as Doc).contextMenuScripts = new List<ScriptField>([newTrail!]);
+ (doc.myTrails as any as Doc).contextMenuLabels = new List<string>(["Create New Trail"]);
+ (doc.myTrails as any as Doc).childContextMenuIcons = new List<string>(["plus"]);
}
- return doc.myPresentations as any as Doc;
+ return doc.myTrails as any as Doc;
}
static async setupFilesystem(doc: Doc) {
await doc.myFilesystem;
if (doc.myFilesystem === undefined) {
doc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true });
- doc.myFileRoot = Docs.Create.TreeDocument([], { title: "file root", _stayInCollection: true, system: true, isFolder: true });
- doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileRoot as Doc, doc.myFileOrphans as Doc], {
- title: "My Documents", _showTitle: "title", _height: 100,
+ // doc.myFileRoot = Docs.Create.TreeDocument([], { title: "file root", _stayInCollection: true, system: true, isFolder: true });
+ const newFolder = ScriptField.MakeFunction(`makeTopLevelFolder()`, { scriptContext: "any" })!;
+ const newFolderButton: Doc = Docs.Create.FontIconDocument({
+ onClick: newFolder, _forceActive: true, toolTip: "Create new folder",
+ _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30,
+ buttonText: "New folder", icon: "folder-plus", system: true
+ });
+ doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileOrphans as Doc], {
+ title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100,
treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true,
- _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true
+ _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true,
+ explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
}));
+ (doc.myFilesystem as any as Doc).contextMenuScripts = new List<ScriptField>([newFolder]);
+ (doc.myFilesystem as any as Doc).contextMenuLabels = new List<string>(["Create new folder"]);
+ (doc.myFilesystem as any as Doc).childContextMenuIcons = new List<string>(["plus"]);
}
return doc.myFilesystem as any as Doc;
}
static setupRecentlyClosedDocs(doc: Doc) {
- // setup Recently Closed library item
if (doc.myRecentlyClosedDocs === undefined) {
+ const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`);
+ const clearDocsButton: Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true });
doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], {
- title: "Recently Closed", _showTitle: "title", treeViewShowClearButton: true, childHideLinkButton: true,
+ title: "My Recently Closed", _showTitle: "title", buttonMenu: true, buttonMenuDoc: clearDocsButton, childHideLinkButton: true,
treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
- _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
+ _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true,
+ explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list."
+
}));
- const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`);
(doc.myRecentlyClosedDocs as any as Doc).contextMenuScripts = new List<ScriptField>([clearAll!]);
- (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List<string>(["Clear All"]);
+ (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List<string>(["Empty recently closed"]);
+ (doc.myRecentlyClosedDocs as any as Doc).contextMenuIcons = new List<string>(["trash"]);
+
}
}
@@ -841,7 +903,7 @@ export class CurrentUserUtils {
// setup Filter item
if (doc.currentFilter === undefined) {
doc.currentFilter = Docs.Create.FilterDocument({
- title: "unnamed filter", _height: 150,
+ title: "Unnamed Filter", _height: 150,
treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "none",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
_lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, _autoHeight: true, _fitWidth: true
@@ -886,31 +948,229 @@ export class CurrentUserUtils {
CurrentUserUtils.setupUserDoc(doc);
}
- static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
- ...opts, _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", _forceActive: true,
+ static linearButtonList = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(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 }),
- backgroundColor: "black", _lockedPosition: true, linearViewIsExpanded: true, system: true
+ _lockedPosition: true, system: true, flexDirection: "row"
})) as any as Doc
- static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
- ...opts, _dropAction: "alias", _removeDropProperties: new List<string>(["_dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true
+ static createToolButton = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
+ ...opts, btnType: ButtonType.ToolButton, _forceActive: true, _dropAction: "alias", _removeDropProperties: new List<string>(["_dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true
})) as any as Doc
/// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window
static setupDockedButtons(doc: Doc) {
if (doc["dockedBtn-undo"] === undefined) {
- doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), dontUndo: true, _stayInCollection: true, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "click to undo", title: "undo", icon: "undo-alt", system: true });
+ doc["dockedBtn-undo"] = CurrentUserUtils.createToolButton({ onClick: ScriptField.MakeScript("undo()"), _width: 30, _height: 30, dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to undo", title: "undo", icon: "undo-alt", system: true });
}
if (doc["dockedBtn-redo"] === undefined) {
- doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), dontUndo: true, _stayInCollection: true, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "click to redo", title: "redo", icon: "redo-alt", system: true });
+ doc["dockedBtn-redo"] = CurrentUserUtils.createToolButton({ onClick: ScriptField.MakeScript("redo()"), _width: 30, _height: 30, dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to redo", title: "redo", icon: "redo-alt", system: true });
}
if (doc.dockedBtns === undefined) {
- doc.dockedBtns = CurrentUserUtils.blist({ title: "docked buttons", ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]);
+ doc.dockedBtns = CurrentUserUtils.linearButtonList({ title: "docked buttons", _height: 40, flexGap: 0, linearViewFloating: true, linearViewIsExpanded: true, linearViewExpandable: true, ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]);
}
(doc["dockedBtn-undo"] as Doc).dontUndo = true;
(doc["dockedBtn-redo"] as Doc).dontUndo = true;
}
+ static textTools(doc: Doc) {
+ const tools: Button[] =
+ [
+ {
+ title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
+ list: ["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia",
+ "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"],
+ script: 'setFont'
+ },
+ { title: "Font size", toolTip: "Font size", width: 75, btnType: ButtonType.NumberButton, numBtnMax: 200, numBtnMin: 0, numBtnType: NumButtonType.DropdownOptions, ignoreClick: true, script: 'setFontSize' },
+ { title: "Font color", toolTip: "Font color", btnType: ButtonType.ColorButton, icon: "font", ignoreClick: true, script: 'setFontColor' },
+ { title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", click: 'toggleBold()', checkResult: 'toggleBold(true)' },
+ { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", click: 'toggleItalic()', checkResult: 'toggleItalic(true)' },
+ { title: "Underline", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", click: 'toggleUnderline()', checkResult: 'toggleUnderline(true)' },
+ { title: "Bullet List", toolTip: "Bullet", btnType: ButtonType.ToggleButton, icon: "list", click: 'setBulletList("bullet")', checkResult: 'setBulletList("bullet", true)' },
+ { title: "Number List", toolTip: "Number", btnType: ButtonType.ToggleButton, icon: "list-ol", click: 'setBulletList("decimal")', checkResult: 'setBulletList("decimal", true)' },
+
+ // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", click: 'toggleStrikethrough()'},
+ // { title: "Superscript", tooltip: "Superscript", btnType: ButtonType.ToggleButton, icon: "superscript", click: 'toggleSuperscript()'},
+ // { title: "Subscript", tooltip: "Subscript", btnType: ButtonType.ToggleButton, icon: "subscript", click: 'toggleSubscript()'},
+ { title: "Left align", toolTip: "Left align", btnType: ButtonType.ToggleButton, icon: "align-left", click: 'setAlignment("left")', checkResult: 'setAlignment("left", true)' },
+ { title: "Center align", toolTip: "Center align", btnType: ButtonType.ToggleButton, icon: "align-center", click: 'setAlignment("center")', checkResult: 'setAlignment("center", true)' },
+ { title: "Right align", toolTip: "Right align", btnType: ButtonType.ToggleButton, icon: "align-right", click: 'setAlignment("right")', checkResult: 'setAlignment("right", true)' },
+ ];
+ return tools;
+ }
+
+ static inkTools(doc: Doc) {
+ const tools: Button[] = [
+ { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen", click: 'setActiveInkTool("pen")', checkResult: 'setActiveInkTool("pen" , true)' },
+ // { title: "Highlighter", toolTip: "Highlighter (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", click: 'setActiveInkTool("highlighter")', checkResult: 'setActiveInkTool("highlighter", true)' },
+ { title: "Circle", toolTip: "Circle (Ctrl+Shift+C)", btnType: ButtonType.ToggleButton, icon: "circle", click: 'setActiveInkTool("circle")', checkResult: 'setActiveInkTool("circle" , true)' },
+ // { title: "Square", toolTip: "Square (Ctrl+Shift+S)", btnType: ButtonType.ToggleButton, icon: "square", click: 'setActiveInkTool("square")', checkResult: 'setActiveInkTool("square" , true)' },
+ { title: "Line", toolTip: "Line (Ctrl+Shift+L)", btnType: ButtonType.ToggleButton, icon: "minus", click: 'setActiveInkTool("line")', checkResult: 'setActiveInkTool("line" , true)' },
+ { title: "Fill color", toolTip: "Fill color", btnType: ButtonType.ColorButton, ignoreClick: true, icon: "fill-drip", script: "setFillColor" },
+ { title: "Stroke width", toolTip: "Stroke width", btnType: ButtonType.NumberButton, numBtnType: NumButtonType.Slider, numBtnMin: 1, ignoreClick: true, script: 'setStrokeWidth' },
+ { title: "Stroke color", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", ignoreClick: true, script: 'setStrokeColor' },
+ ];
+ return tools;
+ }
+
+ static schemaTools(doc: Doc) {
+ const tools: Button[] =
+ [
+ {
+ title: "Show preview",
+ toolTip: "Show preview of selected document",
+ btnType: ButtonType.ToggleButton,
+ switchToggle: true,
+ width: 100,
+ buttonText: "Show Preview",
+ icon: "eye",
+ click: 'toggleSchemaPreview()',
+ checkResult: 'toggleSchemaPreview(true)'
+ },
+ ];
+ return tools;
+ }
+
+ static webTools(doc: Doc) {
+ const tools: Button[] =
+ [
+ { title: "Back", toolTip: "Go back", btnType: ButtonType.ClickButton, icon: "arrow-left", click: 'webBack()' },
+ { title: "Forward", toolTip: "Go forward", btnType: ButtonType.ClickButton, icon: "arrow-right", click: 'webForward()' },
+ //{ title: "Reload", toolTip: "Reload webpage", btnType: ButtonType.ClickButton, icon: "redo-alt", click: 'webReload()' },
+ { title: "URL", toolTip: "URL", width: 250, btnType: ButtonType.EditableText, icon: "lock", ignoreClick: true, script: 'webSetURL' },
+ ];
+
+ return tools;
+ }
+
+ static async contextMenuTools(doc: Doc) {
+ return [
+ {
+ title: "Perspective", toolTip: "View", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
+ list: [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Tree,
+ CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Multicolumn,
+ CollectionViewType.Multirow, CollectionViewType.Time, CollectionViewType.Carousel,
+ CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map,
+ CollectionViewType.Grid],
+ script: 'setView',
+ }, // Always show
+ {
+ title: "Background Color", toolTip: "Background Color", btnType: ButtonType.ColorButton, ignoreClick: true, icon: "fill-drip",
+ script: "setBackgroundColor", hidden: 'selectedDocumentType()'
+ }, // Only when a document is selected
+ {
+ title: "Header Color", toolTip: "Header Color", btnType: ButtonType.ColorButton, ignoreClick: true, icon: "heading",
+ script: "setHeaderColor", hidden: 'selectedDocumentType()',
+ }, // Only when a document is selected
+ { title: "Overlay", toolTip: "Overlay", btnType: ButtonType.ToggleButton, icon: "layer-group", click: 'toggleOverlay()', checkResult: 'toggleOverlay(true)', hidden: 'selectedDocumentType(undefined, "freeform", true)' }, // Only when floating document is selected in freeform
+ // { title: "Alias", btnType: ButtonType.ClickButton, icon: "copy", hidden: 'selectedDocumentType()' }, // Only when a document is selected
+ { title: "Text", type: "textTools", subMenu: true, expanded: 'selectedDocumentType("rtf")' }, // Always available
+ { title: "Ink", type: "inkTools", subMenu: true, expanded: 'selectedDocumentType("ink")' }, // Always available
+ { title: "Web", type: "webTools", subMenu: true, hidden: 'selectedDocumentType("web")' }, // Only when Web is selected
+ { title: "Schema", type: "schemaTools", subMenu: true, hidden: 'selectedDocumentType(undefined, "schema")' } // Only when Schema is selected
+ ];
+ }
+
+ // Sets up the default context menu buttons
+ static async setupContextMenuButtons(doc: Doc) {
+ if (doc.contextMenuBtns === undefined) {
+ const docList: Doc[] = [];
+
+ (await CurrentUserUtils.contextMenuTools(doc)).map(({ title, width, list, toolTip, ignoreClick, icon, type, btnType, click, script, subMenu, hidden, expanded, checkResult }) => {
+ const menuDocList: Doc[] = [];
+ if (subMenu) {
+ // default is textTools
+ let tools: Button[];
+ switch (type) {
+ case "inkTools":
+ tools = CurrentUserUtils.inkTools(doc);
+ break;
+ case "schemaTools":
+ tools = CurrentUserUtils.schemaTools(doc);
+ break;
+ case "webTools":
+ tools = CurrentUserUtils.webTools(doc);
+ break;
+ case "textTools":
+ tools = CurrentUserUtils.textTools(doc);
+ break;
+ default:
+ tools = CurrentUserUtils.textTools(doc);
+ break;
+ }
+ tools.map(({ title, toolTip, icon, btnType, numBtnType, numBtnMax, numBtnMin, click, script, width, list, ignoreClick, switchToggle, checkResult }) => {
+ menuDocList.push(Docs.Create.FontIconDocument({
+ _nativeWidth: width ? width : 25,
+ _nativeHeight: 25,
+ _width: width ? width : 25,
+ _height: 25,
+ icon,
+ toolTip,
+ numBtnType,
+ numBtnMin,
+ numBtnMax,
+ script,
+ btnType: btnType,
+ btnList: new List<string>(list),
+ ignoreClick: ignoreClick,
+ _stayInCollection: true,
+ _hideContextMenu: true,
+ _lockedPosition: true,
+ system: true,
+ dontUndo: true,
+ title,
+ switchToggle,
+ color: Colors.WHITE,
+ backgroundColor: checkResult ? ComputedField.MakeFunction(checkResult) as any : "transparent",
+ _dropAction: "alias",
+ _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
+ onClick: click ? ScriptField.MakeScript(click, { doc: Doc.name }) : undefined
+ }));
+ });
+ docList.push(CurrentUserUtils.linearButtonList({
+ linearViewSubMenu: true,
+ flexGap: 0,
+ ignoreClick: true,
+ linearViewExpandable: true,
+ icon: title,
+ _height: 30,
+ backgroundColor: checkResult ? ComputedField.MakeFunction(checkResult) as any : "transparent",
+ linearViewIsExpanded: expanded ? !(ComputedField.MakeFunction(expanded) as any) : undefined,
+ hidden: hidden ? ComputedField.MakeFunction(hidden) as any : undefined,
+ }, menuDocList));
+ } else {
+ docList.push(Docs.Create.FontIconDocument({
+ _nativeWidth: width ? width : 25,
+ _nativeHeight: 25,
+ _width: width ? width : 25,
+ _height: 25,
+ icon,
+ toolTip,
+ script,
+ btnType,
+ btnList: new List<string>(list),
+ ignoreClick,
+ _stayInCollection: true,
+ _hideContextMenu: true,
+ _lockedPosition: true,
+ system: true,
+ dontUndo: true,
+ title,
+ color: Colors.WHITE,
+ backgroundColor: "transparent",
+ _dropAction: "alias",
+ hidden: hidden ? ComputedField.MakeFunction(hidden) as any : undefined,
+ _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
+ onClick: click ? ScriptField.MakeScript(click, { scriptContext: "any" }) : undefined
+ }));
+ }
+ });
+
+ doc.contextMenuBtns = CurrentUserUtils.linearButtonList({ title: "menu buttons", flexGap: 0, linearViewIsExpanded: true, ignoreClick: true, linearViewExpandable: false, _height: 35 }, docList);
+ }
+ }
+
// sets up the default set of documents to be shown in the Overlay layer
static setupOverlays(doc: Doc) {
if (doc.myOverlayDocs === undefined) {
@@ -940,13 +1200,15 @@ export class CurrentUserUtils {
}
doc.myLinkDatabase = new PrefetchProxy(linkDocs);
}
+ // TODO:glr NOTE: treeViewHideTitle & _showTitle may be confusing, treeViewHideTitle is for the editable title (just for tree view), _showTitle is to show the Document title for any document
if (doc.mySharedDocs === undefined) {
let sharedDocs = Docs.newAccount ? undefined : await DocServer.GetRefField(sharingDocumentId + "outer");
if (!sharedDocs) {
sharedDocs = Docs.Create.TreeDocument([], {
title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 50, _gridGap: 15,
- _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment,
+ _showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment,
_chromeHidden: true, boxShadow: "0 0",
+ 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'"
}, sharingDocumentId + "outer", sharingDocumentId);
(sharedDocs as Doc)["acl-Public"] = (sharedDocs as Doc)[DataSym]["acl-Public"] = SharingPermissions.Augment;
}
@@ -957,6 +1219,8 @@ export class CurrentUserUtils {
sharedDocs.childContextMenuFilters = new List<ScriptField>([dashboardFilter!,]);
sharedDocs.childContextMenuScripts = new List<ScriptField>([addToDashboards!,]);
sharedDocs.childContextMenuLabels = new List<string>(["Add to Dashboards",]);
+ sharedDocs.childContextMenuIcons = new List<string>(["user-plus",]);
+
}
doc.mySharedDocs = new PrefetchProxy(sharedDocs);
}
@@ -965,16 +1229,13 @@ export class CurrentUserUtils {
// Import sidebar is where shared documents are contained
static setupImportSidebar(doc: Doc) {
if (doc.myImportDocs === undefined) {
+ const newImportButton: Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _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 });
doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], {
- title: "My ImportDocuments", _forceActive: true, ignoreClick: true, _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0,
- childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true, _chromeHidden: true,
+ title: "My Imports", _forceActive: true, buttonMenu: true, buttonMenuDoc: newImportButton, 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,
+ explainer: "This is where documents that are Imported into Dash will go."
}));
}
- if (doc.myImportPanel === undefined) {
- const uploads = Cast(doc.myImportDocs, Doc, null);
- const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _stayInCollection: true, _hideContextMenu: true, title: "Import", icon: "upload", system: true });
- doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, _showTitle: "title", ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true, boxShadow: "0 0" }));
- }
}
// Search sidebar is where searches within the document are performed
@@ -982,7 +1243,7 @@ export class CurrentUserUtils {
if (doc.mySearchPanel === undefined) {
doc.mySearchPanel = new PrefetchProxy(Docs.Create.SearchDocument({
backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true,
- childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "Search Sidebar", system: true
+ childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "Search Panel", system: true
})) as any as Doc;
}
}
@@ -1052,8 +1313,9 @@ export class CurrentUserUtils {
doc._raiseWhenDragged = true;
doc._showLabel = false;
doc._showMenuLabel = true;
+ doc.textAlign = StrCast(doc.textAlign, "left");
doc.activeInkColor = StrCast(doc.activeInkColor, "rgb(0, 0, 0)");
- doc.activeInkWidth = StrCast(doc.activeInkWidth, "1");
+ doc.activeInkWidth = Number(StrCast(doc.activeInkWidth, "1"));
doc.activeInkBezier = StrCast(doc.activeInkBezier, "0");
doc.activeFillColor = StrCast(doc.activeFillColor, "");
doc.activeArrowStart = StrCast(doc.activeArrowStart, "");
@@ -1074,10 +1336,11 @@ export class CurrentUserUtils {
doc.filterDocCount = 0;
this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon
this.setupDocTemplates(doc); // sets up the template menu of templates
- this.setupImportSidebar(doc);
+ this.setupImportSidebar(doc); // sets up the import sidebar
this.setupSearchSidebar(doc); // sets up the search sidebar
this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile
this.setupOverlays(doc); // documents in overlay layer
+ this.setupContextMenuButtons(doc); // set up context menu buttons
this.setupDockedButtons(doc); // the bottom bar of font icons
await this.setupSidebarButtons(doc); // the pop-out left sidebar of tools/panels
await this.setupMenuPanel(doc, sharingDocumentId, linkDatabaseId);
@@ -1224,7 +1487,6 @@ export class CurrentUserUtils {
}
public static createNewDashboard = async (userDoc: Doc, id?: string) => {
- const myPresentations = await userDoc.myPresentations as Doc;
const presentation = Doc.MakeCopy(userDoc.emptyPresentation as Doc, true);
const dashboards = await Cast(userDoc.myDashboards, Doc) as Doc;
const dashboardCount = DocListCast(dashboards.data).length + 1;
@@ -1236,6 +1498,7 @@ export class CurrentUserUtils {
_width: 1500,
_height: 1000,
_fitWidth: true,
+ _backgroundGridShow: true,
title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`,
};
const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
@@ -1260,16 +1523,15 @@ export class CurrentUserUtils {
DocListCast(dashboardDoc.data).forEach(doc => doc.dashboard = dashboardDoc);
DocListCast(dashboardDoc.data)[1].data = ComputedField.MakeFunction(`dynamicOffScreenDocs(self.dashboard)`) as any;
- Doc.AddDocToList(myPresentations, "data", presentation);
userDoc.activePresentation = presentation;
Doc.AddDocToList(dashboards, "data", dashboardDoc);
CurrentUserUtils.openDashboard(userDoc, dashboardDoc);
}
- public static GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, maxHeight?: number) {
+ 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,
+ _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, docMaxAutoHeight: maxHeight, backgroundColor: backgroundColor,
_width: width || 200, _height: height || 100, x: x, y: y, _fitWidth: true, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize),
_fontFamily: StrCast(Doc.UserDoc().fontFamily), title
});
@@ -1301,6 +1563,8 @@ Scripting.addGlobal(function openDragFactory(dragFactory: Doc) {
view && SelectionManager.SelectView(view, false);
}
});
+Scripting.addGlobal(function MySharedDocs() { return Doc.SharingDoc(); },
+ "document containing all shared Docs");
Scripting.addGlobal(function IsNoviceMode() { return Doc.UserDoc().noviceMode; },
"is Dash in novice mode");
Scripting.addGlobal(function snapshotDashboard() { CurrentUserUtils.snapshotDashboard(Doc.UserDoc()); },
@@ -1309,6 +1573,8 @@ Scripting.addGlobal(function createNewDashboard() { return CurrentUserUtils.crea
"creates a new dashboard when called");
Scripting.addGlobal(function createNewPresentation() { return MainView.Instance.createNewPresentation(); },
"creates a new presentation when called");
+Scripting.addGlobal(function createNewFolder() { return MainView.Instance.createNewFolder(); },
+ "creates a new folder in myFiles when called");
Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); },
"returns all the links to the document or its annotations", "(doc: any)");
Scripting.addGlobal(function importDocument() { return CurrentUserUtils.importDocument(); },
@@ -1361,3 +1627,19 @@ Scripting.addGlobal(function dynamicOffScreenDocs(dashboard: Doc) {
}
return [];
});
+Scripting.addGlobal(function selectedDocumentType(docType?: DocumentType, colType?: CollectionViewType, checkParent?: boolean) {
+ let selected = SelectionManager.Docs().length ? SelectionManager.Docs()[0] : undefined;
+ if (selected && checkParent) {
+ const parentDoc: Doc = Cast(selected.context, Doc, null);
+ selected = parentDoc;
+ }
+ if (selected && docType && selected.type === docType) return false;
+ else if (selected && colType && selected.viewType === colType) return false;
+ else if (selected && !colType && !docType) return false;
+ else return true;
+});
+Scripting.addGlobal(function makeTopLevelFolder() {
+ const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true });
+ TreeView._editTitleOnLoad = { id: folder[Id], parent: undefined };
+ return Doc.AddDocToList(Doc.UserDoc().myFilesystem as Doc, "data", folder);
+}); \ No newline at end of file
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index cb0ee411c..dfec9823b 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,19 +1,21 @@
import { action, observable, runInAction } from 'mobx';
import { Doc, DocListCast, DocListCastAsync, Opt } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
-import { Cast, NumCast, StrCast } from '../../fields/Types';
+import { Cast } from '../../fields/Types';
import { returnFalse } from '../../Utils';
import { DocumentType } from '../documents/DocumentTypes';
import { CollectionDockingView } from '../views/collections/CollectionDockingView';
import { CollectionView } from '../views/collections/CollectionView';
import { LightboxView } from '../views/LightboxView';
import { DocumentView, ViewAdjustment } from '../views/nodes/DocumentView';
+import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox';
import { Scripting } from './Scripting';
export class DocumentManager {
//global holds all of the nodes (regardless of which collection they're in)
@observable public DocumentViews: DocumentView[] = [];
+ @observable public LinkAnchorBoxViews: DocumentView[] = [];
@observable public RecordingEvent = 0;
@observable public LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = [];
@@ -25,24 +27,41 @@ export class DocumentManager {
@action
public AddView = (view: DocumentView) => {
- DocListCast(view.rootDoc.links).forEach(link => {
- const whichOtherAnchor = view.props.LayoutTemplateString?.includes("anchor2") ? "anchor1" : "anchor2";
- const otherDoc = link && (link[whichOtherAnchor] as Doc);
- const otherDocAnno = DocumentType.MARKER === otherDoc?.type ? otherDoc.annotationOn as Doc : undefined;
- otherDoc && DocumentManager.Instance.DocumentViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, otherDoc) || Doc.AreProtosEqual(dv.rootDoc, otherDocAnno)).
- forEach(otherView => {
- if (otherView.rootDoc.type !== DocumentType.LINK || otherView.props.LayoutTemplateString !== view.props.LayoutTemplateString) {
- this.LinkedDocumentViews.push({ a: whichOtherAnchor === "anchor1" ? otherView : view, b: whichOtherAnchor === "anchor1" ? view : otherView, l: link });
- }
- });
- });
- this.DocumentViews.push(view);
+ //console.log("MOUNT " + view.props.Document.title + "/" + view.props.LayoutTemplateString);
+ if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
+ const viewAnchorIndex = view.props.LayoutTemplateString.includes("anchor2") ? "anchor2" : "anchor1";
+ DocListCast(view.rootDoc.links).forEach(link => {
+ this.LinkAnchorBoxViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)).
+ forEach(otherView => this.LinkedDocumentViews.push(
+ {
+ a: viewAnchorIndex === "anchor2" ? otherView : view,
+ b: viewAnchorIndex === "anchor2" ? view : otherView,
+ l: link
+ })
+ );
+ });
+ this.LinkAnchorBoxViews.push(view);
+ // this.LinkedDocumentViews.forEach(view => console.log(" LV = " + view.a.props.Document.title + "/" + view.a.props.LayoutTemplateString + " --> " +
+ // view.b.props.Document.title + "/" + view.b.props.LayoutTemplateString));
+ } else {
+ this.DocumentViews.push(view);
+ }
}
public RemoveView = action((view: DocumentView) => {
- const index = this.DocumentViews.indexOf(view);
- index !== -1 && this.DocumentViews.splice(index, 1);
+ this.LinkedDocumentViews.slice().forEach(action(pair => {
+ if (pair.a === view || pair.b === view) {
+ const li = this.LinkedDocumentViews.indexOf(pair);
+ li !== -1 && this.LinkedDocumentViews.splice(li, 1);
+ }
+ }));
- this.LinkedDocumentViews.slice().forEach(action((pair, i) => pair.a === view || pair.b === view ? this.LinkedDocumentViews.splice(i, 1) : null));
+ if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
+ const index = this.LinkAnchorBoxViews.indexOf(view);
+ this.LinkAnchorBoxViews.splice(index, 1);
+ } else {
+ const index = this.DocumentViews.indexOf(view);
+ index !== -1 && this.DocumentViews.splice(index, 1);
+ }
});
//gets all views
@@ -139,7 +158,8 @@ export class DocumentManager {
closeContextIfNotFound: boolean = false, // after opening a context where the document should be, this determines whether the context should be closed if the Doc isn't actually there
originatingDoc: Opt<Doc> = undefined, // doc that initiated the display of the target odoc
finished?: () => void,
- originalTarget?: Doc
+ originalTarget?: Doc,
+ noSelect?: boolean
): Promise<void> => {
originalTarget = originalTarget ?? targetDoc;
const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView;
@@ -153,7 +173,7 @@ export class DocumentManager {
}
} else {
targetDoc.hidden && (targetDoc.hidden = undefined);
- docView?.select(false);
+ !noSelect && docView?.select(false);
}
finished?.();
return false;
@@ -170,7 +190,7 @@ export class DocumentManager {
annoContainerView.focus(targetDoc); // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below
}
if (focusView) {
- Doc.linkFollowHighlight(focusView.rootDoc);
+ !noSelect && Doc.linkFollowHighlight(focusView.rootDoc); //TODO:glr make this a setting in PresBox
focusView.focus(targetDoc, {
originalTarget, willZoom, afterFocus: (didFocus: boolean) =>
new Promise<ViewAdjustment>(res => {
@@ -203,7 +223,7 @@ export class DocumentManager {
retryDocView.props.focus(targetDoc, {
willZoom, afterFocus: (didFocus: boolean) =>
new Promise<ViewAdjustment>(res => {
- focusAndFinish(didFocus);
+ !noSelect && focusAndFinish(didFocus);
res();
})
}); // focus on the target in the context
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 5e16de617..421e4c6bb 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -145,7 +145,7 @@ export namespace DragManager {
removeDropProperties?: string[];
moveDocument?: MoveFunction;
removeDocument?: RemoveFunction;
- isSelectionMove?: boolean; // indicates that an explicitly selected Document is being dragged. this will suppress onDragStart scripts
+ isDocDecorationMove?: boolean; // Flags that Document decorations are used to drag document which allows suppression of onDragStart scripts
}
export class LinkDragData {
constructor(dragView: DocumentView, linkSourceGetAnchor: () => Doc,) {
@@ -225,7 +225,7 @@ export namespace DragManager {
if (docDragData && !docDragData.droppedDocuments.length) {
docDragData.dropAction = dragData.userDropAction || dragData.dropAction;
docDragData.droppedDocuments =
- await Promise.all(dragData.draggedDocuments.map(async d => !dragData.isSelectionMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) :
+ await Promise.all(dragData.draggedDocuments.map(async d => !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) :
docDragData.dropAction === "alias" ? Doc.MakeAlias(d) :
docDragData.dropAction === "proto" ? Doc.GetProto(d) :
docDragData.dropAction === "copy" ? (await Doc.MakeClone(d)).clone : d));
@@ -425,10 +425,10 @@ export namespace DragManager {
AbortDrag = () => {
options?.dragComplete?.(new DragCompleteEvent(true, dragData));
- endDrag();
+ cleanupDrag();
};
- const endDrag = action(() => {
+ const cleanupDrag = action(() => {
hideDragShowOriginalElements(false);
document.removeEventListener("pointermove", moveHandler, true);
document.removeEventListener("pointerup", upHandler);
@@ -518,15 +518,14 @@ export namespace DragManager {
`translate(${(xs[i] += moveVec.x) + (options?.offsetX || 0)}px, ${(ys[i] += moveVec.y) + (options?.offsetY || 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`)
);
};
- const upHandler = async (e: PointerEvent) => {
- dispatchDrag(document.elementFromPoint(e.x, e.y) || document.body, e, new DragCompleteEvent(false, dragData), snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom), finishDrag, options);
- endDrag();
+ const upHandler = (e: PointerEvent) => {
+ dispatchDrag(document.elementFromPoint(e.x, e.y) || document.body, e, new DragCompleteEvent(false, dragData), snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom), finishDrag, options, cleanupDrag);
};
document.addEventListener("pointermove", moveHandler, true);
document.addEventListener("pointerup", upHandler);
}
- async function dispatchDrag(target: Element, e: PointerEvent, complete: DragCompleteEvent, pos: { x: number, y: number }, finishDrag?: (e: DragCompleteEvent) => void, options?: DragOptions) {
+ async function dispatchDrag(target: Element, e: PointerEvent, complete: DragCompleteEvent, pos: { x: number, y: number }, finishDrag?: (e: DragCompleteEvent) => void, options?: DragOptions, endDrag?: () => void) {
const dropArgs = {
bubbles: true,
detail: {
@@ -543,5 +542,6 @@ export namespace DragManager {
await finishDrag?.(complete);
target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", dropArgs));
options?.dragComplete?.(complete);
+ endDrag?.();
}
} \ No newline at end of file
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index 635673025..e910a9118 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -29,7 +29,7 @@ export namespace Hypothesis {
* Search for a WebDocument whose url field matches the given uri, return undefined if not found
*/
export const findWebDoc = async (uri: string) => {
- const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document;
+ const currentDoc = SelectionManager.Docs().lastElement();
if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise
const results: Doc[] = [];
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index e009fb3a9..4a8011e3c 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -3,6 +3,8 @@ import * as beziercurve from 'bezier-curve';
import * as fitCurve from 'fit-curve';
import "./InteractionUtils.scss";
import { Utils } from "../../Utils";
+import { CurrentUserUtils } from "./CurrentUserUtils";
+import { InkTool } from "../../fields/InkField";
export namespace InteractionUtils {
export const MOUSETYPE = "mouse";
@@ -139,7 +141,7 @@ export namespace InteractionUtils {
export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number,
color: string, width: number, strokeWidth: number, bezier: string, fill: string, arrowStart: string, arrowEnd: string,
- dash: string | undefined, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean, nodefs: boolean) {
+ dash: string | undefined, scalex: number, scaley: number, shape: string, pevents: string, opacity: number, nodefs: boolean) {
let pts: { X: number; Y: number; }[] = [];
if (shape) { //if any of the shape are true
pts = makePolygon(shape, points);
@@ -209,14 +211,14 @@ export namespace InteractionUtils {
points={strpts}
style={{
// filter: drawHalo ? "url(#inkSelectionHalo)" : undefined,
- fill: fill ? fill : "none",
+ fill: fill && fill !== "transparent" ? fill : "none",
opacity: 1.0,
// opacity: strokeWidth !== width ? 0.5 : undefined,
pointerEvents: pevents as any,
stroke: color ?? "rgb(0, 0, 0)",
strokeWidth: strokeWidth,
- strokeLinejoin: "round",
- strokeLinecap: "round",
+ strokeLinejoin: color === "rgba(245, 230, 95, 0.75)" ? "miter" : "round",
+ strokeLinecap: color === "rgba(245, 230, 95, 0.75)" ? "square" : "round",
strokeDasharray: dashArray
}}
markerStart={`url(#${arrowStart + "Start" + defGuid})`}
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 3579083e4..64da68f59 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -1,13 +1,12 @@
-import { observable, observe, action, reaction, computed } from "mobx";
+import { action, observable, observe } from "mobx";
import { computedFn } from "mobx-utils";
import { DirectLinksSym, Doc, DocListCast, Field, Opt } from "../../fields/Doc";
import { List } from "../../fields/List";
import { ProxyField } from "../../fields/Proxy";
-import { BoolCast, Cast, PromiseValue, StrCast } from "../../fields/Types";
+import { BoolCast, Cast, StrCast } from "../../fields/Types";
import { LightboxView } from "../views/LightboxView";
import { DocumentViewSharedProps, ViewAdjustment } from "../views/nodes/DocumentView";
import { DocumentManager } from "./DocumentManager";
-import { SharingManager } from "./SharingManager";
import { UndoManager } from "./UndoManager";
type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void;
@@ -33,6 +32,7 @@ export class LinkManager {
static links: Doc[] = [];
constructor() {
LinkManager._instance = this;
+ this.createLinkrelationshipLists();
setTimeout(() => {
LinkManager.userLinkDBs = [];
const addLinkToDoc = (link: Doc) => {
@@ -97,6 +97,17 @@ export class LinkManager {
});
}
+
+ public createLinkrelationshipLists = () => {
+ //create new lists for link relations and their associated colors if the lists don't already exist
+ if (!Doc.UserDoc().linkRelationshipList && !Doc.UserDoc().linkColorList) {
+ const linkRelationshipList = new List<string>();
+ const linkColorList = new List<string>();
+ Doc.UserDoc().linkRelationshipList = linkRelationshipList;
+ Doc.UserDoc().linkColorList = linkColorList;
+ }
+ }
+
public addLink(linkDoc: Doc, checkExists = false) {
if (!checkExists || !DocListCast(Doc.LinkDBDoc().data).includes(linkDoc)) {
Doc.AddDocToList(Doc.LinkDBDoc(), "data", linkDoc);
@@ -107,14 +118,29 @@ export class LinkManager {
public getAllRelatedLinks(anchor: Doc) { return this.relatedLinker(anchor); } // finds all links that contain the given anchor
public getAllDirectLinks(anchor: Doc): Doc[] {
- return Array.from(Doc.GetProto(anchor)[DirectLinksSym]);
+ // FIXME:glr Why is Doc undefined?
+ if (Doc.GetProto(anchor)[DirectLinksSym]) {
+ return Array.from(Doc.GetProto(anchor)[DirectLinksSym]);
+ } else {
+ return [];
+ }
} // finds all links that contain the given anchor
relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc): Doc[] {
const lfield = Doc.LayoutFieldKey(anchor);
- const related = DocListCast(anchor[lfield + "-annotations"]).concat(DocListCast(anchor[lfield + "-annotations-timeline"])).reduce((list, anno) =>
+ if (!anchor || anchor instanceof Promise || Doc.GetProto(anchor) instanceof Promise) {
+ console.log("WAITING FOR DOC/PROTO IN LINKMANAGER");
+ return [];
+ }
+ const dirLinks = Doc.GetProto(anchor)[DirectLinksSym];
+ const annos = DocListCast(anchor[lfield + "-annotations"]);
+ const timelineAnnos = DocListCast(anchor[lfield + "-annotations-timeline"]);
+ if (!annos || !timelineAnnos) {
+ debugger;
+ }
+ const related = [...annos, ...timelineAnnos].reduce((list, anno) =>
[...list, ...LinkManager.Instance.relatedLinker(anno)],
- Array.from(Doc.GetProto(anchor)[DirectLinksSym]).slice());
+ Array.from(dirLinks).slice());
return related;
}, true);
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index f981f84cd..40b94024e 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -12,7 +12,7 @@ export { ts };
import * as typescriptlib from '!!raw-loader!./type_decls.d';
import { Doc, Field } from '../../fields/Doc';
-export interface ScriptSucccess {
+export interface ScriptSuccess {
success: true;
result: any;
}
@@ -23,7 +23,7 @@ export interface ScriptError {
result: any;
}
-export type ScriptResult = ScriptSucccess | ScriptError;
+export type ScriptResult = ScriptSuccess | ScriptError;
export type ScriptParam = { [name: string]: string };
@@ -171,10 +171,12 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an
if (!options.editable) {
batch = Doc.MakeReadOnly();
}
+
const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray);
if (batch) {
batch.end();
}
+
return { success: true, result };
} catch (error) {
@@ -314,9 +316,9 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
paramList.push(`${key}: ${typeof val === "object" ? Object.getPrototypeOf(val).constructor.name : typeof val}`);
}
const paramString = paramList.join(", ");
- const funcScript = `(function(${paramString})${requiredType ? `: ${requiredType}` : ''} {
- ${addReturn ? `return ${script};` : script}
- })`;
+ const body = addReturn ? `return ${script};` : `return ${script};`;
+ const reqTypes = requiredType ? `: ${requiredType}` : '';
+ const funcScript = `(function(${paramString})${reqTypes} { ${body} })`;
host.writeFile("file.ts", funcScript);
if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index dbcc49f3d..bac13373c 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,17 +1,17 @@
import { action, observable, ObservableMap } from "mobx";
import { computedFn } from "mobx-utils";
import { Doc, Opt } from "../../fields/Doc";
+import { DocumentType } from "../documents/DocumentTypes";
import { CollectionSchemaView } from "../views/collections/collectionSchema/CollectionSchemaView";
import { CollectionViewType } from "../views/collections/CollectionView";
import { DocumentView } from "../views/nodes/DocumentView";
-import { DocumentType } from "../documents/DocumentTypes";
export namespace SelectionManager {
class Manager {
@observable IsDragging: boolean = false;
- SelectedViews: ObservableMap<DocumentView, boolean> = new ObservableMap();
+ SelectedViews: ObservableMap<DocumentView, Doc> = new ObservableMap();
@observable SelectedSchemaDocument: Doc | undefined;
@observable SelectedSchemaCollection: CollectionSchemaView | undefined;
@@ -28,19 +28,18 @@ export namespace SelectionManager {
this.DeselectAll();
}
- manager.SelectedViews.set(docView, true);
+ manager.SelectedViews.set(docView, docView.rootDoc);
docView.props.whenChildContentsActiveChanged(true);
} else if (!ctrlPressed && Array.from(manager.SelectedViews.entries()).length > 1) {
Array.from(manager.SelectedViews.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false));
manager.SelectedSchemaDocument = undefined;
manager.SelectedSchemaCollection = undefined;
manager.SelectedViews.clear();
- manager.SelectedViews.set(docView, true);
+ manager.SelectedViews.set(docView, docView.rootDoc);
}
}
@action
DeselectView(docView: DocumentView): void {
-
if (manager.SelectedViews.get(docView)) {
manager.SelectedViews.delete(docView);
docView.props.whenChildContentsActiveChanged(false);
@@ -92,7 +91,7 @@ export namespace SelectionManager {
}
export function Views(): Array<DocumentView> {
- return Array.from(manager.SelectedViews.keys()).filter(dv => dv.props.Document._viewType !== CollectionViewType.Docking);
+ return Array.from(manager.SelectedViews.keys()).filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking);
}
export function SelectedSchemaDoc(): Doc | undefined {
return manager.SelectedSchemaDocument;
@@ -100,4 +99,7 @@ export namespace SelectionManager {
export function SelectedSchemaCollection(): CollectionSchemaView | undefined {
return manager.SelectedSchemaCollection;
}
+ export function Docs(): Doc[] {
+ return Array.from(manager.SelectedViews.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking);
+ }
} \ No newline at end of file
diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss
index c9db94419..b7199f433 100644
--- a/src/client/util/SettingsManager.scss
+++ b/src/client/util/SettingsManager.scss
@@ -360,17 +360,18 @@
flex-direction: row;
position: relative;
min-height: 250px;
+ height: 100%;
width: 100%;
.settings-content {
- background-color: #fdfdfd;
+ background-color: $off-white;
}
}
.settings-panel {
position: relative;
min-width: 150px;
- background-color: #e4e4e4;
+ background-color: $light-blue;
.settings-user {
position: absolute;