aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields/Doc.ts
diff options
context:
space:
mode:
authoryipstanley <stanley_yip@brown.edu>2020-02-29 14:18:43 -0500
committeryipstanley <stanley_yip@brown.edu>2020-02-29 14:18:43 -0500
commit2f6e27c67d1790d4350eede3003f0b614460f4d1 (patch)
treeef5e70925b8cdeb8229af849e33e6f3a4cceae7f /src/new_fields/Doc.ts
parentf1fcbeea5fb103b7623e795e72aacd4dfacc6c70 (diff)
parent640f14da28d97600fb32d09023fc932e3a4052c4 (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into pen
Diffstat (limited to 'src/new_fields/Doc.ts')
-rw-r--r--src/new_fields/Doc.ts345
1 files changed, 227 insertions, 118 deletions
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 5f78636a9..dcd97f079 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -1,22 +1,23 @@
-import { observable, ObservableMap, runInAction } from "mobx";
+import { action, computed, observable, ObservableMap, runInAction } from "mobx";
+import { computedFn } from "mobx-utils";
import { alias, map, serializable } from "serializr";
import { DocServer } from "../client/DocServer";
import { DocumentType } from "../client/documents/DocumentTypes";
import { Scripting, scriptingGlobal } from "../client/util/Scripting";
import { afterDocDeserialize, autoObject, Deserializable, SerializationHelper } from "../client/util/SerializationHelper";
-import { Copy, HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols";
+import { UndoManager } from "../client/util/UndoManager";
+import { intersectRect } from "../Utils";
+import { HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols";
import { List } from "./List";
import { ObjectField } from "./ObjectField";
import { PrefetchProxy, ProxyField } from "./Proxy";
import { FieldId, RefField } from "./RefField";
+import { RichTextField } from "./RichTextField";
import { listSpec } from "./Schema";
-import { ComputedField, ScriptField } from "./ScriptField";
-import { BoolCast, Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
+import { ComputedField } from "./ScriptField";
+import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util";
-import { intersectRect } from "../Utils";
-import { UndoManager } from "../client/util/UndoManager";
-import { computedFn } from "mobx-utils";
-import { RichTextField } from "./RichTextField";
+import { Docs } from "../client/documents/Documents";
export namespace Field {
export function toKeyValueString(doc: Doc, key: string): string {
@@ -47,7 +48,7 @@ export namespace Field {
} else if (field instanceof RefField) {
return field[ToString]();
}
- return "(null)";
+ return "";
}
export function IsField(field: any): field is Field;
export function IsField(field: any, includeUndefined: true): field is Field | undefined;
@@ -89,6 +90,7 @@ export function DocListCast(field: FieldResult): Doc[] {
export const WidthSym = Symbol("Width");
export const HeightSym = Symbol("Height");
export const DataSym = Symbol("Data");
+export const LayoutSym = Symbol("Layout");
export const UpdatingFromServer = Symbol("UpdatingFromServer");
const CachedUpdates = Symbol("Cached updates");
@@ -110,8 +112,16 @@ export class Doc extends RefField {
get: getter,
// getPrototypeOf: (target) => Cast(target[SelfProxy].proto, Doc) || null, // TODO this might be able to replace the proto logic in getter
has: (target, key) => key in target.__fields,
- ownKeys: target => Object.keys(target.__fields),
+ ownKeys: target => {
+ const obj = {} as any;
+ Object.assign(obj, target.___fields);
+ runInAction(() => obj.__LAYOUT__ = target.__LAYOUT__);
+ return Object.keys(obj);
+ },
getOwnPropertyDescriptor: (target, prop) => {
+ if (prop.toString() === "__LAYOUT__") {
+ return Reflect.getOwnPropertyDescriptor(target, prop);
+ }
if (prop in target.__fields) {
return {
configurable: true,//TODO Should configurable be true?
@@ -135,10 +145,7 @@ export class Doc extends RefField {
[key: string]: FieldResult;
@serializable(alias("fields", map(autoObject(), { afterDeserialize: afterDocDeserialize })))
- private get __fields() {
- return this.___fields;
- }
-
+ private get __fields() { return this.___fields; }
private set __fields(value) {
this.___fields = value;
for (const key in value) {
@@ -156,25 +163,37 @@ export class Doc extends RefField {
private [UpdatingFromServer]: boolean = false;
private [Update] = (diff: any) => {
- if (this[UpdatingFromServer]) {
- return;
- }
- DocServer.UpdateField(this[Id], diff);
+ !this[UpdatingFromServer] && DocServer.UpdateField(this[Id], diff);
}
private [Self] = this;
private [SelfProxy]: any;
public [WidthSym] = () => NumCast(this[SelfProxy]._width);
public [HeightSym] = () => NumCast(this[SelfProxy]._height);
- public get [DataSym]() { return Cast(this[SelfProxy].resolvedDataDoc, Doc, null) || this[SelfProxy]; }
-
- [ToScriptString]() {
- return "invalid";
- }
- [ToString]() {
- return "Doc";
+ public get [LayoutSym]() { return this[SelfProxy].__LAYOUT__; }
+ public get [DataSym]() {
+ const self = this[SelfProxy];
+ return self.resolvedDataDoc && !self.isTemplateForField ? self :
+ Doc.GetProto(Cast(Doc.Layout(self).resolvedDataDoc, Doc, null) || self);
+ }
+ @computed get __LAYOUT__() {
+ const templateLayoutDoc = Cast(Doc.LayoutField(this[SelfProxy]), Doc, null);
+ if (templateLayoutDoc) {
+ let renderFieldKey: any;
+ const layoutField = templateLayoutDoc[StrCast(templateLayoutDoc.layoutKey, "layout")];
+ if (typeof layoutField === "string") {
+ renderFieldKey = layoutField.split("'")[1];
+ } else {
+ return Cast(layoutField, Doc, null);
+ }
+ return Cast(this[SelfProxy][renderFieldKey + "-layout[" + templateLayoutDoc[Id] + "]"], Doc, null) || templateLayoutDoc;
+ }
+ return undefined;
}
+ [ToScriptString]() { return `DOC-"${this[Self][Id]}"-`; }
+ [ToString]() { return `Doc(${this.title})`; }
+
private [CachedUpdates]: { [key: string]: () => void | Promise<any> } = {};
public static CurrentUserEmail: string = "";
public async [HandleUpdate](diff: any) {
@@ -260,8 +279,7 @@ export namespace Doc {
export function Get(doc: Doc, key: string, ignoreProto: boolean = false): FieldResult {
try {
- const self = doc[Self];
- return getField(self, key, ignoreProto);
+ return getField(doc[Self], key, ignoreProto);
} catch {
return doc;
}
@@ -330,9 +348,12 @@ export namespace Doc {
return r || r2 || r3 || r4;
}
- // gets the document's prototype or returns the document if it is a prototype
- export function GetProto(doc: Doc) {
- return doc && (Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc));
+ // Gets the data document for the document. Note: this is mis-named -- it does not specifically
+ // return the doc's proto, but rather recursively searches through the proto inheritance chain
+ // and returns the document who's proto is undefined or whose proto is marked as a base prototype ('isPrototype').
+ export function GetProto(doc: Doc): Doc {
+ const proto = doc && (Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc));
+ return proto === doc ? proto : Doc.GetProto(proto);
}
export function GetDataDoc(doc: Doc): Doc {
const proto = Doc.GetProto(doc);
@@ -416,17 +437,13 @@ export namespace Doc {
return bounds;
}
- export function MakeTitled(title: string) {
- const doc = new Doc();
- doc.title = title;
- return doc;
- }
- export function MakeAlias(doc: Doc) {
- const alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc) : Doc.MakeDelegate(doc);
- const layout = Doc.Layout(alias);
- if (layout instanceof Doc && layout !== alias) {
+ export function MakeAlias(doc: Doc, id?: string) {
+ const alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc, undefined, id) : Doc.MakeDelegate(doc, id);
+ const layout = Doc.LayoutField(alias);
+ if (layout instanceof Doc && layout !== alias && layout === Doc.Layout(alias)) {
Doc.SetLayout(alias, Doc.MakeAlias(layout));
}
+ alias.aliasOf = doc;
alias.title = ComputedField.MakeFunction(`renameAlias(this, ${Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1})`);
return alias;
}
@@ -437,7 +454,7 @@ export namespace Doc {
// the lyouatDoc's layout is layout string (not a document)
//
export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) {
- return layoutDoc.isTemplateForField && dataDoc && layoutDoc !== dataDoc && !(Doc.LayoutField(layoutDoc) instanceof Doc);
+ return (layoutDoc.isTemplateForField || layoutDoc.isTemplateDoc) && dataDoc && layoutDoc !== dataDoc && !(Doc.LayoutField(layoutDoc) instanceof Doc);
}
//
@@ -445,8 +462,8 @@ export namespace Doc {
// between the two. If so, the layoutDoc is expanded into a new document that inherits the properties
// of the original layout while allowing for individual layout properties to be overridden in the expanded layout.
//
- export function expandTemplateLayout(templateLayoutDoc: Doc, dataDoc?: Doc) {
- if (!WillExpandTemplateLayout(templateLayoutDoc, dataDoc) || !dataDoc) return templateLayoutDoc;
+ export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc) {
+ if (!WillExpandTemplateLayout(templateLayoutDoc, targetDoc) || !targetDoc) return templateLayoutDoc;
const templateField = StrCast(templateLayoutDoc.isTemplateForField); // the field that the template renders
// First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc
@@ -454,19 +471,27 @@ export namespace Doc {
// If it doesn't find the expanded layout, then it makes a delegate of the template layout and
// saves it on the data doc indexed by the template layout's id.
//
- const expandedLayoutFieldKey = templateField + "-layout[" + templateLayoutDoc[Id] + "]";
- const expandedTemplateLayout = dataDoc?.[expandedLayoutFieldKey];
- if (expandedTemplateLayout === undefined) {
- setTimeout(() => {
- if (!dataDoc[expandedLayoutFieldKey]) {
+ const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc);
+ const expandedLayoutFieldKey = (templateField || layoutFielddKey) + "-layout[" + templateLayoutDoc[Id] + "]";
+ let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey];
+ if (templateLayoutDoc.resolvedDataDoc instanceof Promise) {
+ expandedTemplateLayout = undefined;
+ } else if (templateLayoutDoc.resolvedDataDoc === Doc.GetProto(targetDoc)) {
+ expandedTemplateLayout = templateLayoutDoc;
+ } else if (expandedTemplateLayout === undefined) {
+ setTimeout(action(() => {
+ if (!targetDoc[expandedLayoutFieldKey]) {
const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]");
- dataDoc[expandedLayoutFieldKey] = newLayoutDoc;
+ newLayoutDoc.lockedPosition = true;
+ newLayoutDoc.expandedTemplate = targetDoc;
+ targetDoc[expandedLayoutFieldKey] = newLayoutDoc;
+ const dataDoc = Doc.GetProto(targetDoc);
newLayoutDoc.resolvedDataDoc = dataDoc;
- if (dataDoc[templateField] === undefined && templateLayoutDoc[templateField] instanceof List && Cast(templateLayoutDoc[templateField], listSpec(Doc), []).length) {
+ if (dataDoc[templateField] === undefined && templateLayoutDoc[templateField] instanceof List) {
dataDoc[templateField] = ComputedField.MakeFunction(`ObjectField.MakeCopy(templateLayoutDoc["${templateField}"] as List)`, { templateLayoutDoc: Doc.name }, { templateLayoutDoc: templateLayoutDoc });
}
}
- }, 0);
+ }), 0);
}
return expandedTemplateLayout instanceof Doc ? expandedTemplateLayout : undefined; // layout is undefined if the expandedTemplate is pending.
}
@@ -474,24 +499,13 @@ export namespace Doc {
// if the childDoc is a template for a field, then this will return the expanded layout with its data doc.
// otherwise, it just returns the childDoc
export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt<Doc>, childDoc: Doc) {
- const resolvedDataDoc = containerDataDoc === containerDoc || !containerDataDoc ? undefined : Doc.GetDataDoc(containerDataDoc);
- return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc };
- }
- export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) {
- let proto: Doc | undefined = doc;
- while (proto && !Doc.IsPrototype(proto) && proto.proto) {
- proto = proto.proto;
- }
- let docExtensionForField = ((proto || doc)[fieldKey + "_ext"] as Doc);
- if (!docExtensionForField) {
- docExtensionForField = new Doc(doc[Id] + fieldKey, true);
- docExtensionForField.title = fieldKey + ".ext"; // courtesy field--- shouldn't be needed except maybe for debugging
- docExtensionForField.extendsDoc = doc; // this is used by search to map field matches on the extension doc back to the document it extends.
- docExtensionForField.extendsField = fieldKey; // this can be used by search to map matches on the extension doc back to the field that was extended.
- docExtensionForField.type = DocumentType.EXTENSION;
- (proto || doc)[fieldKey + "_ext"] = new PrefetchProxy(docExtensionForField);
+ if (!childDoc || !Doc.GetProto(childDoc)) {
+ console.log("No, no, no!");
+ return { layout: childDoc, data: childDoc };
}
- return docExtensionForField;
+ const existingResolvedDataDoc = childDoc[DataSym] !== Doc.GetProto(childDoc)[DataSym] && childDoc[DataSym];
+ const resolvedDataDoc = existingResolvedDataDoc || (Doc.AreProtosEqual(containerDataDoc, containerDoc) || !containerDataDoc || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc);
+ return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc };
}
export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc {
@@ -534,7 +548,7 @@ export namespace Doc {
} else if (cfield instanceof ComputedField) {
copy[key] = ComputedField.MakeFunction(cfield.script.originalScript);
} else if (field instanceof ObjectField) {
- copy[key] = ObjectField.MakeCopy(field);
+ copy[key] = key.includes("layout[") && doc[key] instanceof Doc ? Doc.MakeCopy(doc[key] as Doc, false) : ObjectField.MakeCopy(field);
} else if (field instanceof Promise) {
debugger; //This shouldn't happend...
} else {
@@ -561,13 +575,13 @@ export namespace Doc {
let _applyCount: number = 0;
export function ApplyTemplate(templateDoc: Doc) {
if (templateDoc) {
- const applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layoutCustom", templateDoc.title + "(..." + _applyCount++ + ")");
- applied && (Doc.GetProto(applied).layout = applied.layout);
+ const applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layout", templateDoc.title + "(..." + _applyCount++ + ")");
+ applied && (Doc.GetProto(applied).type = templateDoc.type);
return applied;
}
return undefined;
}
- export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined = undefined) {
+ export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) {
if (!templateDoc) {
target.layout = undefined;
target._nativeWidth = undefined;
@@ -577,14 +591,13 @@ export namespace Doc {
return;
}
- if ((target[targetKey] as Doc)?.proto !== templateDoc) {
- const layoutCustomLayout = Doc.MakeDelegate(templateDoc);
-
- titleTarget && (Doc.GetProto(target).title = titleTarget);
- Doc.GetProto(target).type = DocumentType.TEMPLATE;
- target.onClick = templateDoc.onClick instanceof ObjectField && templateDoc.onClick[Copy]();
-
- Doc.GetProto(target)[targetKey] = new PrefetchProxy(layoutCustomLayout);
+ if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) {
+ if (target.resolvedDataDoc) {
+ target[targetKey] = new PrefetchProxy(templateDoc);
+ } else {
+ titleTarget && (Doc.GetProto(target).title = titleTarget);
+ Doc.GetProto(target)[targetKey] = new PrefetchProxy(templateDoc);
+ }
}
target.layoutKey = targetKey;
return target;
@@ -603,16 +616,21 @@ export namespace Doc {
templateField.isTemplateForField = metadataFieldKey;
templateField.title = metadataFieldKey;
+ const templateFieldValue = templateField[metadataFieldKey] || templateField.data;
+ const templateCaptionValue = templateField.caption;
// move any data that the template field had been rendering over to the template doc so that things will still be rendered
// when the template field is adjusted to point to the new metadatafield key.
// note 1: if the template field contained a list of documents, each of those documents will be converted to templates as well.
// note 2: this will not overwrite any field that already exists on the template doc at the field key
- if (!templateDoc?.[metadataFieldKey] && templateField.data instanceof ObjectField) {
- Cast(templateField.data, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc));
- (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateField.data));
+ if (!templateDoc?.[metadataFieldKey] && templateFieldValue instanceof ObjectField) {
+ Cast(templateFieldValue, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc));
+ (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateFieldValue));
+ }
+ if (templateCaptionValue instanceof RichTextField && (templateCaptionValue.Text || templateCaptionValue.Data.toString().includes("dashField"))) {
+ templateField["caption-textTemplate"] = ComputedField.MakeFunction(`copyField(this.caption)`, { this: Doc.name });
}
- if (templateField.data instanceof RichTextField && templateField.data.Text) {
- templateField._textTemplate = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name });
+ if (templateFieldValue instanceof RichTextField && (templateFieldValue.Text || templateFieldValue.Data.toString().includes("dashField"))) {
+ templateField[metadataFieldKey + "-textTemplate"] = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name });
}
// get the layout string that the template uses to specify its layout
@@ -624,10 +642,6 @@ export namespace Doc {
// assign the template field doc a delegate of any extension document that was previously used to render the template field (since extension doc's carry rendering informatino)
Doc.Layout(templateField)[metadataFieldKey + "_ext"] = Doc.MakeDelegate(templateField[templateFieldLayoutString?.split("'")[1] + "_ext"] as Doc);
- if (templateField.backgroundColor !== templateDoc?.defaultBackgroundColor) {
- templateField.defaultBackgroundColor = templateField.backgroundColor;
- }
-
return true;
}
@@ -665,11 +679,14 @@ export namespace Doc {
}
// the document containing the view layout information - will be the Document itself unless the Document has
- // a layout field. In that case, all layout information comes from there unless overriden by Document
- export function Layout(doc: Doc) { return Doc.LayoutField(doc) instanceof Doc ? Doc.LayoutField(doc) as Doc : doc; }
+ // a layout field or 'layout' is given.
+ export function Layout(doc: Doc, layout?: Doc): Doc {
+ const overrideLayout = layout && Cast(doc["data-layout[" + layout[Id] + "]"], Doc, null);
+ return overrideLayout || doc[LayoutSym] || doc;
+ }
export function SetLayout(doc: Doc, layout: Doc | string) { doc[StrCast(doc.layoutKey, "layout")] = layout; }
export function LayoutField(doc: Doc) { return doc[StrCast(doc.layoutKey, "layout")]; }
- export function LayoutFieldKey(doc: Doc) { return StrCast(Doc.Layout(doc).layout).split("'")[1]; }
+ export function LayoutFieldKey(doc: Doc): string { return StrCast(Doc.Layout(doc).layout).split("'")[1]; }
const manager = new DocData();
export function SearchQuery(): string { return manager._searchQuery; }
export function SetSearchQuery(query: string) { runInAction(() => manager._searchQuery = query); }
@@ -677,26 +694,26 @@ export namespace Doc {
export function SetUserDoc(doc: Doc) { manager._user_doc = doc; }
export function IsBrushed(doc: Doc) {
return computedFn(function IsBrushed(doc: Doc) {
- return brushManager.BrushedDoc.has(doc) || brushManager.BrushedDoc.has(Doc.GetDataDoc(doc));
+ return brushManager.BrushedDoc.has(doc) || brushManager.BrushedDoc.has(Doc.GetProto(doc));
})(doc);
}
// don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message)
export function IsBrushedDegreeUnmemoized(doc: Doc) {
- return brushManager.BrushedDoc.has(doc) ? 2 : brushManager.BrushedDoc.has(Doc.GetDataDoc(doc)) ? 1 : 0;
+ return brushManager.BrushedDoc.has(doc) ? 2 : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? 1 : 0;
}
export function IsBrushedDegree(doc: Doc) {
return computedFn(function IsBrushDegree(doc: Doc) {
- return brushManager.BrushedDoc.has(doc) ? 2 : brushManager.BrushedDoc.has(Doc.GetDataDoc(doc)) ? 1 : 0;
+ return Doc.IsBrushedDegreeUnmemoized(doc);
})(doc);
}
export function BrushDoc(doc: Doc) {
brushManager.BrushedDoc.set(doc, true);
- brushManager.BrushedDoc.set(Doc.GetDataDoc(doc), true);
+ brushManager.BrushedDoc.set(Doc.GetProto(doc), true);
return doc;
}
export function UnBrushDoc(doc: Doc) {
brushManager.BrushedDoc.delete(doc);
- brushManager.BrushedDoc.delete(Doc.GetDataDoc(doc));
+ brushManager.BrushedDoc.delete(Doc.GetProto(doc));
return doc;
}
@@ -709,14 +726,14 @@ export namespace Doc {
document.removeEventListener("pointerdown", linkFollowUnhighlight);
}
- let dt = 0;
+ let _lastDate = 0;
export function linkFollowHighlight(destDoc: Doc, dataAndDisplayDocs = true) {
linkFollowUnhighlight();
Doc.HighlightDoc(destDoc, dataAndDisplayDocs);
document.removeEventListener("pointerdown", linkFollowUnhighlight);
document.addEventListener("pointerdown", linkFollowUnhighlight);
- const x = dt = Date.now();
- window.setTimeout(() => dt === x && linkFollowUnhighlight(), 5000);
+ const lastDate = _lastDate = Date.now();
+ window.setTimeout(() => _lastDate === lastDate && linkFollowUnhighlight(), 5000);
}
export class HighlightBrush {
@@ -724,18 +741,18 @@ export namespace Doc {
}
const highlightManager = new HighlightBrush();
export function IsHighlighted(doc: Doc) {
- return highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetDataDoc(doc));
+ return highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetProto(doc));
}
export function HighlightDoc(doc: Doc, dataAndDisplayDocs = true) {
runInAction(() => {
highlightManager.HighlightedDoc.set(doc, true);
- dataAndDisplayDocs && highlightManager.HighlightedDoc.set(Doc.GetDataDoc(doc), true);
+ dataAndDisplayDocs && highlightManager.HighlightedDoc.set(Doc.GetProto(doc), true);
});
}
export function UnHighlightDoc(doc: Doc) {
runInAction(() => {
highlightManager.HighlightedDoc.set(doc, false);
- highlightManager.HighlightedDoc.set(Doc.GetDataDoc(doc), false);
+ highlightManager.HighlightedDoc.set(Doc.GetProto(doc), false);
});
}
export function UnhighlightAll() {
@@ -763,7 +780,7 @@ export namespace Doc {
}
export function matchFieldValue(doc: Doc, key: string, value: any): boolean {
- const fieldVal = doc[key] ? doc[key] : doc[key + "_ext"];
+ const fieldVal = doc[key];
if (Cast(fieldVal, listSpec("string"), []).length) {
const vals = Cast(fieldVal, listSpec("string"), []);
return vals.some(v => v === value);
@@ -771,6 +788,104 @@ export namespace Doc {
const fieldStr = Field.toString(fieldVal as Field);
return fieldStr === value;
}
+
+ export function setNativeView(doc: any) {
+ const prevLayout = StrCast(doc.layoutKey).split("_")[1];
+ const deiconify = prevLayout === "icon" && StrCast(doc.deiconifyLayout) ? "layout_" + StrCast(doc.deiconifyLayout) : "";
+ doc.deiconifyLayout = undefined;
+ if (StrCast(doc.title).endsWith("_" + prevLayout) && deiconify) doc.title = StrCast(doc.title).replace("_" + prevLayout, deiconify);
+ else doc.title = undefined;
+ doc.layoutKey = deiconify || "layout";
+ }
+ export function setDocFilterRange(target: Doc, key: string, range?: number[]) {
+ const docRangeFilters = Cast(target._docRangeFilters, listSpec("string"), []);
+ for (let i = 0; i < docRangeFilters.length; i += 3) {
+ if (docRangeFilters[i] === key) {
+ docRangeFilters.splice(i, 3);
+ break;
+ }
+ }
+ if (range !== undefined) {
+ docRangeFilters.push(key);
+ docRangeFilters.push(range[0].toString());
+ docRangeFilters.push(range[1].toString());
+ target._docRangeFilters = new List<string>(docRangeFilters);
+ }
+ }
+ export function setDocFilter(container: Doc, key: string, value: any, modifiers?: string | number) {
+ const docFilters = Cast(container._docFilters, listSpec("string"), []);
+ for (let i = 0; i < docFilters.length; i += 3) {
+ if (docFilters[i] === key && docFilters[i + 1] === value) {
+ docFilters.splice(i, 3);
+ break;
+ }
+ }
+ if (typeof modifiers === "string") {
+ docFilters.push(key);
+ docFilters.push(value);
+ docFilters.push(modifiers);
+ container._docFilters = new List<string>(docFilters);
+ }
+ }
+ export function readDocRangeFilter(doc: Doc, key: string) {
+ const docRangeFilters = Cast(doc._docRangeFilters, listSpec("string"), []);
+ for (let i = 0; i < docRangeFilters.length; i += 3) {
+ if (docRangeFilters[i] === key) {
+ return [Number(docRangeFilters[i + 1]), Number(docRangeFilters[i + 2])];
+ }
+ }
+ }
+
+ export function freezeNativeDimensions(layoutDoc: Doc, width: number, height: number): void {
+ layoutDoc._autoHeight = false;
+ if (!layoutDoc._nativeWidth) {
+ layoutDoc._nativeWidth = NumCast(layoutDoc._width, width);
+ layoutDoc._nativeHeight = NumCast(layoutDoc._height, height);
+ }
+ }
+ export function assignDocToField(doc: Doc, field: string, id: string) {
+ DocServer.GetRefField(id).then(layout => layout instanceof Doc && (doc[field] = layout));
+ return id;
+ }
+
+ // setup a document to use enumerated values for a specified field name:
+ // doc: text document
+ // layoutString: species which text field receives the document's main text (e.g., FormattedTextBox.LayoutString("Todo") )
+ // enumeratedFieldKey : specifies which enumerated field of the document is displayed in the caption (e.g., taskStatus)
+ // captionKey: specifies which field holds the caption template (e.g., caption) -- ideally this wouldn't be needed but would be derived from the layoutString's target field key
+ //
+ export function enumeratedTextTemplate(doc: Doc, layoutString: string, enumeratedFieldKey: string, enumeratedDocs: Doc[], captionKey: string = "caption") {
+ doc.caption = RichTextField.DashField(enumeratedFieldKey);
+ doc._showCaption = captionKey;
+ doc.layout = layoutString;
+
+ Doc.addEnumerationToTextField(doc, enumeratedFieldKey, enumeratedDocs);
+ }
+
+ export async function getEnumerationTextField(enumeratedFieldKey: string) {
+ return (await DocServer.GetRefField(enumeratedFieldKey)) as Doc;
+ }
+
+ export function addEnumerationToTextField(doc: Opt<Doc>, enumeratedFieldKey: string, enumeratedDocs: Doc[]) {
+ DocServer.GetRefField(enumeratedFieldKey).then(optionsCollection => {
+ if (!(optionsCollection instanceof Doc)) {
+ optionsCollection = Docs.Create.StackingDocument([], { title: `${enumeratedFieldKey} field set` }, enumeratedFieldKey);
+ Doc.AddDocToList((Doc.UserDoc().fieldTypes as Doc), "data", optionsCollection as Doc);
+ }
+ const options = optionsCollection as Doc;
+ doc && (Doc.GetProto(doc).backgroundColor = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey})?._backgroundColor || "white"`, undefined, { options }));
+ doc && (Doc.GetProto(doc).color = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey}).color || "black"`, undefined, { options }));
+ enumeratedDocs.map(enumeratedDoc => {
+ const found = DocListCast(options.data).find(d => d.title === enumeratedDoc.title);
+ if (found) {
+ found._backgroundColor = enumeratedDoc._backgroundColor || found._backgroundColor;
+ found._color = enumeratedDoc._color || found._color;
+ } else {
+ Doc.AddDocToList(options, "data", enumeratedDoc);
+ }
+ });
+ });
+ }
}
Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; });
@@ -783,25 +898,19 @@ Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy
Scripting.addGlobal(function aliasDocs(field: any) { return new List<Doc>(field.map((d: any) => Doc.MakeAlias(d))); });
Scripting.addGlobal(function docList(field: any) { return DocListCast(field); });
Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2); });
+Scripting.addGlobal(function setNativeView(doc: any) { Doc.setNativeView(doc); });
Scripting.addGlobal(function undo() { return UndoManager.Undo(); });
Scripting.addGlobal(function redo() { return UndoManager.Redo(); });
+Scripting.addGlobal(function DOC(id: string) { console.log("Can't parse a document id in a script"); return "invalid"; });
+Scripting.addGlobal(function assignDoc(doc: Doc, field: string, id: string) { return Doc.assignDocToField(doc, field, id); });
+Scripting.addGlobal(function curPresentationItem() {
+ const curPres = Doc.UserDoc().curPresentation as Doc;
+ return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)];
+});
Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); });
Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
const docs = DocListCast(Doc.UserDoc().SelectedDocs).filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCUMENT && d.type !== DocumentType.KVP && (!excludeCollections || !Cast(d.data, listSpec(Doc), null)));
return docs.length ? new List(docs) : prevValue;
});
-Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: string) {
- const docFilters = Cast(container._docFilter, listSpec("string"), []);
- for (let i = 0; i < docFilters.length; i += 3) {
- if (docFilters[i] === key && docFilters[i + 1] === value) {
- docFilters.splice(i, 3);
- break;
- }
- }
- if (modifiers !== undefined) {
- docFilters.push(key);
- docFilters.push(value);
- docFilters.push(modifiers);
- container._docFilter = new List<string>(docFilters);
- }
-}); \ No newline at end of file
+Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: string) { Doc.setDocFilter(container, key, value, modifiers); });
+Scripting.addGlobal(function setDocFilterRange(container: Doc, key: string, range: number[]) { Doc.setDocFilterRange(container, key, range); }); \ No newline at end of file