aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts124
-rw-r--r--src/client/util/CurrentUserUtils.ts57
2 files changed, 85 insertions, 96 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 01cfe90da..ad6a4dd3c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -69,53 +69,57 @@ class EmptyBox {
return "";
}
}
-abstract class FInfo {
+export abstract class FInfo {
description: string = "";
- type?: string;
+ fieldType?: string;
values?: Field[];
- layoutField?: boolean; // is this field a layout (or datadoc) field
// format?: string; // format to display values (e.g, decimal places, $, etc)
// parse?: ScriptField; // parse a value from a string
- constructor(d: string, l: boolean = false) { this.description = d; this.layoutField = l; }
+ constructor(d: string) { this.description = d; }
}
-class BoolInfo extends FInfo { type?= "boolean"; values?: boolean[] = [true, false]; }
-class NumInfo extends FInfo { type?= "number"; values?: number[] = []; }
-class StrInfo extends FInfo { type?= "string"; values?: string[] = []; }
-class DocInfo extends FInfo { type?= "Doc"; values?: Doc[] = []; }
-class DimInfo extends FInfo { type?= "DimUnit"; values?= [DimUnit.Pixel, DimUnit.Ratio]; }
-class PEInfo extends FInfo { type?= "pointerEvents"; values?= ["all", "none"]; }
-class DAInfo extends FInfo { type?= "dropActionType"; values?= ["alias", "copy", "move", "same", "proto", "none"]; }
+class BoolInfo extends FInfo { fieldType?= "boolean"; values?: boolean[] = [true, false]; }
+class NumInfo extends FInfo { fieldType?= "number"; values?: number[] = []; constructor(d:string, values?:number[]) { super(d); this.values = values; }}
+class StrInfo extends FInfo { fieldType?= "string"; values?: string[] = []; constructor(d:string, values?:string[]) { super(d); this.values = values; }}
+class DocInfo extends FInfo { fieldType?= "Doc"; values?: Doc[] = []; constructor(d:string, values?:Doc[]) { super(d); this.values = values; }}
+class DimInfo extends FInfo { fieldType?= "DimUnit"; values?= [DimUnit.Pixel, DimUnit.Ratio]; }
+class PEInfo extends FInfo { fieldType?= "pointerEvents"; values?= ["all", "none"]; }
+class DAInfo extends FInfo { fieldType?= "dropActionType"; values?= ["alias", "copy", "move", "same", "proto", "none"]; }
type BOOLt = BoolInfo | boolean;
-type NUMt = NumInfo | number;
-type STRt = StrInfo | string;
-type DOCt = DocInfo | Doc;
-type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio;
-type PEVt = PEInfo | "none" | "all";
+type NUMt = NumInfo | number;
+type STRt = StrInfo | string;
+type DOCt = DocInfo | Doc;
+type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio;
+type PEVt = PEInfo | "none" | "all";
type DROPt = DAInfo | dropActionType;
export class DocumentOptions {
+ x?: NUMt = new NumInfo("x coordinate of document in a freeform view");
+ y?: NUMt = new NumInfo("y coordinage of document in a freeform view");
+ z?: NUMt = new NumInfo("whether document is in overlay (1) or not (0)", [1,0]);
system?: BOOLt = new BoolInfo("is this a system created/owned doc");
+ type?: STRt = new StrInfo("type of document", Array.from(Object.keys(DocumentType)));
+ title?: string;
_dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else");
allowOverlayDrop?: BOOLt = new BoolInfo("can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?");
childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection ");
targetDropAction?: DROPt = new DAInfo("what should happen to the source document when ??? ");
- userColor?: string; // color associated with a Dash user (seen in header fields of shared documents)
- color?: string; // foreground color data doc
+ userColor?: STRt = new StrInfo("color associated with a Dash user (seen in header fields of shared documents)");
+ color?: STRt = new StrInfo("foreground color data doc");
backgroundColor?: STRt = new StrInfo("background color for data doc");
- _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)", true);
- _autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents", true);
- _headerHeight?: NUMt = new NumInfo("height of document header used for displaying title", true);
- _headerFontSize?: NUMt = new NumInfo("font size of header of custom notes", true);
- _headerPointerEvents?: PEVt = new PEInfo("types of events the header of a custom text document can consume", true);
- _panX?: NUMt = new NumInfo("horizontal pan location of a freeform view", true);
- _panY?: NUMt = new NumInfo("vertical pan location of a freeform view", true);
- _width?: NUMt = new NumInfo("displayed width of a document", true);
- _height?: NUMt = new NumInfo("displayed height of document", true);
- _nativeWidth?: NUMt = new NumInfo("native width of document contents (e.g., the pixel width of an image)", true);
- _nativeHeight?: NUMt = new NumInfo("native height of document contents (e.g., the pixel height of an image)", true);
- _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", true);
- _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true);
- _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)", true);
- _fitContentsToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
+ _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)");
+ _autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents");
+ _headerHeight?: NUMt = new NumInfo("height of document header used for displaying title");
+ _headerFontSize?: NUMt = new NumInfo("font size of header of custom notes");
+ _headerPointerEvents?: PEVt = new PEInfo("types of events the header of a custom text document can consume");
+ _panX?: NUMt = new NumInfo("horizontal pan location of a freeform view");
+ _panY?: NUMt = new NumInfo("vertical pan location of a freeform view");
+ _width?: NUMt = new NumInfo("displayed width of a document");
+ _height?: NUMt = new NumInfo("displayed height of document");
+ _nativeWidth?: NUMt = new NumInfo("native width of document contents (e.g., the pixel width of an image)");
+ _nativeHeight?: NUMt = new NumInfo("native height of document contents (e.g., the pixel height of an image)");
+ _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height");
+ _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units");
+ _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)");
+ _fitContentsToBox?: BOOLt = new BoolInfo("whether a freeformview should zoom/scale to create a shrinkwrapped view of its content");
_contentBounds?: List<number>; // the (forced) bounds of the document to display. format is: [left, top, right, bottom]
_lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
_lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
@@ -155,23 +159,20 @@ export class DocumentOptions {
_timecodeToShow?: number; // the time that a document should be displayed (e.g., when an annotation shows up as a video plays)
_timecodeToHide?: number; // the time that a document should be hidden
_timelineLabel?: boolean; // whether the document exists on a timeline
- "_carousel-caption-xMargin"?: number;
- "_carousel-caption-yMargin"?: number;
- "icon-nativeWidth"?: number;
- "icon-nativeHeight"?: number;
- "dragFactory-count"?: number; // number of items created from a drag button (used for setting title with incrementing index)
- x?: number;
- y?: number;
- z?: number; // whether document is in overlay (1) or not (0 or undefined)
+ "_carousel-caption-xMargin"?: NUMt = new NumInfo("x margin of caption inside of a carouself collection");
+ "_carousel-caption-yMargin"?: NUMt = new NumInfo("y margin of caption inside of a carouself collection");
+ "icon-nativeWidth"?: NUMt = new NumInfo("native width of icon view");
+ "icon-nativeHeight"?: NUMt = new NumInfo("native height of icon view");
+ "dragFactory-count"?: NUMt = new NumInfo("number of items created from a drag button (used for setting title with incrementing index)");
lat?: number;
lng?: number;
infoWindowOpen?: boolean;
author?: string;
_layoutKey?: string;
+ fieldValues?: List<any>; // possible field values used by fieldInfos
+ fieldType?: string; // type of afield used by fieldInfos
unrendered?: boolean; // denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf)
- type?: string;
- title?: string;
- "acl-Public"?: string; // public permissions
+ "acl-Public"?: string; // public permissions
"_acl-Public"?: string; // public permissions
version?: string; // version identifier for a document
label?: string;
@@ -340,33 +341,6 @@ export class DocumentOptions {
}
export namespace Docs {
- const _docOptions = new DocumentOptions();
-
- export async function setupFieldInfos() {
- return await DocServer.GetRefField("FieldInfos8") as Doc ??
- runInAction(() => {
- const infos = new Doc("FieldInfos8", true);
- const keys = Object.keys(new DocumentOptions());
- for (const key of keys) {
- const options = (_docOptions as any)[key] as FInfo;
- const finfo = new Doc();
- finfo.name = key;
- switch (options.type) {
- case "boolean": finfo.options = new List<boolean>(options.values as any as boolean[]); break;
- case "number": finfo.options = new List<number>(options.values as any as number[]); break;
- case "Doc": finfo.options = new List<Doc>(options.values as any as Doc[]); break;
- default: // string, pointerEvents, dimUnit, dropActionType
- finfo.options = new List<string>(options.values as any as string[]); break;
- }
- finfo.layoutField = options.layoutField;
- finfo.description = options.description;
- finfo.type = options.type;
- infos[key] = finfo;
- }
- return infos;
- });
- }
-
export let newAccount: boolean = false;
export namespace Prototypes {
@@ -798,8 +772,8 @@ export namespace Docs {
I.tool = tool;
I["text-align"] = "center";
I.title = "ink";
- I.x = options.x;
- I.y = options.y;
+ I.x = options.x as number;
+ I.y = options.y as number;
I._width = options._width as number;
I._height = options._height as number;
I._fontFamily = "cursive";
@@ -1266,8 +1240,8 @@ export namespace DocUtils {
return DocServer.GetRefField(id).then(field => {
if (field instanceof Doc) {
const alias = Doc.MakeAlias(field);
- alias.x = options.x || 0;
- alias.y = options.y || 0;
+ alias.x = options.x as number || 0;
+ alias.y = options.y as number || 0;
alias._width = (options._width as number) || 300;
alias._height = (options._height as number) || (options._width as number) || 300;
return alias;
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index fe9a9b2d9..b9724051a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -13,7 +13,7 @@ import { ImageField, nullAudio } from "../../fields/URLField";
import { SharingPermissions } from "../../fields/util";
import { OmitKeys, Utils } from "../../Utils";
import { DocServer } from "../DocServer";
-import { Docs, DocumentOptions, DocUtils } from "../documents/Documents";
+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";
@@ -39,6 +39,7 @@ import { SnappingManager } from "./SnappingManager";
import { UndoManager } from "./UndoManager";
interface Button {
+ // DocumentOptions fields a button can set
title?: string;
toolTip?: string;
icon?: string;
@@ -51,6 +52,8 @@ interface Button {
btnList?: List<string>;
ignoreClick?: boolean;
buttonText?: string;
+
+ // fields that do not correspond to DocumentOption fields
scripts?: { script?: string; onClick?: string; }
funcs?: { [key:string]: string };
subMenu?: Button[];
@@ -861,8 +864,7 @@ export class CurrentUserUtils {
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 };
- const reqdBtnScripts = { onClick: "importDocument()" };
- return this.AssignDocField(myImports, "buttonMenuDoc", (opts) => Docs.Create.FontIconDocument(opts), reqdBtnOpts, undefined, reqdBtnScripts);
+ return this.AssignDocField(myImports, "buttonMenuDoc", (opts) => Docs.Create.FontIconDocument(opts), reqdBtnOpts, undefined, { onClick: "importDocument()" });
}
static setupClickEditorTemplates(doc: Doc) {
@@ -875,9 +877,8 @@ export class CurrentUserUtils {
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 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 });
}
@@ -914,7 +915,7 @@ export class CurrentUserUtils {
}
static async updateUserDocument(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) {
- doc.globalGroupDatabase ?? (doc.globalGroupDatabase = Docs.Prototypes.MainGroupDocument());
+ this.AssignDocField(doc, "globalGroupDatabase", () => Docs.Prototypes.MainGroupDocument(), {});
await DocListCastAsync(DocCast(doc.globalGroupDatabase).data);
reaction(() => DateCast(DocCast(doc.globalGroupDatabase)["data-lastModified"]),
async () => {
@@ -954,17 +955,35 @@ export class CurrentUserUtils {
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
- doc.globalScriptDatabase ?? ( doc.globalScriptDatabase = Docs.Prototypes.MainScriptDocument());
- doc.myHeaderBar ?? (doc.myHeaderBar = Docs.Create.MulticolumnDocument([], { title: "header bar", system: true })); // drop down panel at top of dashboard for stashing documents
+ 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
setTimeout(() => DocServer.UPDATE_SERVER_CACHE(), 2500);
- doc.fieldInfos = await Docs.setupFieldInfos();
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;
}
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);
+ const entries = Object.entries(new DocumentOptions());
+ 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("_")};
+ 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
+ }
+ 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 => {
@@ -1007,17 +1026,14 @@ export class CurrentUserUtils {
public static _urlState: HistoryUtil.DocUrl;
public static openDashboard = (doc: Doc, fromHistory = false) => {
- const userDoc = Doc.UserDoc();
CurrentUserUtils.MainDocId = doc[Id];
- if (!DocListCast(CurrentUserUtils.MyDashboards.data).includes(doc)) {
- Doc.AddDocToList(CurrentUserUtils.MyDashboards, "data", doc);
- }
+ Doc.AddDocToList(CurrentUserUtils.MyDashboards, "data", doc);
- if (doc) { // this has the side-effect of setting the main container since we're assigning the active/guest dashboard
- userDoc ? (CurrentUserUtils.ActiveDashboard = doc) : (CurrentUserUtils.GuestDashboard = 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);
+
const state = CurrentUserUtils._urlState;
- if (state.sharing === true && !userDoc) {
+ if (state.sharing === true && !Doc.UserDoc()) {
DocServer.Control.makeReadOnly();
} else {
fromHistory || HistoryUtil.pushState({
@@ -1054,7 +1070,7 @@ export class CurrentUserUtils {
const upload = Utils.prepend("/uploadDoc");
const formData = new FormData();
const file = input.files && input.files[0];
- if (file && file.type === 'application/zip') {
+ if (file?.type === 'application/zip') {
formData.append('file', file);
formData.append('remap', "true");
const response = await fetch(upload, { method: "POST", body: formData });
@@ -1067,9 +1083,8 @@ export class CurrentUserUtils {
}
}
} else if (input.files && input.files.length !== 0) {
- const importDocs = CurrentUserUtils.MyImports;
const disposer = OverlayView.ShowSpinner();
- DocListCastAsync(importDocs.data).then(async list => {
+ DocListCastAsync(CurrentUserUtils.MyImports.data).then(async list => {
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");