aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbob <bcz@cs.brown.edu>2019-09-11 15:45:37 -0400
committerbob <bcz@cs.brown.edu>2019-09-11 15:45:37 -0400
commitd7d73856ed405cef01b4cf727ca56f4d9a31e894 (patch)
tree6ee45e9b15e44238ba758f0933e9f0fee857c5b2
parent71594c0e64d2559f2a72bcbc5faee1db78eecfb8 (diff)
cleaned up ScriptBox EditScript's restructured menus for dealing with onClicks... exposed more layout paramters for EditableViews.
-rw-r--r--src/client/views/ContextMenuItem.tsx4
-rw-r--r--src/client/views/EditableView.tsx5
-rw-r--r--src/client/views/ScriptBox.tsx67
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx3
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx6
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx5
-rw-r--r--src/client/views/nodes/ButtonBox.tsx19
-rw-r--r--src/client/views/nodes/DocumentView.tsx42
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx3
9 files changed, 82 insertions, 72 deletions
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index ac055be5b..5f673b3f3 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -93,13 +93,13 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
{this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />)}
</div>;
return (
- <div className={"contextMenu-item" + (this.props.selected ? " contextMenu-itemSelected" : "")} onMouseEnter={this.onPointerEnter} onMouseLeave={this.onPointerLeave}>
+ <div className={"contextMenu-item" + (this.props.selected ? " contextMenu-itemSelected" : "")} onMouseLeave={this.onPointerLeave}>
{this.props.icon ? (
<span className="icon-background">
<FontAwesomeIcon icon={this.props.icon} size="sm" />
</span>
) : null}
- <div className="contextMenu-description">
+ <div className="contextMenu-description" onMouseEnter={this.onPointerEnter} >
{this.props.description}
<FontAwesomeIcon icon={faAngleRight} size="lg" style={{ position: "absolute", right: "10px" }} />
</div>
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 1bdb26b3d..e9db4b048 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -28,7 +28,8 @@ export interface EditableProps {
contents: any;
fontStyle?: string;
fontSize?: number;
- height?: number;
+ height?: number | "auto";
+ maxHeight?: number;
display?: string;
autosuggestProps?: {
resetValue: () => void;
@@ -145,7 +146,7 @@ export class EditableView extends React.Component<EditableProps> {
if (this.props.autosuggestProps) this.props.autosuggestProps.resetValue();
return (
<div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`}
- style={{ display: this.props.display, minHeight: "20px", height: "auto", maxHeight: `${this.props.height}` }}
+ style={{ display: this.props.display, minHeight: "20px", height: `${this.props.height ? this.props.height : "auto"}`, maxHeight: `${this.props.maxHeight}` }}
onClick={this.onClick}>
<span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize }}>{this.props.contents}</span>
</div>
diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx
index 1f3673390..8f08224c8 100644
--- a/src/client/views/ScriptBox.tsx
+++ b/src/client/views/ScriptBox.tsx
@@ -18,6 +18,7 @@ export interface ScriptBoxProps {
onCancel?: () => void;
initialText?: string;
showDocumentIcons?: boolean;
+ setParams?: (p: string[]) => void;
}
@observer
@@ -58,56 +59,30 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
onFocus = this.onFocus;
onBlur = this.onBlur;
}
+ let 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}
+ />;
return (
<div className="scriptBox-outerDiv">
+ <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>
<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>
</div>
- <textarea className="scriptBox-textarea" onChange={this.onChange} value={this._scriptText} onFocus={onFocus} onBlur={onBlur}></textarea>
</div>
);
}
//let l = docList(this.source[0].data).length; if (l) { let ind = this.target[0].index !== undefined ? (this.target[0].index+1) % l : 0; this.target[0].index = ind; this.target[0].proto = getProto(docList(this.source[0].data)[ind]);}
- public static EditButtonScript(doc: Doc, fieldKey: string, content: any, clientX: number, clientY: number) {
- let overlayDisposer: () => void = emptyFunction;
- const script = ScriptCast(doc[fieldKey]);
- let originalText = script && script.script.originalScript;
- // tslint:disable-next-line: no-unnecessary-callback-wrapper
- let scriptingBox = <ScriptBox initialText={originalText} onCancel={() => overlayDisposer()} onSave={(text, onError) => {
- const script = CompileScript(text, {
- params: { this: Doc.name },
- typecheck: false,
- editable: true,
- transformer: DocumentIconContainer.getTransformer()
- });
- if (!script.compiled) {
- onError(script.errors.map(error => error.messageText).join("\n"));
- return;
- }
-
- DragManager.StartButtonDrag([], text, "a script",
- {}, this._params, (button: Doc) => { }, clientX, clientY);
-
- doc[fieldKey] = new ScriptField(script);
- overlayDisposer();
- }} showDocumentIcons />;
- let params = <EditableView
- contents={""}
- display={"block"}
- height={72}
- fontSize={12}
- GetValue={() => ""}
- SetValue={(value: string) => (this._params = value.split(" ").filter(s => s !== " ")) ? true : true}
- />;
- let box = <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
- {scriptingBox}
- {params}
- </div>
- overlayDisposer = OverlayView.Instance.addWindow(box, { x: 400, y: 200, width: 500, height: 400, title: `${doc.title || ""} OnClick` });
- }
- static _params: string[] = [];
- public static EditClickScript(doc: Doc, fieldKey: string, prewrapper?: string, postwrapper?: string) {
+ public static EditButtonScript(title: string, doc: Doc, fieldKey: string, clientX: number, clientY: number, prewrapper?: string, postwrapper?: string) {
let overlayDisposer: () => void = emptyFunction;
const script = ScriptCast(doc[fieldKey]);
let originalText: string | undefined = undefined;
@@ -121,10 +96,9 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
}
}
// tslint:disable-next-line: no-unnecessary-callback-wrapper
- let scriptingBox = <ScriptBox initialText={originalText} onCancel={() => overlayDisposer()} onSave={(text, onError) => {
- if (prewrapper) {
- text = prewrapper + text + (postwrapper ? postwrapper : "");
- }
+ let params: string[] = [];
+ let setParams = (p: string[]) => params.splice(0, params.length, ...p);
+ let scriptingBox = <ScriptBox initialText={originalText} setParams={setParams} onCancel={() => overlayDisposer()} onSave={(text, onError) => {
const script = CompileScript(text, {
params: { this: Doc.name },
typecheck: false,
@@ -135,9 +109,12 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
onError(script.errors.map(error => error.messageText).join("\n"));
return;
}
+
+ params.length && DragManager.StartButtonDrag([], text, "a script", {}, params, (button: Doc) => { }, clientX, clientY);
+
doc[fieldKey] = new ScriptField(script);
overlayDisposer();
}} showDocumentIcons />;
- overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${doc.title || ""} OnClick` });
+ overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: title });
}
}
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 9c26a08f0..c59107b53 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -214,7 +214,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
isEditingCallback={this.isEditingCallback}
display={"inline"}
contents={contents}
- height={Number(MAX_ROW_HEIGHT)}
+ height={"auto"}
+ maxHeight={Number(MAX_ROW_HEIGHT)}
GetValue={() => {
let field = props.Document[props.fieldKey];
if (Field.IsField(field)) {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 654ff2279..91e10b0ac 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -362,8 +362,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
subItems.push({ description: `${this.props.Document.fillColumn ? "Variable Size" : "Autosize"} Column`, event: () => this.props.Document.fillColumn = !this.props.Document.fillColumn, icon: "plus" });
subItems.push({ description: `${this.props.Document.showTitles ? "Hide Titles" : "Show Titles"}`, event: () => this.props.Document.showTitles = !this.props.Document.showTitles ? "title" : "", icon: "plus" });
subItems.push({ description: `${this.props.Document.showCaptions ? "Hide Captions" : "Show Captions"}`, event: () => this.props.Document.showCaptions = !this.props.Document.showCaptions ? "caption" : "", icon: "plus" });
- subItems.push({ description: "Edit onChildClick script", icon: "edit", event: () => ScriptBox.EditClickScript(this.props.Document, "onChildClick") });
ContextMenu.Instance.addItem({ description: "Stacking Options ...", subitems: subItems, icon: "eye" });
+
+ let existingOnClick = ContextMenu.Instance.findByDescription("OnClick...");
+ let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
+ onClicks.push({ description: "Edit onChildClick script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Child Clicked...", this.props.Document, "onChildClick", obj.x, obj.y) });
+ !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
}
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index e31fa0b40..8539b3fcc 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -592,13 +592,14 @@ export class CollectionTreeView extends CollectionSubView(Document) {
<div id="body" className="collectionTreeView-dropTarget"
style={{ overflow: "auto", background: StrCast(this.props.Document.backgroundColor, "lightgray") }}
onContextMenu={this.onContextMenu}
- onWheel={(e: React.WheelEvent) => (e.target as any).scrollHeight > (e.target as any).clientHeight && e.stopPropagation()}
+ onWheel={(e: React.WheelEvent) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()}
onDrop={this.onTreeDrop}
ref={this.createTreeDropTarget}>
<EditableView
contents={this.resolvedDataDoc.title}
display={"block"}
- height={72}
+ maxHeight={72}
+ height={"auto"}
GetValue={() => StrCast(this.resolvedDataDoc.title)}
SetValue={undoBatch((value: string) => (Doc.GetProto(this.resolvedDataDoc).title = value) ? true : true)}
OnFillDown={undoBatch((value: string) => {
diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx
index db4bb7972..68d3b8ae1 100644
--- a/src/client/views/nodes/ButtonBox.tsx
+++ b/src/client/views/nodes/ButtonBox.tsx
@@ -13,6 +13,8 @@ import { undoBatch } from '../../util/UndoManager';
import { DocComponent } from '../DocComponent';
import './ButtonBox.scss';
import { FieldView, FieldViewProps } from './FieldView';
+import { ContextMenuProps } from '../ContextMenuItem';
+import { ContextMenu } from '../ContextMenu';
library.add(faEdit as any);
@@ -41,11 +43,24 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
}
}
+
+ specificContextMenu = (e: React.MouseEvent): void => {
+ let funcs: ContextMenuProps[] = [];
+ funcs.push({
+ description: "Clear Script Params", event: () => {
+ let params = Cast(this.props.Document.buttonParams, listSpec("string"));
+ params && params.map(p => this.props.Document[p] = undefined)
+ }, icon: "trash"
+ });
+
+ ContextMenu.Instance.addItem({ description: "OnClick...", subitems: funcs, icon: "asterisk" });
+ }
+
@undoBatch
@action
drop = (e: Event, de: DragManager.DropEvent) => {
if (de.data instanceof DragManager.DocumentDragData && e.target) {
- Doc.GetProto(this.dataDoc)[(e.target as any).textContent] = new List<Doc>(de.data.droppedDocuments);
+ this.props.Document[(e.target as any).textContent] = new List<Doc>(de.data.droppedDocuments);
e.stopPropagation();
}
}
@@ -55,7 +70,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
let missingParams = params && params.filter(p => this.props.Document[p] === undefined);
params && params.map(async p => await DocListCastAsync(this.props.Document[p])); // bcz: really hacky form of prefetching ...
return (
- <div className="buttonBox-outerDiv" ref={this.createDropTarget} >
+ <div className="buttonBox-outerDiv" ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
<div className="buttonBox-mainButton" style={{ background: StrCast(this.props.Document.backgroundColor), color: StrCast(this.props.Document.color, "black") }} >
<div className="buttonBox-mainButtonCenter">
{(this.Document.text || this.Document.title)}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ca8fb573f..9c2cf5f01 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -446,10 +446,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@undoBatch
makeCustomViewClicked = (): void => {
- let options = { title: "data", width: NumCast(this.props.Document.width), height: NumCast(this.props.Document.height) };
+ let options = { title: "data", width: NumCast(this.props.Document.width), height: NumCast(this.props.Document.height) + 25, x: -NumCast(this.props.Document.width) / 2, y: -NumCast(this.props.Document.height) / 2, };
let fieldTemplate = this.props.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) : Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
- let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: StrCast(this.Document.title) + "layout", width: NumCast(this.props.Document.width) + 20, height: NumCast(this.props.Document.height) + 20 });
+ let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: StrCast(this.Document.title) + "layout", width: NumCast(this.props.Document.width) + 20, height: Math.max(100, NumCast(this.props.Document.height) + 45) });
let metaKey = "data";
let proto = Doc.GetProto(docTemplate);
Doc.MakeTemplate(fieldTemplate, metaKey, proto, true);
@@ -460,15 +460,21 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@undoBatch
makeBtnClicked = (): void => {
let doc = Doc.GetProto(this.props.Document);
- doc.isButton = !BoolCast(doc.isButton);
- if (doc.isButton) {
- if (!doc.nativeWidth) {
- doc.nativeWidth = this.props.Document[WidthSym]();
- doc.nativeHeight = this.props.Document[HeightSym]();
- }
+ if (doc.isButton || doc.onClick) {
+ doc.isButton = false;
+ doc.onClick = undefined;
} else {
- doc.nativeWidth = doc.nativeHeight = undefined;
+ doc.isButton = true;
}
+
+ // if (doc.isButton) {
+ // if (!doc.nativeWidth) {
+ // doc.nativeWidth = this.props.Document[WidthSym]();
+ // doc.nativeHeight = this.props.Document[HeightSym]();
+ // }
+ // } else {
+ // doc.nativeWidth = doc.nativeHeight = undefined;
+ // }
}
@undoBatch
@@ -623,21 +629,25 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" });
subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" });
cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" });
+
let existingMake = ContextMenu.Instance.findByDescription("Make...");
let makes: ContextMenuProps[] = existingMake && "subitems" in existingMake ? existingMake.subitems : [];
makes.push({ description: this.props.Document.isBackground ? "Remove Background" : "Into Background", event: this.makeBackground, icon: this.props.Document.lockedPosition ? "unlock" : "lock" });
- makes.push({ description: this.props.Document.isButton ? "Remove Button" : "Into Button", event: this.makeBtnClicked, icon: "concierge-bell" });
- makes.push({ description: "Custom View", event: this.makeCustomViewClicked, icon: "concierge-bell" });
- makes.push({ description: "Custom Field", event: () => this.props.ContainingCollectionView && Doc.MakeTemplate(this.props.Document, StrCast(this.props.Document.title), this.props.ContainingCollectionView.props.Document, true), icon: "concierge-bell" })
- makes.push({ description: "OnClick Button script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript(this.props.Document, "onClick", this._mainCont, obj.x, obj.y) });
- makes.push({ description: "OnClick script", icon: "edit", event: () => ScriptBox.EditClickScript(this.props.Document, "onClick") });
- makes.push({ description: "OnClick foreach doc", icon: "edit", event: () => ScriptBox.EditClickScript(this.props.Document, "onClick", "docList(this.collectionContext.data).map(d => {", "});\n") });
+ makes.push({ description: "Custom Document View", event: this.makeCustomViewClicked, icon: "concierge-bell" });
+ makes.push({ description: "Metadata Field View", event: () => this.props.ContainingCollectionView && Doc.MakeTemplate(this.props.Document, StrCast(this.props.Document.title), this.props.ContainingCollectionView.props.Document, true), icon: "concierge-bell" })
makes.push({ description: "Into Portal", event: this.makeIntoPortal, icon: "window-restore" });
makes.push({ description: this.layoutDoc.ignoreClick ? "Selectable" : "Unselectable", event: () => this.layoutDoc.ignoreClick = !this.layoutDoc.ignoreClick, icon: this.layoutDoc.ignoreClick ? "unlock" : "lock" });
!existingMake && cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" });
+
+ let existingOnClick = ContextMenu.Instance.findByDescription("OnClick...");
+ let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
+ onClicks.push({ description: this.props.Document.isButton || this.props.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.makeBtnClicked, icon: "concierge-bell" });
+ onClicks.push({ description: "Edit onClick Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", obj.x, obj.y) });
+ onClicks.push({ description: "Edit onClick Foreach Doc Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("Foreach Collection Doc (d) => ", this.props.Document, "onClick", obj.x, obj.y, "docList(this.collectionContext.data).map(d => {", "});\n") });
+ !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
+
let existing = ContextMenu.Instance.findByDescription("Layout...");
let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : [];
-
layoutItems.push({ description: `${this.layoutDoc.chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.layoutDoc.chromeStatus = (this.layoutDoc.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
layoutItems.push({ description: `${this.layoutDoc.autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc.autoHeight = !this.layoutDoc.autoHeight, icon: "plus" });
layoutItems.push({ description: this.props.Document.ignoreAspect || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" });
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 5afd4d834..a27dbd83d 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -112,7 +112,8 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
<div className="keyValuePair-td-value-container">
<EditableView
contents={contents}
- height={36}
+ maxHeight={36}
+ height={"auto"}
GetValue={() => {
return Field.toKeyValueString(props.Document, props.fieldKey);
}}