aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts14
-rw-r--r--src/client/util/CurrentUserUtils.ts88
-rw-r--r--src/client/views/DocumentButtonBar.tsx15
-rw-r--r--src/client/views/ScriptBox.tsx134
-rw-r--r--src/client/views/TemplateMenu.tsx98
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.scss23
-rw-r--r--src/client/views/nodes/DocumentView.tsx22
-rw-r--r--src/client/views/nodes/FieldView.tsx5
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx85
-rw-r--r--src/client/views/nodes/button/FontIconBox.tsx6
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx8
-rw-r--r--src/fields/ScriptField.ts11
13 files changed, 259 insertions, 252 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 51a9283f4..64d26e425 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -264,12 +264,6 @@ export class DocumentOptions {
baseProto?: boolean; // is this a base prototoype
dontRegisterView?: boolean;
lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document. see PresBox.
- 'onDoubleClick-rawScript'?: string; // onDoubleClick script in raw text form
- 'onChildDoubleClick-rawScript'?: string; // onChildDoubleClick script in raw text form
- 'onChildClick-rawScript'?: string; // on ChildClick script in raw text form
- 'onClick-rawScript'?: string; // onClick script in raw text form
- 'onCheckedClick-rawScript'?: string; // onChecked script in raw text form
- 'onCheckedClick-params'?: List<string>; // parameter list for onChecked treeview functions
columnHeaders?: List<SchemaHeaderField>; // headers for stacking views
schemaHeaders?: List<SchemaHeaderField>; // headers for schema view
clipWidth?: number; // percent transition from before to after in comparisonBox
@@ -1065,7 +1059,7 @@ export namespace Docs {
}
export function ButtonDocument(options?: DocumentOptions) {
- return InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}), 'onClick-rawScript': '-script-' });
+ return InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}) });
}
export function SliderDocument(options?: DocumentOptions) {
@@ -1356,7 +1350,11 @@ export namespace DocUtils {
scripts &&
Object.keys(scripts).map(key => {
if (ScriptCast(doc[key])?.script.originalScript !== scripts[key] && scripts[key]) {
- doc[key] = ScriptField.MakeScript(scripts[key], { dragData: DragManager.DocumentDragData.name, value: 'any', scriptContext: 'any', documentView: Doc.name }, { _readOnly_: true });
+ doc[key] = ScriptField.MakeScript(
+ scripts[key],
+ { dragData: DragManager.DocumentDragData.name, value: 'any', scriptContext: 'any', thisContainer: Doc.name, documentView: Doc.name, heading: Doc.name, checked: 'boolean', containingTreeView: Doc.name },
+ { _readOnly_: true }
+ );
}
});
funcs &&
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index ce32595d4..f55ed6e72 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -97,6 +97,45 @@ export class CurrentUserUtils {
return DocUtils.AssignScripts(DocUtils.AssignOpts(tempDocs, reqdOpts, requiredTypes) ?? Docs.Create.MasonryDocument(requiredTypes, reqdOpts), reqdScripts, reqdFuncs);
}
+ /// Initializes templates for editing click funcs of a document
+ static setupChildClickEditors(doc: Doc, field = "clickFuncs-child") {
+ const tempClicks = DocCast(doc[field]);
+ const reqdClickOpts:DocumentOptions = {_width: 300, _height:200, system: true};
+ const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [
+ { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self])))"},
+ { opts: { title: "Open Detail On Right", targetScriptKey: "onChildDoubleClick"}, script: "openOnRight(self.doubleClickView)"}];
+ const reqdClickList = reqdTempOpts.map(opts => {
+ const allOpts = {...reqdClickOpts, ...opts.opts};
+ const clickDoc = tempClicks ? DocListCast(tempClicks.data).find(doc => doc.title === opts.opts.title): undefined;
+ return DocUtils.AssignOpts(clickDoc, allOpts) ?? Docs.Create.ScriptingDocument(ScriptField.MakeScript(opts.script,allOpts));
+ });
+
+ const reqdOpts:DocumentOptions = { title: "child click editors", _height:75, system: true};
+ return DocUtils.AssignOpts(tempClicks, reqdOpts, reqdClickList) ?? (doc[field] = Docs.Create.TreeDocument(reqdClickList, reqdOpts));
+ }
+
+ /// Initializes templates for editing click funcs of a document
+ static setupClickEditorTemplates(doc: Doc, field = "template-clickFuncs") {
+ const tempClicks = DocCast(doc[field]);
+ const reqdClickOpts:DocumentOptions = { _width: 300, _height:200, system: true};
+ const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [
+ { opts: { title: "onClick"}, script: "console.log( 'click')"},
+ { opts: { title: "onDoubleClick"}, script: "console.log( 'double click')"},
+ { opts: { title: "onChildClick"}, script: "console.log( 'child click')"},
+ { opts: { title: "onChildDoubleClick"}, script: "console.log( 'child double click')"},
+ { opts: { title: "onCheckedClick"}, script: "console.log( heading, checked, containingTreeView)"},
+ ];
+ const reqdClickList = reqdTempOpts.map(opts => {
+ const allOpts = {...reqdClickOpts, ...opts.opts};
+ const clickDoc = tempClicks ? DocListCast(tempClicks.data).find(doc => doc.title === opts.opts.title): undefined;
+ return DocUtils.AssignOpts(clickDoc, allOpts) ?? MakeTemplate(Docs.Create.ScriptingDocument(ScriptField.MakeScript(opts.script, {heading:Doc.name, checked:"boolean", containingTreeView:Doc.name}), allOpts), true, opts.opts.title);
+ });
+
+ const reqdOpts:DocumentOptions = {title: "click editor templates", _height:75, system: true};
+ return DocUtils.AssignOpts(tempClicks, reqdOpts, reqdClickList) ?? (doc[field] = Docs.Create.TreeDocument(reqdClickList, reqdOpts));
+ }
+
+
/// Initializes templates that can be applied to notes
static setupNoteTemplates(doc: Doc, field="template-notes") {
const tempNotes = DocCast(doc[field]);
@@ -105,7 +144,7 @@ export class CurrentUserUtils {
{ noteType: "Idea", backgroundColor: "pink", icon: "lightbulb" },
{ noteType: "Topic", backgroundColor: "lightblue", icon: "book-open" }];
const reqdNoteList = reqdTempOpts.map(opts => {
- const reqdOpts = {...opts, title: "text", system: true};
+ const reqdOpts = {...opts, title: "text", width:200, system: true};
const noteType = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.noteType === opts.noteType): undefined;
return DocUtils.AssignOpts(noteType, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts), true, opts.noteType??"Note");
});
@@ -118,10 +157,10 @@ export class CurrentUserUtils {
static setupDocTemplates(doc: Doc, field="myTemplates") {
DocUtils.AssignDocField(doc, "presElement", opts => Docs.Create.PresElementBoxDocument(opts), { title: "pres element template", type: DocumentType.PRESELEMENT, _fitWidth: true, _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data"});
const templates = [
- DocCast(doc.presElement),
CurrentUserUtils.setupNoteTemplates(doc),
CurrentUserUtils.setupClickEditorTemplates(doc)
];
+ CurrentUserUtils.setupChildClickEditors(doc)
const reqdOpts = { title: "template layouts", _xMargin: 0, system: true, };
const reqdScripts = { dropConverter: "convertToButtons(dragData)" };
return DocUtils.AssignDocField(doc, field, (opts,items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, templates, reqdScripts);
@@ -748,51 +787,6 @@ export class CurrentUserUtils {
DocUtils.AssignDocField(myImports, "buttonMenuDoc", (opts) => Docs.Create.FontIconDocument(opts), reqdBtnOpts, undefined, { onClick: "importDocument()" });
return myImports;
}
-
- static setupClickEditorTemplates(doc: Doc) {
- if (doc["clickFuncs-child"] === undefined) {
- // to use this function, select it from the context menu of a collection. then edit the onChildClick script. Add two Doc variables: 'target' and 'thisContainer', then assign 'target' to some target collection. After that, clicking on any document in the initial collection will open it in the target
- const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript(
- "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self]))) ",
- { thisContainer: Doc.name }), {
- title: "Click to open in target", _width: 300, _height: 200,
- targetScriptKey: "onChildClick", system: true
- });
-
- const openDetail = Docs.Create.ScriptingDocument(ScriptField.MakeScript( "openOnRight(self.doubleClickView)", {}),
- { title: "Double click to open doubleClickView", _width: 300, _height: 200, targetScriptKey: "onChildDoubleClick", system: true });
-
- doc["clickFuncs-child"] = Docs.Create.TreeDocument([openInTarget, openDetail], { title: "on Child Click function templates", system: true });
- }
-
- if (doc.clickFuncs === undefined) {
- const onClick = Docs.Create.ScriptingDocument(undefined, {
- title: "onClick", "onClick-rawScript": "console.log('click')",
- isTemplateDoc: true, isTemplateForField: "onClick", _width: 300, _height: 200, system: true
- }, "onClick");
- const onChildClick = Docs.Create.ScriptingDocument(undefined, {
- title: "onChildClick", "onChildClick-rawScript": "console.log('child click')",
- isTemplateDoc: true, isTemplateForField: "onChildClick", _width: 300, _height: 200, system: true
- }, "onChildClick");
- const onDoubleClick = Docs.Create.ScriptingDocument(undefined, {
- title: "onDoubleClick", "onDoubleClick-rawScript": "console.log('double click')",
- isTemplateDoc: true, isTemplateForField: "onDoubleClick", _width: 300, _height: 200, system: true
- }, "onDoubleClick");
- const onChildDoubleClick = Docs.Create.ScriptingDocument(undefined, {
- title: "onChildDoubleClick", "onChildDoubleClick-rawScript": "console.log('child double click')",
- isTemplateDoc: true, isTemplateForField: "onChildDoubleClick", _width: 300, _height: 200, system: true
- }, "onChildDoubleClick");
- const onCheckedClick = Docs.Create.ScriptingDocument(undefined, {
- title: "onCheckedClick", "onCheckedClick-rawScript": "console.log(heading + checked + containingTreeView)",
- "onCheckedClick-params": new List<string>(["heading", "checked", "containingTreeView"]), isTemplateDoc: true,
- isTemplateForField: "onCheckedClick", _width: 300, _height: 200, system: true
- }, "onCheckedClick");
- doc.clickFuncs = Docs.Create.TreeDocument([onClick, onChildClick, onDoubleClick, onCheckedClick], { title: "onClick funcs", system: true });
- }
-
- return doc.clickFuncs as Doc;
- }
-
/// Updates the UserDoc to have all required fields, docs, etc. No changes should need to be
/// written to the server if the code hasn't changed. However, choices need to be made for each Doc/field
/// whether to revert to "default" values, or to leave them as the user/system last set them.
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index bac51a11d..1d4056759 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -335,8 +335,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
);
}
@observable _aliasDown = false;
- onAliasButtonDown = action((e: React.PointerEvent): void => {
- this.props.views()[0]?.select(false);
+ onTemplateButton = action((e: React.PointerEvent): void => {
this._tooltipOpen = false;
setupMoveUpEvents(this, e, this.onAliasButtonMoved, emptyFunction, emptyFunction);
});
@@ -374,7 +373,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
</div>
)
}>
- <div className={'documentButtonBar-linkButton-empty'} ref={this._dragRef} onPointerDown={this.onAliasButtonDown}>
+ <div className={'documentButtonBar-linkButton-empty'} ref={this._dragRef} onPointerDown={this.onTemplateButton}>
{<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
</div>
</Flyout>
@@ -412,15 +411,15 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
<DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={false} />
</div>
) : null}
- {/*!Doc.UserDoc()["documentLinksButton-fullMenu"] ? (null) : <div className="documentButtonBar-button">
- {this.templateButton}
- </div>
- /*<div className="documentButtonBar-button">
+ {
+ Doc.noviceMode ? null : <div className="documentButtonBar-button">{this.templateButton}</div>
+ /*<div className="documentButtonBar-button">
{this.metadataButton}
</div>
<div className="documentButtonBar-button">
{this.contextButton}
- </div> */}
+ </div> */
+ }
{!SelectionManager.Views()?.some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>}
<div className="documentButtonBar-button">{this.pinButton}</div>
{!Doc.UserDoc()['documentLinksButton-fullMenu'] ? null : <div className="documentButtonBar-button">{this.shareButton}</div>}
diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx
index b7ea124b9..416162aeb 100644
--- a/src/client/views/ScriptBox.tsx
+++ b/src/client/views/ScriptBox.tsx
@@ -1,17 +1,16 @@
-import { action, observable } from "mobx";
-import { observer } from "mobx-react";
-import * as React from "react";
-import { Doc, Opt } from "../../fields/Doc";
-import { ScriptField } from "../../fields/ScriptField";
-import { ScriptCast } from "../../fields/Types";
-import { emptyFunction } from "../../Utils";
-import { DragManager } from "../util/DragManager";
-import { CompileScript } from "../util/Scripting";
-import { EditableView } from "./EditableView";
-import { DocumentIconContainer } from "./nodes/DocumentIcon";
-import { OverlayView } from "./OverlayView";
-import "./ScriptBox.scss";
-
+import { action, observable } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { Doc, Opt } from '../../fields/Doc';
+import { ScriptField } from '../../fields/ScriptField';
+import { ScriptCast } from '../../fields/Types';
+import { emptyFunction } from '../../Utils';
+import { DragManager } from '../util/DragManager';
+import { CompileScript } from '../util/Scripting';
+import { EditableView } from './EditableView';
+import { DocumentIconContainer } from './nodes/DocumentIcon';
+import { OverlayView } from './OverlayView';
+import './ScriptBox.scss';
export interface ScriptBoxProps {
onSave: (text: string, onError: (error: string) => void) => void;
@@ -28,53 +27,58 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
constructor(props: ScriptBoxProps) {
super(props);
- this._scriptText = props.initialText || "";
+ this._scriptText = props.initialText || '';
}
@action
onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
this._scriptText = e.target.value;
- }
+ };
@action
onError = (error: string) => {
- console.log("ScriptBox: " + error);
- }
+ console.log('ScriptBox: ' + error);
+ };
overlayDisposer?: () => void;
onFocus = () => {
this.overlayDisposer?.();
this.overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
- }
+ };
onBlur = () => {
this.overlayDisposer?.();
- }
+ };
render() {
- let onFocus: Opt<() => void> = undefined, onBlur: Opt<() => void> = undefined;
+ let onFocus: Opt<() => void> = undefined,
+ onBlur: Opt<() => void> = undefined;
if (this.props.showDocumentIcons) {
onFocus = this.onFocus;
onBlur = this.onBlur;
}
- const params = <EditableView
- contents={""}
- display={"block"}
- maxHeight={72}
- height={35}
- fontSize={28}
- GetValue={() => ""}
- SetValue={(value: string) => this.props.setParams && this.props.setParams(value.split(" ").filter(s => s !== " ")) ? true : true}
- />;
+ const params = <EditableView contents={''} display={'block'} maxHeight={72} height={35} fontSize={28} GetValue={() => ''} SetValue={(value: string) => (this.props.setParams?.(value.split(' ').filter(s => s !== ' ')) ? true : true)} />;
return (
<div className="scriptBox-outerDiv">
- <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
+ <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<textarea className="scriptBox-textarea" onChange={this.onChange} value={this._scriptText} onFocus={onFocus} onBlur={onBlur}></textarea>
- <div style={{ background: "beige" }} >{params}</div>
+ <div style={{ background: 'beige' }}>{params}</div>
</div>
<div className="scriptBox-toolbar">
- <button onClick={e => { this.props.onSave(this._scriptText, this.onError); e.stopPropagation(); }}>Save</button>
- <button onClick={e => { this.props.onCancel && this.props.onCancel(); e.stopPropagation(); }}>Cancel</button>
+ <button
+ onClick={e => {
+ this.props.onSave(this._scriptText, this.onError);
+ e.stopPropagation();
+ }}>
+ Save
+ </button>
+ <button
+ onClick={e => {
+ this.props.onCancel && this.props.onCancel();
+ e.stopPropagation();
+ }}>
+ Cancel
+ </button>
</div>
</div>
);
@@ -90,35 +94,43 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
// tslint:disable-next-line: no-unnecessary-callback-wrapper
const params: string[] = [];
const setParams = (p: string[]) => params.splice(0, params.length, ...p);
- const scriptingBox = <ScriptBox initialText={originalText} setParams={setParams} onCancel={overlayDisposer} onSave={(text, onError) => {
- if (!text) {
- Doc.GetProto(doc)[fieldKey] = undefined;
- } else {
- const script = CompileScript(text, {
- params: { this: Doc.name, ...contextParams },
- typecheck: false,
- editable: true,
- transformer: DocumentIconContainer.getTransformer()
- });
- if (!script.compiled) {
- onError(script.errors.map(error => error.messageText).join("\n"));
- return;
- }
+ const scriptingBox = (
+ <ScriptBox
+ initialText={originalText}
+ setParams={setParams}
+ onCancel={overlayDisposer}
+ onSave={(text, onError) => {
+ if (!text) {
+ Doc.GetProto(doc)[fieldKey] = undefined;
+ } else {
+ const script = CompileScript(text, {
+ params: { this: Doc.name, ...contextParams },
+ typecheck: false,
+ editable: true,
+ transformer: DocumentIconContainer.getTransformer(),
+ });
+ if (!script.compiled) {
+ onError(script.errors.map(error => error.messageText).join('\n'));
+ return;
+ }
- const div = document.createElement("div");
- div.style.width = "90";
- div.style.height = "20";
- div.style.background = "gray";
- div.style.position = "absolute";
- div.style.display = "inline-block";
- div.style.transform = `translate(${clientX}px, ${clientY}px)`;
- div.innerHTML = "button";
- params.length && DragManager.StartButtonDrag([div], text, doc.title + "-instance", {}, params, (button: Doc) => { }, clientX, clientY);
+ const div = document.createElement('div');
+ div.style.width = '90';
+ div.style.height = '20';
+ div.style.background = 'gray';
+ div.style.position = 'absolute';
+ div.style.display = 'inline-block';
+ div.style.transform = `translate(${clientX}px, ${clientY}px)`;
+ div.innerHTML = 'button';
+ params.length && DragManager.StartButtonDrag([div], text, doc.title + '-instance', {}, params, (button: Doc) => {}, clientX, clientY);
- Doc.GetProto(doc)[fieldKey] = new ScriptField(script);
- overlayDisposer();
- }
- }} showDocumentIcons />;
+ Doc.GetProto(doc)[fieldKey] = new ScriptField(script);
+ overlayDisposer();
+ }
+ }}
+ showDocumentIcons
+ />
+ );
overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title });
}
}
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 156513f47..863829a51 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -55,16 +55,12 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
@observable private _hidden: boolean = true;
toggleLayout = (e: React.ChangeEvent<HTMLInputElement>, layout: string): void => {
- this.props.docViews.map(dv => dv.switchViews(e.target.checked, layout));
+ this.props.docViews.map(dv => dv.switchViews(e.target.checked, layout, undefined, true));
};
toggleDefault = (e: React.ChangeEvent<HTMLInputElement>): void => {
this.props.docViews.map(dv => dv.switchViews(false, 'layout'));
};
- toggleAudio = (e: React.ChangeEvent<HTMLInputElement>): void => {
- this.props.docViews.map(dv => (dv.props.Document._showAudio = e.target.checked));
- };
-
@undoBatch
@action
toggleTemplate = (event: React.ChangeEvent<HTMLInputElement>, template: string): void => {
@@ -76,12 +72,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
this._hidden = !this._hidden;
};
- @undoBatch
- @action
- toggleChrome = (): void => {
- this.props.docViews.map(dv => Doc.Layout(dv.layoutDoc)).forEach(layout => (layout._chromeHidden = !layout._chromeHidden));
- };
-
// todo: add brushes to brushMap to save with a style name
onCustomKeypress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
@@ -95,13 +85,9 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
.map(key => runInAction(() => this._addedKeys.add(key.replace('layout_', ''))));
}
- return100 = () => 100;
+ return100 = () => 300;
@computed get scriptField() {
- const script = ScriptField.MakeScript(
- 'docs.map(d => switchView(d, this))',
- { this: Doc.name, heading: 'string', checked: 'string', containingTreeView: Doc.name, firstDoc: Doc.name },
- { docs: new List<Doc>(this.props.docViews.map(dv => dv.props.Document)) }
- );
+ const script = ScriptField.MakeScript('docs.map(d => switchView(d, this))', { this: Doc.name }, { docs: this.props.docViews.map(dv => dv.props.Document) as any });
return script ? () => script : undefined;
}
templateIsUsed = (selDoc: Doc, templateDoc: Doc) => {
@@ -113,13 +99,10 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
const firstDoc = this.props.docViews[0].props.Document;
const templateName = StrCast(firstDoc.layoutKey, 'layout').replace('layout_', '');
const noteTypes = DocListCast(Cast(Doc.UserDoc()['template-notes'], Doc, null)?.data);
- const addedTypes = Doc.noviceMode ? [] : DocListCast(Cast(Doc.UserDoc()['template-buttons'], Doc, null)?.data);
- const layout = Doc.Layout(firstDoc);
+ const addedTypes = DocListCast(Cast(Doc.UserDoc()['template-clickFuncs'], Doc, null)?.data);
const templateMenu: Array<JSX.Element> = [];
this.props.templates?.forEach((checked, template) => templateMenu.push(<TemplateToggle key={template} template={template} checked={checked} toggle={this.toggleTemplate} />));
- templateMenu.push(<OtherToggle key={'audio'} name={'Audio'} checked={firstDoc._showAudio ? true : false} toggle={this.toggleAudio} />);
templateMenu.push(<OtherToggle key={'default'} name={'Default'} checked={templateName === 'layout'} toggle={this.toggleDefault} />);
- !Doc.noviceMode && templateMenu.push(<OtherToggle key={'chrome'} name={'Chrome'} checked={!layout._chromeHidden} toggle={this.toggleChrome} />);
addedTypes.concat(noteTypes).map(template => (template.treeViewChecked = this.templateIsUsed(firstDoc, template)));
this._addedKeys &&
Array.from(this._addedKeys)
@@ -129,43 +112,42 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
<ul className="template-list" style={{ display: 'block' }}>
{Doc.noviceMode ? null : <input placeholder="+ layout" ref={this._customRef} onKeyPress={this.onCustomKeypress} />}
{templateMenu}
- {Doc.noviceMode ? null : (
- <CollectionTreeView
- Document={Doc.MyTemplates}
- CollectionView={undefined}
- ContainingCollectionDoc={undefined}
- ContainingCollectionView={undefined}
- styleProvider={DefaultStyleProvider}
- setHeight={returnFalse}
- docViewPath={returnEmptyDoclist}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- rootSelected={returnFalse}
- onCheckedClick={this.scriptField}
- onChildClick={this.scriptField}
- dropAction={undefined}
- isAnyChildContentActive={returnFalse}
- isContentActive={returnTrue}
- bringToFront={emptyFunction}
- focus={emptyFunction}
- whenChildContentsActiveChanged={emptyFunction}
- ScreenToLocalTransform={Transform.Identity}
- isSelected={returnFalse}
- pinToPres={emptyFunction}
- select={emptyFunction}
- renderDepth={1}
- addDocTab={returnFalse}
- PanelWidth={this.return100}
- PanelHeight={this.return100}
- treeViewHideHeaderFields={true}
- dontRegisterView={true}
- fieldKey={'data'}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- addDocument={returnFalse}
- />
- )}
+ <CollectionTreeView
+ Document={Doc.MyTemplates}
+ CollectionView={undefined}
+ ContainingCollectionDoc={undefined}
+ ContainingCollectionView={undefined}
+ styleProvider={DefaultStyleProvider}
+ setHeight={returnFalse}
+ docViewPath={returnEmptyDoclist}
+ docFilters={returnEmptyFilter}
+ docRangeFilters={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ rootSelected={returnFalse}
+ onCheckedClick={this.scriptField}
+ onChildClick={this.scriptField}
+ dropAction={undefined}
+ isAnyChildContentActive={returnFalse}
+ isContentActive={returnTrue}
+ bringToFront={emptyFunction}
+ focus={emptyFunction}
+ whenChildContentsActiveChanged={emptyFunction}
+ ScreenToLocalTransform={Transform.Identity}
+ isSelected={returnFalse}
+ pinToPres={emptyFunction}
+ select={emptyFunction}
+ renderDepth={1}
+ addDocTab={returnFalse}
+ PanelWidth={this.return100}
+ PanelHeight={this.return100}
+ treeViewHideHeaderFields={true}
+ treeViewHideTitle={true}
+ dontRegisterView={true}
+ fieldKey={'data'}
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ addDocument={returnFalse}
+ />
</ul>
);
}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 6850fb23a..a6c367ff7 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -296,7 +296,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeHeight(doc)) ? height : undefined}
dontCenter={this.props.childIgnoreNativeSize ? 'xy' : undefined}
- dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)}
+ dontRegisterView={BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)}
rootSelected={this.rootSelected}
showTitle={this.props.childShowTitle}
dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType}
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 6a1bfa406..c02692bfb 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -1,4 +1,4 @@
-@import "../global/globalCssVariables";
+@import '../global/globalCssVariables';
.documentView-effectsWrapper {
border-radius: inherit;
@@ -24,7 +24,7 @@
width: 100%;
height: 100%;
border-radius: inherit;
- transition: outline .3s linear;
+ transition: outline 0.3s linear;
cursor: grab;
// background: $white; //overflow: hidden;
@@ -62,7 +62,7 @@
.documentView-audioBackground {
display: inline-block;
- width: 10%;
+ width: 25px;
height: 25;
position: absolute;
top: 10px;
@@ -88,7 +88,7 @@
width: 100%;
overflow: hidden;
- >.documentView-node {
+ > .documentView-node {
position: absolute;
}
}
@@ -158,7 +158,7 @@
top: 0;
width: 100%;
height: 14;
- background: rgba(0, 0, 0, .4);
+ background: rgba(0, 0, 0, 0.4);
text-align: center;
text-overflow: ellipsis;
white-space: pre;
@@ -187,19 +187,18 @@
transition: opacity 0.5s;
}
}
-
}
.documentView-node:hover,
.documentView-node-topmost:hover {
- >.documentView-styleWrapper {
- >.documentView-titleWrapper-hover {
+ > .documentView-styleWrapper {
+ > .documentView-titleWrapper-hover {
display: inline-block;
}
}
- >.documentView-styleWrapper {
- >.documentView-captionWrapper {
+ > .documentView-styleWrapper {
+ > .documentView-captionWrapper {
opacity: 1;
}
}
@@ -225,6 +224,6 @@
.documentView-node:first-child {
position: relative;
- background: "#B59B66"; //$white;
+ background: '#B59B66'; //$white;
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8847c0c6a..edaa40bad 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -177,6 +177,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps {
dontScaleFilter?: (doc: Doc) => boolean; // decides whether a document can be scaled to fit its container vs native size with scrolling
NativeWidth?: () => number;
NativeHeight?: () => number;
+ NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps
LayoutTemplate?: () => Opt<Doc>;
contextMenuItems?: () => { script: ScriptField; filter?: ScriptField; label: string; icon: string }[];
onClick?: () => ScriptField;
@@ -191,7 +192,6 @@ export interface DocumentViewProps extends DocumentViewSharedProps {
export interface DocumentViewInternalProps extends DocumentViewProps {
NativeWidth: () => number;
NativeHeight: () => number;
- NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps
isSelected: (outsideReaction?: boolean) => boolean;
select: (ctrlPressed: boolean) => void;
DocumentView: () => DocumentView;
@@ -716,7 +716,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
this.Document.followLinkLocation = location;
} else if (this.Document._isLinkButton && this.onClickHandler) {
this.Document._isLinkButton = false;
- this.Document['onClick-rawScript'] = this.dataDoc['onClick-rawScript'] = this.dataDoc.onClick = this.Document.onClick = this.layoutDoc.onClick = undefined;
+ this.dataDoc.onClick = this.Document.onClick = this.layoutDoc.onClick = undefined;
}
};
@undoBatch
@@ -750,7 +750,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
};
@undoBatch deleteClicked = () => this.props.removeDocument?.(this.props.Document);
- @undoBatch setToggleDetail = () => (this.Document.onClick = ScriptField.MakeScript(`toggleDetail(documentView, "${StrCast(this.Document.layoutKey).replace('layout_', '')}")`, { documentView: 'any' }));
+ @undoBatch setToggleDetail = () =>
+ (this.Document.onClick = ScriptField.MakeScript(
+ `toggleDetail(documentView, "${StrCast(this.Document.layoutKey)
+ .replace('layout_', '')
+ .replace(/^layout$/, 'detail')}")`,
+ { documentView: 'any' }
+ ));
@undoBatch
@action
@@ -1538,11 +1544,15 @@ export class DocumentView extends React.Component<DocumentViewProps> {
Doc.setNativeView(this.props.Document);
custom && DocUtils.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
};
- switchViews = action((custom: boolean, view: string, finished?: () => void) => {
+ switchViews = action((custom: boolean, view: string, finished?: () => void, useExistingLayout = false) => {
this.docView && (this.docView._animateScalingTo = 0.1); // shrink doc
setTimeout(
action(() => {
- this.setCustomView(custom, view);
+ if (useExistingLayout && custom && this.rootDoc['layout_' + view]) {
+ this.rootDoc.layoutKey = 'layout_' + view;
+ } else {
+ this.setCustomView(custom, view);
+ }
this.docView && (this.docView._animateScalingTo = 1); // expand it
setTimeout(
action(() => {
@@ -1646,7 +1656,7 @@ ScriptingGlobals.add(function deiconifyView(documentView: DocumentView) {
ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuffix: string) {
if (dv.Document.layoutKey === 'layout_' + detailLayoutKeySuffix) dv.switchViews(false, 'layout');
- else dv.switchViews(true, detailLayoutKeySuffix);
+ else dv.switchViews(true, detailLayoutKeySuffix, undefined, true);
});
ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc) {
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 5a6c49809..dd2c13391 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -4,10 +4,9 @@ import { observer } from 'mobx-react';
import { DateField } from '../../../fields/DateField';
import { Doc, Field, FieldResult, Opt } from '../../../fields/Doc';
import { List } from '../../../fields/List';
-import { WebField } from '../../../fields/URLField';
-import { DocumentView, DocumentViewSharedProps } from './DocumentView';
import { ScriptField } from '../../../fields/ScriptField';
-import { RecordingBox } from './RecordingBox';
+import { WebField } from '../../../fields/URLField';
+import { DocumentViewSharedProps } from './DocumentView';
//
// these properties get assigned through the render() method of the DocumentView when it creates this node.
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index 05ff40f22..1c9b0bc0e 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -6,7 +6,7 @@ import { Doc } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
import { returnEmptyString } from '../../../Utils';
import { DragManager } from '../../util/DragManager';
@@ -60,6 +60,14 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
constructor(props: any) {
super(props);
+ if (!this.compileParams.length) {
+ const params = ScriptCast(this.rootDoc[this.props.fieldKey])?.script.options.params as { [key: string]: any };
+ if (params) {
+ this.compileParams = Array.from(Object.keys(params))
+ .filter(p => !p.startsWith('_'))
+ .map(key => key + ':' + params[key]);
+ }
+ }
}
// vars included in fields that store parameters types and names and the script itself
@@ -70,30 +78,30 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
return this.compileParams.map(p => p.split(':')[1].trim());
}
@computed({ keepAlive: true }) get rawScript() {
- return StrCast(this.dataDoc[this.props.fieldKey + '-rawScript'], '');
+ return ScriptCast(this.rootDoc[this.fieldKey])?.script.originalScript ?? '';
}
@computed({ keepAlive: true }) get functionName() {
- return StrCast(this.dataDoc[this.props.fieldKey + '-functionName'], '');
+ return StrCast(this.rootDoc[this.props.fieldKey + '-functionName'], '');
}
@computed({ keepAlive: true }) get functionDescription() {
- return StrCast(this.dataDoc[this.props.fieldKey + '-functionDescription'], '');
+ return StrCast(this.rootDoc[this.props.fieldKey + '-functionDescription'], '');
}
@computed({ keepAlive: true }) get compileParams() {
- return Cast(this.dataDoc[this.props.fieldKey + '-params'], listSpec('string'), []);
+ return Cast(this.rootDoc[this.props.fieldKey + '-params'], listSpec('string'), []);
}
set rawScript(value) {
- this.dataDoc[this.props.fieldKey + '-rawScript'] = value;
+ Doc.SetInPlace(this.rootDoc, this.props.fieldKey, new ScriptField(undefined, undefined, value), true);
}
set functionName(value) {
- this.dataDoc[this.props.fieldKey + '-functionName'] = value;
+ Doc.SetInPlace(this.rootDoc, this.props.fieldKey + '-functionName', value, true);
}
set functionDescription(value) {
- this.dataDoc[this.props.fieldKey + '-functionDescription'] = value;
+ Doc.SetInPlace(this.rootDoc, this.props.fieldKey + '-functionDescription', value, true);
}
set compileParams(value) {
- this.dataDoc[this.props.fieldKey + '-params'] = new List<string>(value);
+ Doc.SetInPlace(this.rootDoc, this.props.fieldKey + '-params', new List<string>(value), true);
}
getValue(result: any, descrip: boolean) {
@@ -107,8 +115,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
@action
componentDidMount() {
- this.rawScript = ScriptCast(this.dataDoc[this.props.fieldKey])?.script?.originalScript ?? this.rawScript;
-
+ this.rawText = this.rawScript;
const observer = new _global.ResizeObserver(
action((entries: any) => {
const area = document.querySelector('textarea');
@@ -171,13 +178,13 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
const params: ScriptParam = {};
this.compileParams.forEach(p => (params[p.split(':')[0].trim()] = p.split(':')[1].trim()));
- const result = CompileScript(this.rawScript, {
+ const result = CompileScript(this.rawText, {
editable: true,
transformer: DocumentIconContainer.getTransformer(),
params,
typecheck: false,
});
- this.dataDoc[this.fieldKey] = result.compiled ? new ScriptField(result) : undefined;
+ Doc.SetInPlace(this.rootDoc, this.fieldKey, result.compiled ? new ScriptField(result, undefined, this.rawText) : new ScriptField(undefined, undefined, this.rawText), true);
this.onError(result.compiled ? undefined : result.errors);
return result.compiled;
};
@@ -187,9 +194,9 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
onRun = () => {
if (this.onCompile()) {
const bindings: { [name: string]: any } = {};
- this.paramsNames.forEach(key => (bindings[key] = this.dataDoc[key]));
+ this.paramsNames.forEach(key => (bindings[key] = this.rootDoc[key]));
// binds vars so user doesnt have to refer to everything as self.<var>
- ScriptCast(this.dataDoc[this.fieldKey], null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError);
+ ScriptCast(this.rootDoc[this.fieldKey], null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError);
}
};
@@ -257,14 +264,14 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
// sets field of the corresponding field key (param name) to be dropped document
@action
onDrop = (e: Event, de: DragManager.DropEvent, fieldKey: string) => {
- this.dataDoc[fieldKey] = de.complete.docDragData?.droppedDocuments[0];
+ Doc.SetInPlace(this.rootDoc, fieldKey, de.complete.docDragData?.droppedDocuments[0], true);
e.stopPropagation();
};
// deletes a param from all areas in which it is stored
@action
onDelete = (num: number) => {
- this.dataDoc[this.paramsNames[num]] = undefined;
+ Doc.SetInPlace(this.rootDoc, this.paramsNames[num], undefined, true);
this.compileParams.splice(num, 1);
return true;
};
@@ -274,7 +281,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
viewChanged = (e: React.ChangeEvent, name: string) => {
//@ts-ignore
const val = e.target.selectedOptions[0].value;
- this.dataDoc[name] = val[0] === 'S' ? val.substring(1) : val[0] === 'N' ? parseInt(val.substring(1)) : val.substring(1) === 'true';
+ Doc.SetInPlace(this.rootDoc, name, val[0] === 'S' ? val.substring(1) : val[0] === 'N' ? parseInt(val.substring(1)) : val.substring(1) === 'true', true);
};
// creates a copy of the script document
@@ -330,8 +337,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
maxHeight={72}
height={35}
fontSize={14}
- contents={this.dataDoc[parameter]?.title ?? 'undefined'}
- GetValue={() => this.dataDoc[parameter]?.title ?? 'undefined'}
+ contents={StrCast(DocCast(this.rootDoc[parameter])?.title, 'undefined')}
+ GetValue={() => StrCast(DocCast(this.rootDoc[parameter])?.title, 'undefined')}
SetValue={action((value: string) => {
const script = CompileScript(value, {
addReturn: true,
@@ -341,7 +348,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
const results = script.compiled && script.run();
if (results && results.success) {
this._errorMessage = '';
- this.dataDoc[parameter] = results.result;
+ Doc.SetInPlace(this.rootDoc, parameter, results.result, true);
return true;
}
this._errorMessage = 'invalid document';
@@ -354,7 +361,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
// rendering when a string's value can be set in applied UI
renderBasicType(parameter: string, isNum: boolean) {
- const strVal = isNum ? NumCast(this.dataDoc[parameter]).toString() : StrCast(this.dataDoc[parameter]);
+ const strVal = isNum ? NumCast(this.rootDoc[parameter]).toString() : StrCast(this.rootDoc[parameter]);
return (
<div className="scriptingBox-paramInputs" style={{ overflowY: 'hidden' }}>
<EditableView
@@ -368,7 +375,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
const setValue = isNum ? parseInt(value) : value;
if (setValue !== undefined && setValue !== ' ') {
this._errorMessage = '';
- this.dataDoc[parameter] = setValue;
+ Doc.SetInPlace(this.rootDoc, parameter, setValue, true);
return true;
}
this._errorMessage = 'invalid input';
@@ -389,7 +396,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
className="scriptingBox-viewPicker"
onPointerDown={e => e.stopPropagation()}
onChange={e => this.viewChanged(e, parameter)}
- value={typeof this.dataDoc[parameter] === 'string' ? 'S' + StrCast(this.dataDoc[parameter]) : typeof this.dataDoc[parameter] === 'number' ? 'N' + NumCast(this.dataDoc[parameter]) : 'B' + BoolCast(this.dataDoc[parameter])}>
+ value={typeof this.rootDoc[parameter] === 'string' ? 'S' + StrCast(this.rootDoc[parameter]) : typeof this.rootDoc[parameter] === 'number' ? 'N' + NumCast(this.rootDoc[parameter]) : 'B' + BoolCast(this.rootDoc[parameter])}>
{types.map(type => (
<option className="scriptingBox-viewOption" value={(typeof type === 'string' ? 'S' : typeof type === 'number' ? 'N' : 'B') + type}>
{' '}
@@ -442,7 +449,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
@action
handleFunc(pos: number) {
- const scriptString = this.rawScript.slice(0, pos - 2);
+ const scriptString = this.rawText.slice(0, pos - 2);
this._currWord = scriptString.split(' ')[scriptString.split(' ').length - 1];
this._suggestions = [StrCast(this._scriptingParams[this._currWord])];
return this._suggestions;
@@ -474,7 +481,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
}
getSuggestedParams(pos: number) {
- const firstScript = this.rawScript.slice(0, pos);
+ const firstScript = this.rawText.slice(0, pos);
const indexP = firstScript.lastIndexOf('.');
const indexS = firstScript.lastIndexOf(' ');
const func = firstScript.slice((indexP > indexS ? indexP : indexS) + 1, firstScript.length + 1);
@@ -494,8 +501,9 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
@action
keyHandler(e: any, pos: number) {
+ e.stopPropagation();
if (this._lastChar === 'Enter') {
- this.rawScript = this.rawScript + ' ';
+ this.rawText = this.rawText + ' ';
}
if (e.key === '(') {
this.suggestionPos();
@@ -504,7 +512,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
this._scriptSuggestedParams = this.getSuggestedParams(pos);
if (this._scriptParamsText !== undefined && this._scriptParamsText.length > 0) {
- if (this.rawScript[pos - 2] !== '(') {
+ if (this.rawText[pos - 2] !== '(') {
this._paramSuggestion = true;
}
}
@@ -515,22 +523,22 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
if (this._lastChar === '(') {
this._paramSuggestion = false;
} else if (this._lastChar === ')') {
- if (this.rawScript.slice(0, this.rawScript.length - 1).split('(').length - 1 > this.rawScript.slice(0, this.rawScript.length - 1).split(')').length - 1) {
+ if (this.rawText.slice(0, this.rawText.length - 1).split('(').length - 1 > this.rawText.slice(0, this.rawText.length - 1).split(')').length - 1) {
if (this._scriptParamsText.length > 0) {
this._paramSuggestion = true;
}
}
}
- } else if (this.rawScript.split('(').length - 1 <= this.rawScript.split(')').length - 1) {
+ } else if (this.rawText.split('(').length - 1 <= this.rawText.split(')').length - 1) {
this._paramSuggestion = false;
}
}
- this._lastChar = e.key === 'Backspace' ? this.rawScript[this.rawScript.length - 2] : e.key;
+ this._lastChar = e.key === 'Backspace' ? this.rawText[this.rawText.length - 2] : e.key;
if (this._paramSuggestion) {
const parameters = this._scriptParamsText.split(',');
- const index = this.rawScript.lastIndexOf('(');
- const enteredParams = this.rawScript.slice(index, this.rawScript.length);
+ const index = this.rawText.lastIndexOf('(');
+ const enteredParams = this.rawText.slice(index, this.rawText.length);
const splitEntered = enteredParams.split(',');
const numEntered = splitEntered.length;
@@ -564,15 +572,16 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
handlePosChange(number: any) {
this._caretPos = number;
if (this._caretPos === 0) {
- this.rawScript = ' ' + this.rawScript;
+ this.rawText = ' ' + this.rawText;
} else if (this._spaced) {
this._spaced = false;
- if (this.rawScript[this._caretPos - 1] === ' ') {
- this.rawScript = this.rawScript.slice(0, this._caretPos - 1) + this.rawScript.slice(this._caretPos, this.rawScript.length);
+ if (this.rawText[this._caretPos - 1] === ' ') {
+ this.rawText = this.rawText.slice(0, this._caretPos - 1) + this.rawText.slice(this._caretPos, this.rawText.length);
}
}
}
+ @observable rawText: string = '';
@computed({ keepAlive: true }) get renderScriptingBox() {
TraceMobx();
return (
@@ -583,8 +592,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
placeholder="write your script here"
onFocus={this.onFocus}
onBlur={() => this._overlayDisposer?.()}
- onChange={(e: any) => (this.rawScript = e.target.value)}
- value={this.rawScript}
+ onChange={action((e: any) => (this.rawText = e.target.value))}
+ value={this.rawText}
movePopupAsYouType={true}
loadingComponent={() => <span>Loading</span>}
trigger={{
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 5e279f984..78ef85ec2 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -579,11 +579,11 @@ ScriptingGlobals.add(function setView(view: string) {
// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
- const selected = SelectionManager.Docs().lastElement();
+ const selected = SelectionManager.Views().lastElement();
if (checkResult) {
- return selected?._backgroundColor ?? 'transparent';
+ return selected?.props.Document._backgroundColor ?? 'transparent';
}
- if (selected) selected._backgroundColor = color;
+ if (selected) selected.props.Document._backgroundColor = color;
});
// toggle: Set overlay status of selected document
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index eb87d11a4..b8ee89ef2 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -398,7 +398,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
updateTitle = () => {
- const title = StrCast(this.dataDoc.title);
+ const title = StrCast(this.dataDoc.title, Cast(this.dataDoc.title, RichTextField, null)?.Text);
if (
!this.props.dontRegisterView && // (this.props.Document.isTemplateForField === "text" || !this.props.Document.isTemplateForField) && // only update the title if the data document's data field is changing
(title.startsWith('-') || title.startsWith('@')) &&
@@ -1000,7 +1000,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
// set the document height when one of the component heights changes and autoHeight is on
() => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, autoHeight: this.autoHeight, marginsHeight: this.autoHeightMargins }),
({ sidebarHeight, textHeight, autoHeight, marginsHeight }) => {
- autoHeight && this.props.setHeight?.(this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight)));
+ const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight));
+ autoHeight && newHeight && this.props.setHeight?.(newHeight);
},
{ fireImmediately: true }
);
@@ -1768,7 +1769,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
removeDocument={this.removeDocument}
/>
) : (
- <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.props.DocumentView?.()!), true)}>
+ <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.props.DocumentView?.()!, false), true)}>
+ //@ts-ignore
<ComponentTag
{...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
NativeWidth={returnZero}
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index 2b4b1ef4c..68fb45987 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -81,6 +81,8 @@ async function deserializeScript(script: ScriptField) {
@scriptingGlobal
@Deserializable('script', deserializeScript)
export class ScriptField extends ObjectField {
+ @serializable
+ readonly rawscript: string | undefined;
@serializable(object(scriptSchema))
readonly script: CompiledScript;
@serializable(object(scriptSchema))
@@ -94,15 +96,16 @@ export class ScriptField extends ObjectField {
return this._scriptFieldCache.get(field);
}
- constructor(script: CompiledScript, setterscript?: CompiledScript) {
+ constructor(script: CompiledScript | undefined, setterscript?: CompiledScript, rawscript?: string) {
super();
const captured = script?.options.capturedVariables;
if (captured) {
this.captures = new List<string>(Object.keys(captured).map(key => key + ':' + (captured[key] instanceof Doc ? 'ID->' + (captured[key] as Doc)[Id] : captured[key].toString())));
}
+ this.rawscript = rawscript;
this.setterscript = setterscript;
- this.script = script;
+ this.script = script ?? (CompileScript('false') as CompiledScript);
}
// init(callback: (res: Field) => any) {
@@ -127,7 +130,7 @@ export class ScriptField extends ObjectField {
// }
[Copy](): ObjectField {
- return new ScriptField(this.script, this.setterscript);
+ return new ScriptField(this.script, this.setterscript, this.rawscript);
}
toString() {
return `${this.script.originalScript} + ${this.setterscript?.originalScript}`;
@@ -175,7 +178,7 @@ export class ComputedField extends ScriptField {
_valueOutsideReaction = (doc: Doc) => (this._lastComputedResult = this.script.run({ this: doc, self: Cast(doc.rootDocument, Doc, null) || doc, _last_: this._lastComputedResult, _readOnly_: true }, console.log).result);
[Copy](): ObjectField {
- return new ComputedField(this.script, this.setterscript);
+ return new ComputedField(this.script, this.setterscript, this.rawscript);
}
public static MakeScript(script: string, params: object = {}) {