aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields
diff options
context:
space:
mode:
Diffstat (limited to 'src/new_fields')
-rw-r--r--src/new_fields/Doc.ts345
-rw-r--r--src/new_fields/ObjectField.ts1
-rw-r--r--src/new_fields/RichTextField.ts16
-rw-r--r--src/new_fields/RichTextUtils.ts39
-rw-r--r--src/new_fields/ScriptField.ts8
-rw-r--r--src/new_fields/URLField.ts2
-rw-r--r--src/new_fields/documentSchemas.ts54
-rw-r--r--src/new_fields/util.ts27
8 files changed, 295 insertions, 197 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
diff --git a/src/new_fields/ObjectField.ts b/src/new_fields/ObjectField.ts
index 566104b40..9aa1c9b04 100644
--- a/src/new_fields/ObjectField.ts
+++ b/src/new_fields/ObjectField.ts
@@ -1,4 +1,3 @@
-import { Doc } from "./Doc";
import { RefField } from "./RefField";
import { OnUpdate, Parent, Copy, ToScriptString, ToString } from "./FieldSymbols";
import { Scripting } from "../client/util/Scripting";
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
index 7b6ce9b98..ad4a5a252 100644
--- a/src/new_fields/RichTextField.ts
+++ b/src/new_fields/RichTextField.ts
@@ -33,20 +33,8 @@ export class RichTextField extends ObjectField {
return this.Text;
}
- [ToPlainText]() {
- // Because we're working with plain text, just concatenate all paragraphs
- let content = JSON.parse(this.Data).doc.content;
- let paragraphs = content.filter((item: any) => item.type === "paragraph");
-
- // Functions to flatten ProseMirror paragraph objects (and their components) to plain text
- // While this function already exists in state.doc.textBeteen(), it doesn't account for newlines
- let blockText = (block: any) => block.text;
- let concatenateParagraph = (p: any) => (p.content ? p.content.map(blockText).join(joiner) : "") + delimiter;
-
- // Concatentate paragraphs and string the result together
- let textParagraphs: string[] = paragraphs.map(concatenateParagraph);
- let plainText = textParagraphs.join(joiner);
- return plainText.substring(0, plainText.length - 1);
+ public static DashField(fieldKey: string) {
+ return new RichTextField(`{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"${fieldKey}","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}`, "");
}
} \ No newline at end of file
diff --git a/src/new_fields/RichTextUtils.ts b/src/new_fields/RichTextUtils.ts
index c50f8cc48..1d90c984d 100644
--- a/src/new_fields/RichTextUtils.ts
+++ b/src/new_fields/RichTextUtils.ts
@@ -1,5 +1,5 @@
import { EditorState, Transaction, TextSelection } from "prosemirror-state";
-import { Node, Fragment, Mark, MarkType } from "prosemirror-model";
+import { Node, Fragment, Mark } from "prosemirror-model";
import { RichTextField } from "./RichTextField";
import { docs_v1 } from "googleapis";
import { GoogleApiClientUtils } from "../client/apis/google_docs/GoogleApiClientUtils";
@@ -17,6 +17,7 @@ import { Id } from "./FieldSymbols";
import { DocumentView } from "../client/views/nodes/DocumentView";
import { AssertionError } from "assert";
import { Networking } from "../client/Network";
+import { extname } from "path";
export namespace RichTextUtils {
@@ -113,6 +114,7 @@ export namespace RichTextUtils {
width: number;
title: string;
url: string;
+ agnostic: string;
}
const parseInlineObjects = async (document: docs_v1.Schema$Document): Promise<Map<string, ImageTemplate>> => {
@@ -123,12 +125,10 @@ export namespace RichTextUtils {
const objects = Object.keys(inlineObjects).map(objectId => inlineObjects[objectId]);
const mediaItems: MediaItem[] = objects.map(object => {
const embeddedObject = object.inlineObjectProperties!.embeddedObject!;
- const baseUrl = embeddedObject.imageProperties!.contentUri!;
- const filename = `upload_${Utils.GenerateGuid()}.png`;
- return { baseUrl, filename };
+ return { baseUrl: embeddedObject.imageProperties!.contentUri! };
});
- const uploads = await Networking.PostToServer("/googlePhotosMediaDownload", { mediaItems });
+ const uploads = await Networking.PostToServer("/googlePhotosMediaGet", { mediaItems });
if (uploads.length !== mediaItems.length) {
throw new AssertionError({ expected: mediaItems.length, actual: uploads.length, message: "Error with internally uploading inlineObjects!" });
@@ -136,16 +136,17 @@ export namespace RichTextUtils {
for (let i = 0; i < objects.length; i++) {
const object = objects[i];
- const { fileNames } = uploads[i];
+ const { accessPaths } = uploads[i];
+ const { agnostic, _m } = accessPaths;
const embeddedObject = object.inlineObjectProperties!.embeddedObject!;
const size = embeddedObject.size!;
const width = size.width!.magnitude!;
- const url = Utils.fileUrl(fileNames.clean);
inlineObjectMap.set(object.objectId!, {
title: embeddedObject.title || `Imported Image from ${document.title}`,
width,
- url
+ url: Utils.prepend(_m.client),
+ agnostic: Utils.prepend(agnostic.client)
});
}
}
@@ -156,7 +157,6 @@ export namespace RichTextUtils {
interface MediaItem {
baseUrl: string;
- filename: string;
}
export const Import = async (documentId: GoogleApiClientUtils.Docs.DocumentId, textNote: Doc): Promise<Opt<GoogleApiClientUtils.Docs.ImportResult>> => {
@@ -268,19 +268,19 @@ export namespace RichTextUtils {
};
const imageNode = (schema: any, image: ImageTemplate, textNote: Doc) => {
- const { url: src, width } = image;
+ const { url: src, width, agnostic } = image;
let docid: string;
- const guid = Utils.GenerateDeterministicGuid(src);
+ const guid = Utils.GenerateDeterministicGuid(agnostic);
const backingDocId = StrCast(textNote[guid]);
if (!backingDocId) {
- const backingDoc = Docs.Create.ImageDocument(src, { _width: 300, _height: 300 });
+ const backingDoc = Docs.Create.ImageDocument(agnostic, { _width: 300, _height: 300 });
DocumentView.makeCustomViewClicked(backingDoc, undefined, Docs.Create.FreeformDocument);
docid = backingDoc[Id];
textNote[guid] = docid;
} else {
docid = backingDocId;
}
- return schema.node("image", { src, width, docid, float: null, location: "onRight" });
+ return schema.node("image", { src, agnostic, width, docid, float: null, location: "onRight" });
};
const textNode = (schema: any, run: docs_v1.Schema$TextRun) => {
@@ -436,7 +436,7 @@ export namespace RichTextUtils {
const width = attrs.width;
requests.push(await EncodeImage({
startIndex: position + nodeSize - 1,
- uri: attrs.src,
+ uri: attrs.agnostic,
width: Number(typeof width === "string" ? width.replace("px", "") : width)
}));
}
@@ -499,15 +499,18 @@ export namespace RichTextUtils {
};
};
- const EncodeImage = async (information: ImageInformation) => {
- const source = [Docs.Create.ImageDocument(information.uri)];
+ const EncodeImage = async ({ uri, width, startIndex }: ImageInformation) => {
+ if (!uri) {
+ return {};
+ }
+ const source = [Docs.Create.ImageDocument(uri)];
const baseUrls = await GooglePhotos.Transactions.UploadThenFetch(source);
if (baseUrls) {
return {
insertInlineImage: {
uri: baseUrls[0],
- objectSize: { width: { magnitude: information.width, unit: "PT" } },
- location: { index: information.startIndex }
+ objectSize: { width: { magnitude: width, unit: "PT" } },
+ location: { index: startIndex }
}
};
}
diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts
index f8a8d1226..9288fea9e 100644
--- a/src/new_fields/ScriptField.ts
+++ b/src/new_fields/ScriptField.ts
@@ -106,7 +106,7 @@ export class ScriptField extends ObjectField {
}
public static CompileScript(script: string, params: object = {}, addReturn = false, capturedVariables?: { [name: string]: Field }) {
const compiled = CompileScript(script, {
- params: { this: Doc.name, _last_: "any", ...params },
+ params: { this: Doc.name, source: Doc.name, _last_: "any", ...params },
typecheck: false,
editable: true,
addReturn: addReturn,
@@ -114,8 +114,8 @@ export class ScriptField extends ObjectField {
});
return compiled;
}
- public static MakeFunction(script: string, params: object = {}) {
- const compiled = ScriptField.CompileScript(script, params, true);
+ public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Field }) {
+ const compiled = ScriptField.CompileScript(script, params, true, capturedVariables);
return compiled.compiled ? new ScriptField(compiled) : undefined;
}
@@ -130,7 +130,7 @@ export class ScriptField extends ObjectField {
export class ComputedField extends ScriptField {
_lastComputedResult: any;
//TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc
- value = computedFn((doc: Doc) => this._lastComputedResult = this.script.run({ this: doc, _last_: this._lastComputedResult }, console.log).result);
+ value = computedFn((doc: Doc) => this._lastComputedResult = this.script.run({ source: doc.expandedTemplate || doc, this: doc, _last_: this._lastComputedResult }, console.log).result);
public static MakeScript(script: string, params: object = {}) {
const compiled = ScriptField.CompileScript(script, params, false);
return compiled.compiled ? new ComputedField(compiled) : undefined;
diff --git a/src/new_fields/URLField.ts b/src/new_fields/URLField.ts
index cfab36906..fb71160ca 100644
--- a/src/new_fields/URLField.ts
+++ b/src/new_fields/URLField.ts
@@ -49,3 +49,5 @@ export const nullAudio = "https://actions.google.com/sounds/v1/alarms/beep_short
@scriptingGlobal @Deserializable("pdf") export class PdfField extends URLField { }
@scriptingGlobal @Deserializable("web") export class WebField extends URLField { }
@scriptingGlobal @Deserializable("youtube") export class YoutubeField extends URLField { }
+@scriptingGlobal @Deserializable("webcam") export class WebCamField extends URLField { }
+
diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts
index 4a5c1fdb0..7006163e0 100644
--- a/src/new_fields/documentSchemas.ts
+++ b/src/new_fields/documentSchemas.ts
@@ -4,39 +4,47 @@ import { Doc } from "./Doc";
import { DateField } from "./DateField";
export const documentSchema = createSchema({
- layout: "string", // this is the native layout string for the document. templates can be added using other fields and setting layoutKey below (see layout_custom as an example)
+ type: "string", // enumerated type of document -- should be template-specific (ie, start with an '_')
+ layout: "string", // this is the native layout string for the document. templates can be added using other fields and setting layoutKey below
layoutKey: "string", // holds the field key for the field that actually holds the current lyoat
- layout_custom: Doc, // used to hold a custom layout (there's nothing special about this field .. any field could hold a custom layout that can be selected by setting 'layoutKey')
title: "string", // document title (can be on either data document or layout)
- _dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy")
- _nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set
- _nativeHeight: "number", // "
- _width: "number", // width of document in its container's coordinate system
- _height: "number", // "
+ dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy")
+ childDropAction: "string", // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "alias" or "copy")
+ _autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents
+ _nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set
+ _nativeHeight: "number", // "
+ _width: "number", // width of document in its container's coordinate system
+ _height: "number", // "
+ _xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set
+ _yPadding: "number", // pixels of padding on top/bottom of collectionfreeformview contents when fitToBox is set
+ _xMargin: "number", // margin added on left/right of most documents to add separation from their container
+ _yMargin: "number", // margin added on top/bottom of most documents to add separation from their container
+ _showCaption: "string", // whether editable caption text is overlayed at the bottom of the document
+ _showTitle: "string", // the fieldkey whose contents should be displayed at the top of the document
+ _showTitleHover: "string", // the showTitle should be shown only on hover
+ _showAudio: "boolean", // whether to show the audio record icon on documents
_freeformLayoutEngine: "string",// the string ID for the layout engine to use to layout freeform view documents
- _LODdisable: "boolean", // whether to disbale LOD switching for CollectionFreeFormViews
+ _LODdisable: "boolean", // whether to disbale LOD switching for CollectionFreeFormViews
+ _pivotField: "string", // specifies which field should be used as the timeline/pivot axis
+ _replacedChrome: "string", // what the default chrome is replaced with. Currently only supports the value of 'replaced' for PresBox's.
+ _chromeStatus: "string", // determines the state of the collection chrome. values allowed are 'replaced', 'enabled', 'disabled', 'collapsed'
color: "string", // foreground color of document
backgroundColor: "string", // background color of document
opacity: "number", // opacity of document
- creationDate: DateField, // when the document was created
+ creationDate: DateField, // when the document was created
links: listSpec(Doc), // computed (readonly) list of links associated with this document
- removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped
onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop)
- onPointerDown: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop)
- onPointerUp: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop)
+ onPointerDown: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop)
+ onPointerUp: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop)
onDragStart: ScriptField, // script to run when document is dragged (without being selected). the script should return the Doc to be dropped.
dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document.
- ignoreAspect: "boolean", // whether aspect ratio should be ignored when laying out or manipulating the document
- autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents
+ removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped
isTemplateForField: "string",// when specifies a field key, then the containing document is a template that renders the specified field
isBackground: "boolean", // whether document is a background element and ignores input events (can only selet with marquee)
- type: "string", // enumerated type of document
treeViewOpen: "boolean", // flag denoting whether the documents sub-tree (contents) is visible or hidden
treeViewExpandedView: "string", // name of field whose contents are being displayed as the document's subtree
- preventTreeViewOpen: "boolean", // ignores the treeViewOpen flag (for allowing a view to not be slaved to other views of the document)
- currentTimecode: "number", // current play back time of a temporal document (video / audio)
- summarizedDocs: listSpec(Doc), // documents that are summarized by this document (and which will typically be opened by clicking this document)
- maximizedDocs: listSpec(Doc), // documents to maximize when clicking this document (generally this document will be an icon)
+ treeViewPreventOpen: "boolean", // ignores the treeViewOpen flag (for allowing a view to not be slaved to other views of the document)
+ currentTimecode: "number", // current play back time of a temporal document (video / audio)
maximizeLocation: "string", // flag for where to place content when following a click interaction (e.g., onRight, inPlace, inTab)
lockedPosition: "boolean", // whether the document can be moved (dragged)
lockedTransform: "boolean", // whether the document can be panned/zoomed
@@ -44,20 +52,12 @@ export const documentSchema = createSchema({
borderRounding: "string", // border radius rounding of document
searchFields: "string", // the search fields to display when this document matches a search in its metadata
heading: "number", // the logical layout 'heading' of this document (used by rule provider to stylize h1 header elements, from h2, etc)
- showCaption: "string", // whether editable caption text is overlayed at the bottom of the document
- showTitle: "string", // the fieldkey whose contents should be displayed at the top of the document
- showTitleHover: "string", // the showTitle should be shown only on hover
isButton: "boolean", // whether document functions as a button (overiding native interactions of its content)
ignoreClick: "boolean", // whether documents ignores input clicks (but does not ignore manipulation and other events)
- isAnimating: "string", // whether the document is in the midst of animating between two layouts (used by icons to de/iconify documents). value is undefined|"min"|"max"
- animateToDimensions: listSpec("number"), // layout information about the target rectangle a document is animating towards
scrollToLinkID: "string", // id of link being traversed. allows this doc to scroll/highlight/etc its link anchor. scrollToLinkID should be set to undefined by this doc after it sets up its scroll,etc.
strokeWidth: "number",
fontSize: "string",
fitToBox: "boolean", // whether freeform view contents should be zoomed/panned to fill the area of the document view
- xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set
- yPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set
- LODarea: "number", // area (width*height) where CollectionFreeFormViews switch from a label to rendering contents
letterSpacing: "string",
textTransform: "string"
});
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index 2cedda7a6..6d7f6b56e 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -1,5 +1,5 @@
import { UndoManager } from "../client/util/UndoManager";
-import { Doc, Field, FieldResult, UpdatingFromServer } from "./Doc";
+import { Doc, Field, FieldResult, UpdatingFromServer, LayoutSym } from "./Doc";
import { SerializationHelper } from "../client/util/SerializationHelper";
import { ProxyField, PrefetchProxy } from "./Proxy";
import { RefField } from "./RefField";
@@ -14,7 +14,7 @@ function _readOnlySetter(): never {
}
export function TraceMobx() {
- //trace();
+ // trace();
}
export interface GetterResult {
@@ -100,19 +100,17 @@ export function makeEditable() {
_setter = _setterImpl;
}
-let layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox",
- "LODdisable", "dropAction", "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"];
+const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox",
+ "LODdisable", "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"];
export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean {
let prop = in_prop;
- if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" &&
- ((prop as string).startsWith("_") || layoutProps.includes(prop))) {
+ if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) {
if (!prop.startsWith("_")) {
console.log(prop + " is deprecated - switch to _" + prop);
prop = "_" + prop;
}
- const resolvedLayout = getFieldImpl(target, getFieldImpl(target, "layoutKey", receiver), receiver);
- if (resolvedLayout instanceof Doc) {
- resolvedLayout[prop] = value;
+ if (target.__LAYOUT__) {
+ target.__LAYOUT__[prop] = value;
return true;
}
}
@@ -121,16 +119,15 @@ export function setter(target: any, in_prop: string | symbol | number, value: an
export function getter(target: any, in_prop: string | symbol | number, receiver: any): any {
let prop = in_prop;
- if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" &&
- ((prop as string).startsWith("_") || layoutProps.includes(prop))) {
+ if (prop === LayoutSym) {
+ return target.__LAYOUT__;
+ }
+ if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) {
if (!prop.startsWith("_")) {
console.log(prop + " is deprecated - switch to _" + prop);
prop = "_" + prop;
}
- const resolvedLayout = getFieldImpl(target, getFieldImpl(target, "layoutKey", receiver), receiver);
- if (resolvedLayout instanceof Doc) {
- return resolvedLayout[prop];
- }
+ if (target.__LAYOUT__) return target.__LAYOUT__[prop];
}
if (prop === "then") {//If we're being awaited
return undefined;