diff options
-rw-r--r-- | src/client/util/RichTextSchema.tsx | 28 | ||||
-rw-r--r-- | src/client/util/Scripting.ts | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionViewChromes.tsx | 1 | ||||
-rw-r--r-- | src/new_fields/Doc.ts | 23 | ||||
-rw-r--r-- | src/new_fields/ScriptField.ts | 5 |
5 files changed, 31 insertions, 28 deletions
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 69296d8bc..71d4530f2 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -906,15 +906,13 @@ export class DashFieldView { if (modText) { self._fieldSpan.innerHTML = self._dashDoc![self._fieldKey] = modText; Doc.addFieldEnumerations(self._textBoxDoc, self._fieldKey, []); - } else if (!self._fieldSpan.innerText.startsWith(":=") && !self._fieldSpan.innerText.startsWith("=:=")) { - self._dashDoc![self._fieldKey] = newText; - } - - // if the text starts with a ':=' then treat it as an expression by making a computed field from its value storing it in the key - if (self._fieldSpan.innerText.startsWith(":=") && self._dashDoc) { - self._dashDoc[self._fieldKey] = ComputedField.MakeFunction(self._fieldSpan.innerText.substring(2)); - } else if (self._fieldSpan.innerText.startsWith("=:=") && self._dashDoc) { + } // if the text starts with a ':=' then treat it as an expression by making a computed field from its value storing it in the key + else if (self._fieldSpan.innerText.startsWith(":=")) { + self._dashDoc![self._fieldKey] = ComputedField.MakeFunction(self._fieldSpan.innerText.substring(2)); + } else if (self._fieldSpan.innerText.startsWith("=:=")) { Doc.Layout(tbox.props.Document)[self._fieldKey] = ComputedField.MakeFunction(self._fieldSpan.innerText.substring(3)); + } else { + self._dashDoc![self._fieldKey] = newText; } }); }; @@ -928,14 +926,9 @@ export class DashFieldView { this._fieldCheck.style.minWidth = "12px"; this._fieldCheck.style.backgroundColor = "rgba(155, 155, 155, 0.24)"; this._fieldCheck.onchange = function (e: any) { - // look for a document whose id === the fieldKey being displayed. If there's a match, then that document - // holds the different enumerated values for the field in the titles of its collected documents. - // if there's a partial match from the start of the input text, complete the text --- TODO: make this an auto suggest box and select from a drop down. - const checked = e.target.checked; - DocServer.GetRefField(self._fieldKey).then(options => self._dashDoc![self._fieldKey] = checked); + self._dashDoc![self._fieldKey] = e.target.checked; } - this._fieldSpan = document.createElement("div"); this._fieldSpan.id = Utils.GenerateGuid(); this._fieldSpan.contentEditable = "true"; @@ -950,12 +943,11 @@ export class DashFieldView { const setDashDoc = (doc: Doc) => { self._dashDoc = doc; - if (self._dashDoc && self._options?.length && !self._dashDoc[self._fieldKey]) { + if (self._options?.length && !self._dashDoc[self._fieldKey]) { self._dashDoc[self._fieldKey] = StrCast(self._options[0].title); } - const layout = tbox.props.Document; - // NOTE: if the field key starts with "@", then the actual field key is stored in the "@"fieldKey. Dereferencing these fields happens in ImageBox and RichTextSchema - self._fieldKey = self._fieldKey.startsWith("@") ? StrCast(layout[StrCast(self._fieldKey).substring(1)]) : self._fieldKey; + // NOTE: if the field key starts with "@", then the actual field key is stored in the field 'fieldKey' (removing the @). + self._fieldKey = self._fieldKey.startsWith("@") ? StrCast(tbox.props.Document[StrCast(self._fieldKey).substring(1)]) : self._fieldKey; this._labelSpan.innerHTML = `${self._fieldKey}: `; const fieldVal = Cast(this._dashDoc?.[self._fieldKey], "boolean", null); this._fieldCheck.style.display = (fieldVal === true || fieldVal === false) ? "inline-block" : "none"; diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 0fa96963e..ce21b7fa7 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -215,6 +215,8 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult { const { requiredType = "", addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options; + if (options.params && !options.params.this) options.params.this = Doc.name; + if (options.params && !options.params.self) options.params.self = Doc.name; if (options.globals) { Scripting.setScriptingGlobals(options.globals); } diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 9391b153e..aa6e07968 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -400,6 +400,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro style={{ top: collapsed ? 70 : 10, transform: `rotate(${collapsed ? 180 : 0}deg) scale(0.5) translate(${collapsed ? "-100%, -100%" : "0, 0"})`, + pointerEvents: collapsed ? "none" : undefined, opacity: (collapsed && !this.props.CollectionView.props.isSelected()) ? 0 : 0.9, left: (collapsed ? 0 : "unset"), }} diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 08efcad56..3ac297e94 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -465,8 +465,14 @@ export namespace Doc { // Returns an expanded template layout for a target data document if there is a template relationship // 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, targetDoc?: Doc, templateParams?: string) { + // templateArgs should be equivalent to the layout key that generates the template since that's where the template parameters are stored in ()'s at the end of the key. + // NOTE: the template will have references to "@params" -- the template arguments will be assigned to the '@params' field + // so that when the @params key is accessed, it will be rewritten as the key that is stored in the 'params' field and + // the derefence will then occur on the expandedTemplate (the original document). + // in the future, field references could be written as @<someparam> and then arguments would be passed in the layout key as: + // layout_mytemplate(somparam=somearg). + // then any references to @someparam would be rewritten as accesses to 'somearg' on the expandedTemplate + export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc, templateArgs?: string) { if (!WillExpandTemplateLayout(templateLayoutDoc, targetDoc) || !targetDoc) return templateLayoutDoc; const templateField = StrCast(templateLayoutDoc.isTemplateForField); // the field that the template renders @@ -475,9 +481,10 @@ 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 params = templateParams?.match(/\(([a-zA-Z0-9_-]*)\)/)?.[1].replace("()", "") || ""; + const args = templateArgs?.match(/\(([a-zA-Z0-9_-]*)\)/)?.[1].replace("()", "") || ""; + const params = args.split("=").length > 1 ? args.split("=")[0] : "PARAMS"; const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc); - const expandedLayoutFieldKey = (templateField || layoutFielddKey) + "-layout[" + templateLayoutDoc[Id] + params + "]"; + const expandedLayoutFieldKey = (templateField || layoutFielddKey) + "-layout[" + templateLayoutDoc[Id] + args + "]"; let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey]; if (templateLayoutDoc.resolvedDataDoc instanceof Promise) { expandedTemplateLayout = undefined; @@ -487,10 +494,10 @@ export namespace Doc { setTimeout(action(() => { if (!targetDoc[expandedLayoutFieldKey]) { const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]"); - newLayoutDoc["params"] = params; + // the template's arguments are stored in params which is derefenced to find + // the actual field key where the parameterized template data is stored. + newLayoutDoc[params] = args; newLayoutDoc.expandedTemplate = targetDoc; - // the template's parameters are stored in params which are derefenced to find - // the actual field key where the template data is stored. Currently this is only used in RichTextSchema's docView targetDoc[expandedLayoutFieldKey] = newLayoutDoc; const dataDoc = Doc.GetProto(targetDoc); newLayoutDoc.resolvedDataDoc = dataDoc; @@ -512,7 +519,7 @@ export namespace Doc { } 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, "(" + StrCast(containerDoc["params"]) + ")"), data: resolvedDataDoc }; + return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc, "(" + StrCast(containerDoc["PARAMS"]) + ")"), data: resolvedDataDoc }; } export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc { diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index 606f55b7c..954c22a8d 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -7,6 +7,7 @@ import { Doc, Field } from "../new_fields/Doc"; import { Plugins } from "./util"; import { computedFn } from "mobx-utils"; import { ProxyField } from "./Proxy"; +import { Cast } from "./Types"; function optional(propSchema: PropSchema) { return custom(value => { @@ -106,7 +107,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, source: Doc.name, _last_: "any", ...params }, + params: { this: Doc.name, self: Doc.name, _last_: "any", ...params }, typecheck: false, editable: true, addReturn: addReturn, @@ -130,7 +131,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({ source: doc.expandedTemplate || doc, this: doc, _last_: this._lastComputedResult }, console.log).result); + value = computedFn((doc: Doc) => this._lastComputedResult = this.script.run({ this: doc, self: Cast(doc.expandedTemplate, Doc, null) || 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; |