aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts2
-rw-r--r--src/client/northstar/dash-fields/HistogramField.ts2
-rw-r--r--src/client/northstar/operations/HistogramOperation.ts4
-rw-r--r--src/client/util/DocumentManager.ts2
-rw-r--r--src/client/util/DragManager.ts17
-rw-r--r--src/client/util/Scripting.ts97
-rw-r--r--src/client/util/SelectionManager.ts2
-rw-r--r--src/client/util/Transform.ts14
-rw-r--r--src/client/views/InkingCanvas.scss3
-rw-r--r--src/client/views/Main.scss23
-rw-r--r--src/client/views/Main.tsx128
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx24
-rw-r--r--src/client/views/collections/CollectionTreeView.scss86
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx11
-rw-r--r--src/client/views/collections/CollectionViewBase.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx91
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx338
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx6
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx6
-rw-r--r--src/fields/Document.ts30
-rw-r--r--src/fields/KeyStore.ts105
-rw-r--r--src/fields/NumberField.ts2
23 files changed, 585 insertions, 414 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 340983e11..46c27e672 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -43,6 +43,7 @@ export interface DocumentOptions {
layoutKeys?: Key[];
viewType?: number;
backgroundColor?: string;
+ copyDraggedItems?: boolean;
}
export namespace Documents {
@@ -86,6 +87,7 @@ export namespace Documents {
if (options.ink !== undefined) { doc.Set(KeyStore.Ink, new InkField(options.ink)); }
if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); }
if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); }
+ if (options.copyDraggedItems !== undefined) { doc.SetBoolean(KeyStore.CopyDraggedItems, options.copyDraggedItems); }
return doc;
}
diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts
index 90be70b80..48731f52d 100644
--- a/src/client/northstar/dash-fields/HistogramField.ts
+++ b/src/client/northstar/dash-fields/HistogramField.ts
@@ -27,7 +27,7 @@ export class HistogramField extends BasicField<HistogramOperation> {
}
Copy(): Field {
- return new HistogramField(this.Data);
+ return new HistogramField(this.Data.Copy());
}
ToScriptString(): string {
diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts
index e63de1632..840520235 100644
--- a/src/client/northstar/operations/HistogramOperation.ts
+++ b/src/client/northstar/operations/HistogramOperation.ts
@@ -42,6 +42,10 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons
this.SchemaName = schemaName;
}
+ Copy(): HistogramOperation {
+ return new HistogramOperation(this.SchemaName, this.X, this.Y, this.V, this.Normalization);
+ }
+
Equals(other: Object): boolean {
throw new Error("Method not implemented.");
}
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index bf59fbb43..341959936 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -29,7 +29,7 @@ export class DocumentManager {
public getAllDocumentViews(collection: Document) {
return this.DocumentViews.filter(dv =>
- dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document == collection);
+ dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document.Id === collection.Id);
}
public getDocumentView(toFind: Document): DocumentView | null {
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 043932de5..0ee7ed2b3 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,7 +1,5 @@
import { action } from "mobx";
import { Document } from "../../fields/Document";
-import { ImageField } from "../../fields/ImageField";
-import { KeyStore } from "../../fields/KeyStore";
import { CollectionDockingView } from "../views/collections/CollectionDockingView";
import { CollectionView } from "../views/collections/CollectionView";
import { DocumentDecorations } from "../views/DocumentDecorations";
@@ -10,16 +8,19 @@ import { DocumentView } from "../views/nodes/DocumentView";
export function setupDrag(
_reference: React.RefObject<HTMLDivElement>,
docFunc: () => Document,
- removeFunc: (containingCollection: CollectionView) => void = () => { }
+ removeFunc: (containingCollection: CollectionView) => void = () => { },
+ copyOnDrop: boolean = false
) {
let onRowMove = action(
(e: PointerEvent): void => {
e.stopPropagation();
e.preventDefault();
+ // TODO: bcz -- this needs to have a drag threshold so that it doesn't trigger when just selecting.
document.removeEventListener("pointermove", onRowMove);
document.removeEventListener("pointerup", onRowUp);
var dragData = new DragManager.DocumentDragData([docFunc()]);
+ dragData.copyOnDrop = copyOnDrop;
dragData.removeDocument = removeFunc;
DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y);
}
@@ -125,6 +126,7 @@ export namespace DragManager {
xOffset?: number;
yOffset?: number;
aliasOnDrop?: boolean;
+ copyOnDrop?: boolean;
removeDocument?: (collectionDrop: CollectionView) => void;
[id: string]: any;
}
@@ -136,15 +138,12 @@ export namespace DragManager {
downY: number,
options?: DragOptions
) {
- StartDrag(
- eles,
- dragData,
- downX, downY,
- options,
+ StartDrag(eles, dragData, downX, downY, options,
(dropData: { [id: string]: any }) =>
(dropData.droppedDocuments = dragData.aliasOnDrop
? dragData.draggedDocuments.map(d => d.CreateAlias())
- : dragData.draggedDocuments)
+ : dragData.copyOnDrop ? dragData.draggedDocuments.map(d => d.Copy(true) as Document) :
+ dragData.draggedDocuments)
);
}
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 4e97b9401..7c0649a6a 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -18,41 +18,57 @@ import * as typescriptlib from '!!raw-loader!./type_decls.d'
import { Documents } from "../documents/Documents";
import { Key } from "../../fields/Key";
+export interface ScriptSucccess {
+ success: true;
+ result: any;
+}
+
+export interface ScriptError {
+ success: false;
+ error: any;
+}
+
+export type ScriptResult = ScriptSucccess | ScriptError;
-export interface ExecutableScript {
- (): any;
+export interface CompileSuccess {
+ compiled: true;
+ run(args?: { [name: string]: any }): ScriptResult;
+}
- compiled: boolean;
+export interface CompileError {
+ compiled: false;
+ errors: any[];
}
-function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [name: string]: any }): ExecutableScript {
- const compiled = !(diagnostics && diagnostics.some(diag => diag.category == ts.DiagnosticCategory.Error));
+export type CompiledScript = CompileSuccess | CompileError;
+
+function Run(script: string | undefined, customParams: string[], diagnostics: any[]): CompiledScript {
+ const errors = diagnostics.some(diag => diag.category == ts.DiagnosticCategory.Error);
+ if (errors || !script) {
+ return { compiled: false, errors: diagnostics };
+ }
- let func: () => Opt<Field>;
- if (compiled && script) {
- let fieldTypes = [Document, NumberField, TextField, ImageField, RichTextField, ListField, Key];
- let paramNames = ["KeyStore", "Documents", ...fieldTypes.map(fn => fn.name)];
- let params: any[] = [KeyStore, Documents, ...fieldTypes]
- for (let prop in scope) {
- if (prop === "this") {
+ let fieldTypes = [Document, NumberField, TextField, ImageField, RichTextField, ListField, Key];
+ let paramNames = ["KeyStore", "Documents", ...fieldTypes.map(fn => fn.name)];
+ let params: any[] = [KeyStore, Documents, ...fieldTypes]
+ let compiledFunction = new Function(...paramNames, `return ${script}`);
+ let run = (args: { [name: string]: any } = {}): ScriptResult => {
+ let argsArray: any[] = [];
+ for (let name of customParams) {
+ if (name === "this") {
continue;
}
- paramNames.push(prop);
- params.push(scope[prop]);
+ argsArray.push(args[name]);
+ }
+ let thisParam = args["this"];
+ try {
+ const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray);
+ return { success: true, result };
+ } catch (error) {
+ return { success: false, error };
}
- let thisParam = scope["this"];
- let compiledFunction = new Function(...paramNames, script);
- func = function (): Opt<Field> {
- return compiledFunction.apply(thisParam, params)
- };
- } else {
- func = () => undefined;
}
-
- return Object.assign(func,
- {
- compiled
- });
+ return { compiled: true, run };
}
interface File {
@@ -108,20 +124,39 @@ class ScriptingCompilerHost {
}
}
-export function CompileScript(script: string, scope?: { [name: string]: any }, addReturn: boolean = false): ExecutableScript {
+export interface ScriptOptions {
+ requiredType?: string;
+ addReturn?: boolean;
+ params?: { [name: string]: string };
+}
+
+export function CompileScript(script: string, { requiredType = "", addReturn = false, params = {} }: ScriptOptions = {}): CompiledScript {
let host = new ScriptingCompilerHost;
- let funcScript = `(function() {
+ let paramArray: string[] = [];
+ if ("this" in params) {
+ paramArray.push("this");
+ }
+ for (const key in params) {
+ if (key === "this") continue;
+ paramArray.push(key);
+ }
+ let paramString = paramArray.map(key => `${key}: ${params[key]}`).join(", ");
+ let funcScript = `(function(${paramString})${requiredType ? `: ${requiredType}` : ''} {
${addReturn ? `return ${script};` : script}
- }).apply(this)`
+ })`;
host.writeFile("file.ts", funcScript);
host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
let program = ts.createProgram(["file.ts"], {}, host);
let testResult = program.emit();
- let outputText = "return " + host.readFile("file.js");
+ let outputText = host.readFile("file.js");
let diagnostics = ts.getPreEmitDiagnostics(program).concat(testResult.diagnostics);
- return Compile(outputText, diagnostics, scope || {});
+ return Run(outputText, paramArray, diagnostics);
+}
+
+export function OrLiteralType(returnType: string): string {
+ return `${returnType} | string | number`;
}
export function ToField(data: any): Opt<Field> {
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 958c14491..79d4ceb25 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,6 +1,7 @@
import { observable, action } from "mobx";
import { DocumentView } from "../views/nodes/DocumentView";
import { Document } from "../../fields/Document";
+import { Main } from "../views/Main";
export namespace SelectionManager {
class Manager {
@@ -40,6 +41,7 @@ export namespace SelectionManager {
}
manager.SelectedDocuments.length = 0;
if (found) manager.SelectedDocuments.push(found);
+ Main.Instance.SetTextDoc(undefined, undefined);
}
export function SelectedDocuments(): Array<DocumentView> {
diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts
index 3e1039166..060c5da82 100644
--- a/src/client/util/Transform.ts
+++ b/src/client/util/Transform.ts
@@ -17,45 +17,45 @@ export class Transform {
this._scale = scale;
}
- translate = (x: number, y: number): Transform => {
+ translate = (x: number, y: number): this => {
this._translateX += x;
this._translateY += y;
return this;
}
- scale = (scale: number): Transform => {
+ scale = (scale: number): this => {
this._scale *= scale;
this._translateX *= scale;
this._translateY *= scale;
return this;
}
- scaleAbout = (scale: number, x: number, y: number): Transform => {
+ scaleAbout = (scale: number, x: number, y: number): this => {
this._translateX += x * this._scale - x * this._scale * scale;
this._translateY += y * this._scale - y * this._scale * scale;
this._scale *= scale;
return this;
}
- transform = (transform: Transform): Transform => {
+ transform = (transform: Transform): this => {
this._translateX = transform._translateX + transform._scale * this._translateX;
this._translateY = transform._translateY + transform._scale * this._translateY;
this._scale *= transform._scale;
return this;
}
- preTranslate = (x: number, y: number): Transform => {
+ preTranslate = (x: number, y: number): this => {
this._translateX += this._scale * x;
this._translateY += this._scale * y;
return this;
}
- preScale = (scale: number): Transform => {
+ preScale = (scale: number): this => {
this._scale *= scale;
return this;
}
- preTransform = (transform: Transform): Transform => {
+ preTransform = (transform: Transform): this => {
this._translateX += transform._translateX * this._scale;
this._translateY += transform._translateY * this._scale;
this._scale *= transform._scale;
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
index c5a2a50cb..42ae38c73 100644
--- a/src/client/views/InkingCanvas.scss
+++ b/src/client/views/InkingCanvas.scss
@@ -1,5 +1,8 @@
@import "global_variables";
+.inkingCanvas {
+ opacity:0.99;
+}
.inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect {
position: absolute;
top: 0;
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 594803aab..fe7f007b0 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -4,7 +4,7 @@ html,
body {
width: 100%;
height: 100%;
- overflow: hidden;
+ overflow: auto;
font-family: $sans-serif;
margin: 0;
position:absolute;
@@ -157,12 +157,33 @@ button:hover {
cursor: pointer;
}
}
+#root {
+ overflow: visible;
+}
#main-div {
width:100%;
height:100%;
position:absolute;
top: 0;
left:0;
+ overflow: scroll;
+}
+.mainDiv-textInput {
+ background:pink;
+ width: 200px;
+ height: 200px;
+ position:absolute;
+ overflow: visible;
+ top: 0;
+ left: 0;
+ .formattedTextBox-cont {
+ background:pink;
+ width: 100%;
+ height: 100%;
+ position:absolute;
+ top: 0;
+ left: 0;
+ }
}
#mainContent-div {
width:100%;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 237eb3b6e..c9467e130 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -1,57 +1,42 @@
-import { action, configure, observable, runInAction, trace, computed, reaction } from 'mobx';
+import { IconName, library } from '@fortawesome/fontawesome-svg-core';
+import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, computed, configure, observable, runInAction, trace } from 'mobx';
+import { observer } from 'mobx-react';
import "normalize.css";
import * as React from 'react';
import * as ReactDOM from 'react-dom';
+import Measure from 'react-measure';
+import * as request from 'request';
import { Document } from '../../fields/Document';
+import { Field, FieldWaiting, Opt } from '../../fields/Field';
import { KeyStore } from '../../fields/KeyStore';
-import "./Main.scss";
+import { ListField } from '../../fields/ListField';
+import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu';
+import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
import { MessageStore } from '../../server/Message';
+import { RouteStore } from '../../server/RouteStore';
+import { ServerUtils } from '../../server/ServerUtil';
import { Utils } from '../../Utils';
-import * as request from 'request'
-import * as rp from 'request-promise'
import { Documents } from '../documents/Documents';
+import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
+import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
+import { Gateway, Settings } from '../northstar/manager/Gateway';
+import { AggregateFunction, Catalog } from '../northstar/model/idea/idea';
+import '../northstar/model/ModelExtensions';
+import { HistogramOperation } from '../northstar/operations/HistogramOperation';
+import '../northstar/utils/Extensions';
import { Server } from '../Server';
import { setupDrag } from '../util/DragManager';
import { Transform } from '../util/Transform';
-import { UndoManager, undoBatch } from '../util/UndoManager';
-import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu';
+import { UndoManager } from '../util/UndoManager';
import { CollectionDockingView } from './collections/CollectionDockingView';
import { ContextMenu } from './ContextMenu';
import { DocumentDecorations } from './DocumentDecorations';
-import { DocumentView } from './nodes/DocumentView';
-import "./Main.scss";
-import { observer } from 'mobx-react';
import { InkingControl } from './InkingControl';
-import { RouteStore } from '../../server/RouteStore';
-import { library, IconName } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faFont } from '@fortawesome/free-solid-svg-icons';
-import { faImage } from '@fortawesome/free-solid-svg-icons';
-import { faFilePdf } from '@fortawesome/free-solid-svg-icons';
-import { faObjectGroup } from '@fortawesome/free-solid-svg-icons';
-import { faTable } from '@fortawesome/free-solid-svg-icons';
-import { faGlobeAsia } from '@fortawesome/free-solid-svg-icons';
-import { faUndoAlt } from '@fortawesome/free-solid-svg-icons';
-import { faRedoAlt } from '@fortawesome/free-solid-svg-icons';
-import { faPenNib } from '@fortawesome/free-solid-svg-icons';
-import { faFilm } from '@fortawesome/free-solid-svg-icons';
-import { faMusic } from '@fortawesome/free-solid-svg-icons';
-import { faTree } from '@fortawesome/free-solid-svg-icons';
-import Measure from 'react-measure';
-import { DashUserModel } from '../../server/authentication/models/user_model';
-import { ServerUtils } from '../../server/ServerUtil';
-import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
-import { Field, Opt, FieldWaiting } from '../../fields/Field';
-import { ListField } from '../../fields/ListField';
-import { Gateway, Settings } from '../northstar/manager/Gateway';
-import { Catalog, Schema, Attribute, AttributeGroup, AggregateFunction } from '../northstar/model/idea/idea';
-import { ArrayUtil } from '../northstar/utils/ArrayUtil';
-import '../northstar/model/ModelExtensions'
-import '../northstar/utils/Extensions'
-import { HistogramOperation } from '../northstar/operations/HistogramOperation';
-import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
-import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
-import { CollectionView } from './collections/CollectionView';
+import "./Main.scss";
+import { DocumentView } from './nodes/DocumentView';
+import { FormattedTextBox } from './nodes/FormattedTextBox';
@observer
export class Main extends React.Component {
@@ -219,6 +204,30 @@ export class Main extends React.Component {
focusDocument = (doc: Document) => { }
noScaling = () => 1;
+ @observable _textDoc?: Document = undefined;
+ _textRect: any;
+ @action
+ SetTextDoc(textDoc?: Document, div?: HTMLDivElement) {
+ this._textDoc = undefined;
+ this._textDoc = textDoc;
+ if (div)
+ this._textRect = div.getBoundingClientRect();
+ }
+
+ @computed
+ get activeTextBox() {
+ if (this._textDoc) {
+ let x: number = this._textRect.x;
+ let y: number = this._textRect.y;
+ let w: number = this._textRect.width;
+ let h: number = this._textRect.height;
+ return <div className="mainDiv-textInput" style={{ transform: `translate(${x}px, ${y}px)`, width: `${w}px`, height: `${h}px` }} >
+ <FormattedTextBox fieldKey={KeyStore.Archives} doc={this._textDoc} isSelected={() => true} select={() => { }} isTopMost={true} selectOnLoad={true} bindings={undefined} />
+ </ div>
+ }
+ else return (null);
+ }
+
@computed
get mainContent() {
return !this.mainContainer ? (null) :
@@ -247,7 +256,7 @@ export class Main extends React.Component {
let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" }))
let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
let addSchemaNode = action(() => Documents.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" }));
- let addTreeNode = action(() => Documents.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas" }));
+ let addTreeNode = action(() => Documents.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", copyDraggedItems: true }));
let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, height: 200, title: "video node" }));
let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" }));
let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" }));
@@ -312,24 +321,27 @@ export class Main extends React.Component {
isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} />
}
return (
- <div id="main-div">
- <DocumentDecorations />
- <Measure onResize={(r: any) => runInAction(() => {
- this.pwidth = r.entry.width;
- this.pheight = r.entry.height;
- })}>
- {({ measureRef }) =>
- <div ref={measureRef} id="mainContent-div">
- {this.mainContent}
- </div>
- }
- </Measure>
- <ContextMenu />
- {this.nodesMenu}
- {this.miscButtons}
- {workspaceMenu}
- <InkingControl />
- </div>
+ [
+ <div id="main-div">
+ <DocumentDecorations />
+ <Measure onResize={(r: any) => runInAction(() => {
+ this.pwidth = r.entry.width;
+ this.pheight = r.entry.height;
+ })}>
+ {({ measureRef }) =>
+ <div ref={measureRef} id="mainContent-div">
+ {this.mainContent}
+ </div>
+ }
+ </Measure>
+ <ContextMenu />
+ {this.nodesMenu}
+ {this.miscButtons}
+ {workspaceMenu}
+ <InkingControl />
+ </div>,
+ this.activeTextBox
+ ]
);
}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 0ff6c3b40..b10aaba98 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -86,12 +86,10 @@ export class CollectionSchemaView extends CollectionViewBase {
)
let reference = React.createRef<HTMLDivElement>();
let onItemDown = setupDrag(reference, () => props.doc, (containingCollection: CollectionView) => this.props.removeDocument(props.doc));
- let applyToDoc = (doc: Document, value: string) => {
- let script = CompileScript(value, { this: doc }, true);
- if (!script.compiled) {
- return false;
- }
- let field = script();
+ let applyToDoc = (doc: Document, run: (args?: { [name: string]: any }) => any) => {
+ const res = run({ this: doc });
+ if (!res.success) return false;
+ const field = res.result;
if (field instanceof Field) {
doc.Set(props.fieldKey, field);
return true;
@@ -118,12 +116,22 @@ export class CollectionSchemaView extends CollectionViewBase {
return field || "";
}}
SetValue={(value: string) => {
- return applyToDoc(props.doc, value);
+ let script = CompileScript(value, { addReturn: true, params: { this: "Document" } });
+ if (!script.compiled) {
+ return false;
+ }
+ return applyToDoc(props.doc, script.run);
}}
OnFillDown={(value: string) => {
+ let script = CompileScript(value, { addReturn: true, params: { this: "Document" } });
+ if (!script.compiled) {
+ return;
+ }
+ const run = script.run;
+ //TODO This should be able to be refactored to compile the script once
this.props.Document.GetTAsync<ListField<Document>>(this.props.fieldKey, ListField).then((val) => {
if (val) {
- val.Data.forEach(doc => applyToDoc(doc, value));
+ val.Data.forEach(doc => applyToDoc(doc, run));
}
})
}}>
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 5a14aa54d..f2affbf55 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -1,64 +1,62 @@
@import "../global_variables";
-#body {
+
+.collectionTreeView-dropTarget {
+ border: 0px solid transparent;
+ border-radius: $border-radius;
+ box-sizing: border-box;
+ height: 100%;
padding: 20px;
padding-left: 10px;
padding-right: 0px;
background: $light-color-secondary;
font-size: 13px;
overflow: scroll;
-}
-ul {
- list-style: none;
- padding-left: 20px;
-}
+ ul {
+ list-style: none;
+ padding-left: 20px;
+ }
-li {
- margin: 5px 0;
-}
+ li {
+ margin: 5px 0;
+ }
-.collection-child {
- margin-top: 10px;
- margin-bottom: 10px;
-}
+ .collection-child {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ }
-.no-indent {
- padding-left: 0;
-}
+ .no-indent {
+ padding-left: 0;
+ }
-.bullet {
- width: 1.5em;
- display: inline-block;
- color: $intermediate-color;
-}
+ .bullet {
+ width: 1.5em;
+ display: inline-block;
+ color: $intermediate-color;
+ }
-.coll-title {
- font-size: 24px;
- margin-bottom: 20px;
-}
+ .coll-title {
+ font-size: 24px;
+ margin-bottom: 20px;
+ }
-.collectionTreeView-dropTarget {
- border: 0px solid transparent;
- border-radius: $border-radius;
- box-sizing: border-box;
- height: 100%;
-}
+ .docContainer {
+ display: inline-table;
+ }
-.docContainer {
- display: inline-table;
-}
+ .docContainer:hover {
+ .delete-button {
+ display: inline;
+ width: auto;
+ }
+ }
-.docContainer:hover {
.delete-button {
+ color: $intermediate-color;
+ float: right;
+ margin-left: 15px;
+ margin-top: 3px;
display: inline;
- width: auto;
}
-}
-
-.delete-button {
- color: $intermediate-color;
- float: right;
- margin-left: 15px;
- margin-top: 3px;
- display: inline;
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 70790af18..0b12f11fd 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -18,6 +18,7 @@ import React = require("react")
export interface TreeViewProps {
document: Document;
deleteDoc: (doc: Document) => void;
+ copyOnDrag: boolean;
}
export enum BulletType {
@@ -63,7 +64,7 @@ class TreeView extends React.Component<TreeViewProps> {
*/
renderTitle() {
let reference = React.createRef<HTMLDivElement>();
- let onItemDown = setupDrag(reference, () => this.props.document, (containingCollection: CollectionView) => this.props.deleteDoc(this.props.document));
+ let onItemDown = setupDrag(reference, () => this.props.document, (containingCollection: CollectionView) => this.props.deleteDoc(this.props.document), this.props.copyOnDrag);
let editableView = (titleString: string) =>
(<EditableView
display={"inline"}
@@ -85,13 +86,12 @@ class TreeView extends React.Component<TreeViewProps> {
render() {
let bulletType = BulletType.List;
let childElements: JSX.Element | undefined = undefined;
-
var children = this.props.document.GetT<ListField<Document>>(KeyStore.Data, ListField);
if (children && children !== FieldWaiting) { // add children for a collection
if (!this._collapsed) {
bulletType = BulletType.Collapsible;
childElements = <ul>
- {children.Data.map(value => <TreeView key={value.Id} document={value} deleteDoc={this.remove} />)}
+ {children.Data.map(value => <TreeView key={value.Id} document={value} deleteDoc={this.remove} copyOnDrag={this.props.copyOnDrag} />)}
</ul>
}
else bulletType = BulletType.Collapsed;
@@ -118,10 +118,11 @@ export class CollectionTreeView extends CollectionViewBase {
}
render() {
- var children = this.props.Document.GetT<ListField<Document>>(KeyStore.Data, ListField);
+ let children = this.props.Document.GetT<ListField<Document>>(KeyStore.Data, ListField);
+ let copyOnDrag = this.props.Document.GetBoolean(KeyStore.CopyDraggedItems, false);
let childrenElement = !children || children === FieldWaiting ? (null) :
(children.Data.map(value =>
- <TreeView document={value} key={value.Id} deleteDoc={this.remove} />)
+ <TreeView document={value} key={value.Id} deleteDoc={this.remove} copyOnDrag={copyOnDrag} />)
)
return (
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index d8f4a0be5..5a24f8cde 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -83,13 +83,13 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
@action
protected drop(e: Event, de: DragManager.DropEvent): boolean {
if (de.data instanceof DragManager.DocumentDragData) {
- if (de.data.aliasOnDrop) {
+ if (de.data.aliasOnDrop || de.data.copyOnDrop) {
[KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key =>
de.data.draggedDocuments.map((draggedDocument: Document, i: number) =>
draggedDocument.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocuments[i].SetNumber(key, f.Data) : null)));
}
let added = de.data.droppedDocuments.reduce((added, d) => this.props.addDocument(d, false), true);
- if (added && de.data.removeDocument && !de.data.aliasOnDrop) {
+ if (added && de.data.removeDocument && !de.data.aliasOnDrop && !de.data.copyOnDrop) {
de.data.removeDocument(this.props.CollectionView);
}
e.stopPropagation();
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index d4809ac1c..1189dd4e8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,4 +1,4 @@
-import { computed, reaction, runInAction, trace } from "mobx";
+import { computed, reaction } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../../../fields/Document";
import { FieldWaiting } from "../../../../fields/Field";
@@ -11,59 +11,60 @@ import { CollectionViewProps } from "../CollectionViewBase";
import "./CollectionFreeFormLinksView.scss";
import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView";
import React = require("react");
-import v5 = require("uuid/v5");
-import { find } from "async";
@observer
export class CollectionFreeFormLinksView extends React.Component<CollectionViewProps> {
+ HackToAvoidReactionFiringUnnecessarily?: Document = undefined;
componentDidMount() {
- reaction(() => {
- return DocumentManager.Instance.getAllDocumentViews(this.props.Document).map(dv => dv.props.Document.GetNumber(KeyStore.X, 0))
- }, () => {
- let views = DocumentManager.Instance.getAllDocumentViews(this.props.Document);
- for (let i = 0; i < views.length; i++) {
- for (let j = 0; j < views.length; j++) {
- let srcDoc = views[j].props.Document;
- let dstDoc = views[i].props.Document;
- let x1 = srcDoc.GetNumber(KeyStore.X, 0);
- let x1w = srcDoc.GetNumber(KeyStore.Width, -1);
- let x2 = dstDoc.GetNumber(KeyStore.X, 0);
- let x2w = dstDoc.GetNumber(KeyStore.Width, -1);
- if (x1w < 0 || x2w < 0 || i == j)
- continue;
- let dstTarg = dstDoc;
- let srcTarg = srcDoc;
- let findBrush = (field: ListField<Document>) => field.Data.findIndex(brush => {
- let bdocs = brush ? brush.GetList(KeyStore.BrushingDocs, [] as Document[]) : [];
- return (bdocs.length && ((bdocs[0] == dstTarg && bdocs[1] == srcTarg)) ? true : false)
- });
- let brushAction = (field: ListField<Document>) => {
- let found = findBrush(field);
- if (found != -1) {
- console.log("REMOVE BRUSH " + srcTarg.Title + " " + dstTarg.Title);
- field.Data.splice(found, 1);
- }
- };
- if (Math.abs(x1 + x1w - x2) < 20) {
- let linkDoc: Document = new Document();
- linkDoc.SetText(KeyStore.Title, "Histogram Brush");
- linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
- linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
-
- brushAction = brushAction = (field: ListField<Document>) => {
- if (findBrush(field) == -1) {
- console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title);
- (findBrush(field) == -1) && field.Data.push(linkDoc);
+ this.HackToAvoidReactionFiringUnnecessarily = this.props.Document
+ reaction(() =>
+ DocumentManager.Instance.getAllDocumentViews(this.HackToAvoidReactionFiringUnnecessarily!).
+ map(dv => dv.props.Document.GetNumber(KeyStore.X, 0)),
+ () => {
+ let views = DocumentManager.Instance.getAllDocumentViews(this.props.Document);
+ for (let i = 0; i < views.length; i++) {
+ for (let j = 0; j < views.length; j++) {
+ let srcDoc = views[j].props.Document;
+ let dstDoc = views[i].props.Document;
+ let x1 = srcDoc.GetNumber(KeyStore.X, 0);
+ let x1w = srcDoc.GetNumber(KeyStore.Width, -1);
+ let x2 = dstDoc.GetNumber(KeyStore.X, 0);
+ let x2w = dstDoc.GetNumber(KeyStore.Width, -1);
+ if (x1w < 0 || x2w < 0 || i == j)
+ continue;
+ let dstTarg = dstDoc;
+ let srcTarg = srcDoc;
+ let findBrush = (field: ListField<Document>) => field.Data.findIndex(brush => {
+ let bdocs = brush ? brush.GetList(KeyStore.BrushingDocs, [] as Document[]) : [];
+ return (bdocs.length && ((bdocs[0] == dstTarg && bdocs[1] == srcTarg)) ? true : false)
+ });
+ let brushAction = (field: ListField<Document>) => {
+ let found = findBrush(field);
+ if (found != -1) {
+ console.log("REMOVE BRUSH " + srcTarg.Title + " " + dstTarg.Title);
+ field.Data.splice(found, 1);
}
};
- }
- dstTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
- srcTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
+ if (Math.abs(x1 + x1w - x2) < 20) {
+ let linkDoc: Document = new Document();
+ linkDoc.SetText(KeyStore.Title, "Histogram Brush");
+ linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
+ linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
+ brushAction = brushAction = (field: ListField<Document>) => {
+ if (findBrush(field) == -1) {
+ console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title);
+ (findBrush(field) == -1) && field.Data.push(linkDoc);
+ }
+ };
+ }
+ dstTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
+ srcTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
+
+ }
}
- }
- })
+ })
}
documentAnchors(view: DocumentView) {
let equalViews = [view];
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 37bb78151..f99ba111c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -21,6 +21,7 @@ import v5 = require("uuid/v5");
import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
import { PreviewCursor } from "./PreviewCursor";
import { NumberField } from "../../../../fields/NumberField";
+import { Main } from "../../Main";
@observer
export class CollectionFreeFormView extends CollectionViewBase {
@@ -185,6 +186,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
@action
private SetPan(panX: number, panY: number) {
+ Main.Instance.SetTextDoc(undefined, undefined);
var x1 = this.getLocalTransform().inverse().Scale;
const newPanX = Math.min((1 - 1 / x1) * this.nativeWidth, Math.max(0, panX));
const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY));
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 0c0efc437..e59179874 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -2,19 +2,19 @@ import { action, IReactionDisposer, reaction } from "mobx";
import { baseKeymap } from "prosemirror-commands";
import { history, redo, undo } from "prosemirror-history";
import { keymap } from "prosemirror-keymap";
-import { schema } from "../../util/RichTextSchema";
-import { EditorState, Transaction } from "prosemirror-state";
+import { EditorState, Plugin, Transaction } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
-import { Opt, FieldWaiting } from "../../../fields/Field";
-import "./FormattedTextBox.scss";
-import React = require("react");
+import { FieldWaiting, Opt } from "../../../fields/Field";
+import { KeyStore } from "../../../fields/KeyStore";
import { RichTextField } from "../../../fields/RichTextField";
-import { FieldViewProps, FieldView } from "./FieldView";
-import { Plugin } from "prosemirror-state";
-import { Decoration, DecorationSet } from "prosemirror-view";
+import { inpRules } from "../../util/RichTextRules";
+import { schema } from "../../util/RichTextSchema";
import { TooltipTextMenu } from "../../util/TooltipTextMenu";
import { ContextMenu } from "../../views/ContextMenu";
-import { inpRules } from "../../util/RichTextRules";
+import { Main } from "../Main";
+import { FieldView, FieldViewProps } from "./FieldView";
+import "./FormattedTextBox.scss";
+import React = require("react");
const { buildMenuItems } = require("prosemirror-example-setup");
const { menuBar } = require("prosemirror-menu");
@@ -35,156 +35,196 @@ const { menuBar } = require("prosemirror-menu");
// this will edit the document and assign the new value to that field.
//]
export class FormattedTextBox extends React.Component<FieldViewProps> {
- public static LayoutString(fieldStr: string = "DataKey") {
- return FieldView.LayoutString(FormattedTextBox, fieldStr);
- }
- private _ref: React.RefObject<HTMLDivElement>;
- private _editorView: Opt<EditorView>;
- private _reactionDisposer: Opt<IReactionDisposer>;
-
- constructor(props: FieldViewProps) {
- super(props);
-
- this._ref = React.createRef();
- this.onChange = this.onChange.bind(this);
- }
-
- dispatchTransaction = (tx: Transaction) => {
- if (this._editorView) {
- const state = this._editorView.state.apply(tx);
- this._editorView.updateState(state);
- const { doc, fieldKey } = this.props;
- doc.SetDataOnPrototype(
- fieldKey,
- JSON.stringify(state.toJSON()),
- RichTextField
- );
- // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+ public static LayoutString(fieldStr: string = "DataKey") {
+ return FieldView.LayoutString(FormattedTextBox, fieldStr);
+ }
+ private _ref: React.RefObject<HTMLDivElement>;
+ private _editorView: Opt<EditorView>;
+ private _reactionDisposer: Opt<IReactionDisposer>;
+ private _inputReactionDisposer: Opt<IReactionDisposer>;
+
+ constructor(props: FieldViewProps) {
+ super(props);
+
+ this._ref = React.createRef();
+ this.onChange = this.onChange.bind(this);
}
- };
-
- componentDidMount() {
- let state: EditorState;
- const config = {
- schema,
- inpRules, //these currently don't do anything, but could eventually be helpful
- plugins: [
- history(),
- keymap({ "Mod-z": undo, "Mod-y": redo }),
- keymap(baseKeymap),
- this.tooltipMenuPlugin()
- ]
+
+ dispatchTransaction = (tx: Transaction) => {
+ if (this._editorView) {
+ const state = this._editorView.state.apply(tx);
+ this._editorView.updateState(state);
+ this.FieldDoc.SetDataOnPrototype(
+ this.FieldKey,
+ JSON.stringify(state.toJSON()),
+ RichTextField
+ );
+ // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+ }
};
- let field = this.props.doc.GetT(this.props.fieldKey, RichTextField);
- if (field && field != FieldWaiting && field.Data) {
- state = EditorState.fromJSON(config, JSON.parse(field.Data));
- } else {
- state = EditorState.create(config);
+ get FieldDoc() { return this.props.fieldKey === KeyStore.Archives ? Main.Instance._textDoc! : this.props.doc; }
+ get FieldKey() { return this.props.fieldKey === KeyStore.Archives ? KeyStore.Data : this.props.fieldKey; }
+
+ componentDidMount() {
+ const config = {
+ schema,
+ inpRules, //these currently don't do anything, but could eventually be helpful
+ plugins: [
+ history(),
+ keymap({ "Mod-z": undo, "Mod-y": redo }),
+ keymap(baseKeymap),
+ this.tooltipMenuPlugin()
+ ]
+ };
+
+ if (this.props.fieldKey === KeyStore.Archives) {
+ this._inputReactionDisposer = reaction(() => Main.Instance._textDoc && Main.Instance._textDoc.Id,
+ () => {
+ if (this._editorView)
+ this._editorView!.destroy();
+
+ this.setupEditor(config);
+ }
+ )
+ }
+
+ this._reactionDisposer = reaction(
+ () => {
+ const field = this.FieldDoc.GetT(this.FieldKey, RichTextField);
+ return field && field != FieldWaiting ? field.Data : undefined;
+ },
+ field => {
+ if (field && this._editorView) {
+ this._editorView.updateState(
+ EditorState.fromJSON(config, JSON.parse(field))
+ );
+ }
+ }
+ );
+ this.setupEditor(config);
+ }
+
+ private setupEditor(config: any) {
+
+ let state: EditorState;
+ let field = this.FieldDoc.GetT(this.FieldKey, RichTextField);
+ if (field && field != FieldWaiting && field.Data) {
+ state = EditorState.fromJSON(config, JSON.parse(field.Data));
+ } else {
+ state = EditorState.create(config);
+ }
+ if (this._ref.current) {
+ this._editorView = new EditorView(this._ref.current, {
+ state,
+ dispatchTransaction: this.dispatchTransaction
+ });
+ }
+
+ if (this.props.selectOnLoad) {
+ this.props.select();
+ this._editorView!.focus();
+ }
}
- if (this._ref.current) {
- this._editorView = new EditorView(this._ref.current, {
- state,
- dispatchTransaction: this.dispatchTransaction
- });
+
+ componentWillUnmount() {
+ if (this._editorView) {
+ this._editorView.destroy();
+ }
+ if (this._reactionDisposer) {
+ this._reactionDisposer();
+ }
+ if (this._inputReactionDisposer) {
+ this._inputReactionDisposer();
+ }
+ }
+
+ shouldComponentUpdate() {
+ return false;
+ }
+
+ @action
+ onChange(e: React.ChangeEvent<HTMLInputElement>) {
+ const { fieldKey, doc } = this.props;
+ doc.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
+ // doc.SetData(fieldKey, e.target.value, RichTextField);
}
+ onPointerDown = (e: React.PointerEvent): void => {
+ if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
+ e.stopPropagation();
+ }
+ if (e.buttons === 1 && this.props.fieldKey !== KeyStore.Archives)
+ e.preventDefault();
+ };
+ onPointerUp = (e: React.PointerEvent): void => {
+ if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
+ e.stopPropagation();
+ }
+ if (this.props.fieldKey !== KeyStore.Archives) {
+ e.preventDefault();
+ Main.Instance.SetTextDoc(this.props.doc, this._ref.current!);
+ }
+ };
- this._reactionDisposer = reaction(
- () => {
- const field = this.props.doc.GetT(this.props.fieldKey, RichTextField);
- return field && field != FieldWaiting ? field.Data : undefined;
- },
- field => {
- if (field && this._editorView) {
- this._editorView.updateState(
- EditorState.fromJSON(config, JSON.parse(field))
- );
+ onFocused = (e: React.FocusEvent): void => {
+ if (this.props.fieldKey !== KeyStore.Archives) {
+ Main.Instance.SetTextDoc(this.props.doc, this._ref.current!);
}
- }
- );
- if (this.props.selectOnLoad) {
- this.props.select();
- this._editorView!.focus();
}
- }
- componentWillUnmount() {
- if (this._editorView) {
- this._editorView.destroy();
+ //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE
+ textCapability = (e: React.MouseEvent): void => { };
+
+ specificContextMenu = (e: React.MouseEvent): void => {
+ ContextMenu.Instance.addItem({
+ description: "Text Capability",
+ event: this.textCapability
+ });
+
+ // ContextMenu.Instance.addItem({
+ // description: "Submenu",
+ // items: [
+ // {
+ // description: "item 1", event:
+ // },
+ // {
+ // description: "item 2", event:
+ // }
+ // ]
+ // })
+ // e.stopPropagation()
+ };
+
+ onPointerWheel = (e: React.WheelEvent): void => {
+ e.stopPropagation();
+ };
+
+ tooltipMenuPlugin() {
+ return new Plugin({
+ view(_editorView) {
+ return new TooltipTextMenu(_editorView);
+ }
+ });
}
- if (this._reactionDisposer) {
- this._reactionDisposer();
+ onKeyPress(e: React.KeyboardEvent) {
+ e.stopPropagation();
+ // stop propagation doesn't seem to stop propagation of native keyboard events.
+ // so we set a flag on the native event that marks that the event's been handled.
+ // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
}
- }
-
- shouldComponentUpdate() {
- return false;
- }
-
- @action
- onChange(e: React.ChangeEvent<HTMLInputElement>) {
- const { fieldKey, doc } = this.props;
- doc.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
- // doc.SetData(fieldKey, e.target.value, RichTextField);
- }
- onPointerDown = (e: React.PointerEvent): void => {
- if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
- e.stopPropagation();
+ render() {
+ return (
+ <div
+ className="formattedTextBox-cont"
+ onKeyDown={this.onKeyPress}
+ onKeyPress={this.onKeyPress}
+ onPointerUp={this.onPointerUp}
+ onPointerDown={this.onPointerDown}
+ onContextMenu={this.specificContextMenu}
+ // tfs: do we need this event handler
+ onWheel={this.onPointerWheel}
+ ref={this._ref}
+ />
+ );
}
- };
-
- //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE
- textCapability = (e: React.MouseEvent): void => {};
-
- specificContextMenu = (e: React.MouseEvent): void => {
- ContextMenu.Instance.addItem({
- description: "Text Capability",
- event: this.textCapability
- });
-
- // ContextMenu.Instance.addItem({
- // description: "Submenu",
- // items: [
- // {
- // description: "item 1", event:
- // },
- // {
- // description: "item 2", event:
- // }
- // ]
- // })
- // e.stopPropagation()
- };
-
- onPointerWheel = (e: React.WheelEvent): void => {
- e.stopPropagation();
- };
-
- tooltipMenuPlugin() {
- return new Plugin({
- view(_editorView) {
- return new TooltipTextMenu(_editorView);
- }
- });
- }
- onKeyPress(e: React.KeyboardEvent) {
- e.stopPropagation();
- // stop propagation doesn't seem to stop propagation of native keyboard events.
- // so we set a flag on the native event that marks that the event's been handled.
- // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
- }
- render() {
- return (
- <div
- className="formattedTextBox-cont"
- onKeyDown={this.onKeyPress}
- onKeyPress={this.onKeyPress}
- onPointerDown={this.onPointerDown}
- onContextMenu={this.specificContextMenu}
- // tfs: do we need this event handler
- onWheel={this.onPointerWheel}
- ref={this._ref}
- />
- );
- }
}
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 283c1f732..9bd6c1052 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -40,11 +40,13 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
}
let realDoc = doc;
- let script = CompileScript(this._valueInput, undefined, true);
+ let script = CompileScript(this._valueInput, { addReturn: true });
if (!script.compiled) {
return;
}
- let field = script();
+ let res = script.run();
+ if (!res.success) return;
+ const field = res.result;
if (field instanceof Field) {
realDoc.Set(new Key(this._keyInput), field);
} else {
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 7ed5ee272..5647f45bf 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -76,11 +76,13 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
return field || "";
}}
SetValue={(value: string) => {
- let script = CompileScript(value, undefined, true);
+ let script = CompileScript(value, { addReturn: true });
if (!script.compiled) {
return false;
}
- let field = script();
+ let res = script.run();
+ if (!res.success) return false;
+ const field = res.result;
if (field instanceof Field) {
props.doc.Set(props.fieldKey, field);
return true;
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 538d4ada9..02004678d 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -10,6 +10,9 @@ import { Types } from "../server/Message";
import { UndoManager } from "../client/util/UndoManager";
import { HtmlField } from "./HtmlField";
import { BooleanField } from "./BooleanField";
+import { allLimit } from "async";
+import { prototype } from "nodemailer/lib/smtp-pool";
+import { HistogramField } from "../client/northstar/dash-fields/HistogramField";
export class Document extends Field {
//TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field
@@ -343,7 +346,10 @@ export class Document extends Field {
SetText(key: Key, value: string, replaceWrongType = true) {
this.SetData(key, value, TextField, replaceWrongType);
}
-
+ @action
+ SetBoolean(key: Key, value: boolean, replaceWrongType = true) {
+ this.SetData(key, value, BooleanField, replaceWrongType);
+ }
@action
SetNumber(key: Key, value: number, replaceWrongType = true) {
this.SetData(key, value, NumberField, replaceWrongType);
@@ -393,8 +399,26 @@ export class Document extends Field {
return title;
//throw new Error("Method not implemented.");
}
- Copy(): Field {
- throw new Error("Method not implemented.");
+ Copy(copyProto?: boolean, id?: string): Field {
+ let copy = new Document();
+ this._proxies.forEach((fieldid, keyid) => { // copy each prototype field
+ let key = KeyStore.KeyLookup(keyid);
+ if (key) {
+ this.GetAsync(key, (field: Opt<Field>) => {
+ if (key === KeyStore.Prototype && copyProto) { // handle prototype field specially
+ if (field instanceof Document) {
+ copy.Set(key, field.Copy(false)); // only copying one level of prototypes for now...
+ }
+ }
+ else
+ if (field instanceof Document) // ... TODO bcz: should we copy documents or reference them
+ copy.Set(key!, field)
+ else if (field)
+ copy.Set(key!, field.Copy())
+ })
+ }
+ });
+ return copy;
}
ToJson(): { type: Types; data: [string, string][]; _id: string } {
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 6ed3b1604..42dc34c51 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -2,49 +2,64 @@ import { Key } from "./Key";
import { KeyTransfer } from "../server/Message";
export namespace KeyStore {
- export const Prototype = new Key("Prototype");
- export const X = new Key("X");
- export const Y = new Key("Y");
- export const Page = new Key("Page");
- export const Title = new Key("Title");
- export const Author = new Key("Author");
- export const PanX = new Key("PanX");
- export const PanY = new Key("PanY");
- export const Scale = new Key("Scale");
- export const NativeWidth = new Key("NativeWidth");
- export const NativeHeight = new Key("NativeHeight");
- export const Width = new Key("Width");
- export const Height = new Key("Height");
- export const ZIndex = new Key("ZIndex");
- export const Data = new Key("Data");
- export const Annotations = new Key("Annotations");
- export const ViewType = new Key("ViewType");
- export const Layout = new Key("Layout");
- export const BackgroundColor = new Key("BackgroundColor");
- export const BackgroundLayout = new Key("BackgroundLayout");
- export const OverlayLayout = new Key("OverlayLayout");
- export const LayoutKeys = new Key("LayoutKeys");
- export const LayoutFields = new Key("LayoutFields");
- export const ColumnsKey = new Key("SchemaColumns");
- export const SchemaSplitPercentage = new Key("SchemaSplitPercentage");
- export const Caption = new Key("Caption");
- export const ActiveWorkspace = new Key("ActiveWorkspace");
- export const DocumentText = new Key("DocumentText");
- export const BrushingDocs = new Key("BrushingDocs");
- export const LinkedToDocs = new Key("LinkedToDocs");
- export const LinkedFromDocs = new Key("LinkedFromDocs");
- export const LinkDescription = new Key("LinkDescription");
- export const LinkTags = new Key("LinkTag");
- export const Thumbnail = new Key("Thumbnail");
- export const ThumbnailPage = new Key("ThumbnailPage");
- export const CurPage = new Key("CurPage");
- export const AnnotationOn = new Key("AnnotationOn");
- export const NumPages = new Key("NumPages");
- export const Ink = new Key("Ink");
- export const Cursors = new Key("Cursors");
- export const OptionalRightCollection = new Key("OptionalRightCollection");
- export const Archives = new Key("Archives");
- export const Updated = new Key("Updated");
- export const Workspaces = new Key("Workspaces");
- export const Minimized = new Key("Minimized");
+ export const Prototype = new Key("Prototype");
+ export const X = new Key("X");
+ export const Y = new Key("Y");
+ export const Page = new Key("Page");
+ export const Title = new Key("Title");
+ export const Author = new Key("Author");
+ export const PanX = new Key("PanX");
+ export const PanY = new Key("PanY");
+ export const Scale = new Key("Scale");
+ export const NativeWidth = new Key("NativeWidth");
+ export const NativeHeight = new Key("NativeHeight");
+ export const Width = new Key("Width");
+ export const Height = new Key("Height");
+ export const ZIndex = new Key("ZIndex");
+ export const Data = new Key("Data");
+ export const Annotations = new Key("Annotations");
+ export const ViewType = new Key("ViewType");
+ export const Layout = new Key("Layout");
+ export const BackgroundColor = new Key("BackgroundColor");
+ export const BackgroundLayout = new Key("BackgroundLayout");
+ export const OverlayLayout = new Key("OverlayLayout");
+ export const LayoutKeys = new Key("LayoutKeys");
+ export const LayoutFields = new Key("LayoutFields");
+ export const ColumnsKey = new Key("SchemaColumns");
+ export const SchemaSplitPercentage = new Key("SchemaSplitPercentage");
+ export const Caption = new Key("Caption");
+ export const ActiveWorkspace = new Key("ActiveWorkspace");
+ export const DocumentText = new Key("DocumentText");
+ export const BrushingDocs = new Key("BrushingDocs");
+ export const LinkedToDocs = new Key("LinkedToDocs");
+ export const LinkedFromDocs = new Key("LinkedFromDocs");
+ export const LinkDescription = new Key("LinkDescription");
+ export const LinkTags = new Key("LinkTag");
+ export const Thumbnail = new Key("Thumbnail");
+ export const ThumbnailPage = new Key("ThumbnailPage");
+ export const CurPage = new Key("CurPage");
+ export const AnnotationOn = new Key("AnnotationOn");
+ export const NumPages = new Key("NumPages");
+ export const Ink = new Key("Ink");
+ export const Cursors = new Key("Cursors");
+ export const OptionalRightCollection = new Key("OptionalRightCollection");
+ export const Archives = new Key("Archives");
+ export const Workspaces = new Key("Workspaces");
+ export const Minimized = new Key("Minimized");
+ export const CopyDraggedItems = new Key("CopyDraggedItems");
+
+ export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight,
+ Width, Height, ZIndex, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys,
+ LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs,
+ LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection,
+ Archives, Workspaces, Minimized, CopyDraggedItems
+ ];
+ export function KeyLookup(keyid: string) {
+ for (let i = 0; i < KeyList.length; i++) {
+ let keylistid = KeyList[i].Id;
+ if (keylistid === keyid)
+ return KeyList[i];
+ }
+ return null;
+ }
}
diff --git a/src/fields/NumberField.ts b/src/fields/NumberField.ts
index 47dfc74cb..e0c8648de 100644
--- a/src/fields/NumberField.ts
+++ b/src/fields/NumberField.ts
@@ -8,7 +8,7 @@ export class NumberField extends BasicField<number> {
}
ToScriptString(): string {
- return "new NumberField(this.Data)";
+ return `new NumberField(${this.Data})`;
}
Copy() {