From 3c71a4b9c727f8eee8631b46b28c010682608f13 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 16 Feb 2019 07:46:55 -0500 Subject: Fixed server and added a field debug viewer --- src/client/util/Scripting.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/util') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 6bc5fa412..befb9df4c 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -6,7 +6,7 @@ import { NumberField as NumberFieldImport, NumberField } from "../../fields/Numb import { ImageField as ImageFieldImport } from "../../fields/ImageField"; import { TextField as TextFieldImport, TextField } from "../../fields/TextField"; import { RichTextField as RichTextFieldImport } from "../../fields/RichTextField"; -import { KeyStore as KeyStoreImport } from "../../fields/Key"; +import { KeyStore as KeyStoreImport } from "../../fields/KeyStore"; export interface ExecutableScript { (): any; -- cgit v1.2.3-70-g09d2 From 3e02f7c7efe0b07ab1e34165e6d8d369f69110b0 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 20 Feb 2019 10:55:30 -0500 Subject: fixed dragdrop issue. improved selection in schema views, but not fixed fully. --- src/client/util/DragManager.ts | 6 +- src/client/views/DocumentDecorations.tsx | 19 ++-- .../views/collections/CollectionSchemaView.tsx | 110 ++++++++++----------- 3 files changed, 62 insertions(+), 73 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 337ec855a..6d5fe12a7 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,3 +1,4 @@ +import { DocumentDecorations } from "../views/DocumentDecorations"; export namespace DragManager { export function Root() { @@ -59,10 +60,8 @@ export namespace DragManager { }; } - - let _lastPointerX: number = 0; - let _lastPointerY: number = 0; export function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options: DragOptions) { + DocumentDecorations.Instance.Hidden = true; if (!dragDiv) { dragDiv = document.createElement("div"); DragManager.Root().appendChild(dragDiv); @@ -131,5 +130,6 @@ export namespace DragManager { } })); options.handlers.dragComplete({}); + DocumentDecorations.Instance.Hidden = false; } } \ No newline at end of file diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 770433e27..dccab1dc5 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,9 +1,8 @@ -import { observable, computed } from "mobx"; +import { observable, computed, action } from "mobx"; import React = require("react"); import { SelectionManager } from "../util/SelectionManager"; import { observer } from "mobx-react"; import './DocumentDecorations.scss' -import { CollectionFreeFormView } from "./collections/CollectionFreeFormView"; import { KeyStore } from '../../fields/KeyStore' import { NumberField } from "../../fields/NumberField"; @@ -12,7 +11,7 @@ export class DocumentDecorations extends React.Component { static Instance: DocumentDecorations private _resizer = "" private _isPointerDown = false; - @observable private _opacity = 1; + @observable private _hidden = false; constructor(props: Readonly<{}>) { super(props) @@ -39,14 +38,10 @@ export class DocumentDecorations extends React.Component { }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE }); } - @computed - get opacity(): number { - return this._opacity - } - set opacity(o: number) { - this._opacity = Math.min(Math.max(0, o), 1) - } + @computed + public get Hidden() { return this._hidden; } + public set Hidden(value: boolean) { this._hidden = value; } onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -147,13 +142,15 @@ export class DocumentDecorations extends React.Component { render() { var bounds = this.Bounds; + if (this.Hidden) { + return (null); + } return (
e.preventDefault()}>
e.preventDefault()}>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 597a97222..fa37e0e76 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -2,7 +2,6 @@ import React = require("react") import { action, observable } from "mobx"; import { observer } from "mobx-react"; import Measure from "react-measure"; -import SplitPane from "react-split-pane"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; import "react-table/react-table.css"; import { Document } from "../../../fields/Document"; @@ -15,7 +14,6 @@ import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase"; -import { relative } from "path"; @observer export class CollectionSchemaView extends CollectionViewBase { @@ -67,6 +65,7 @@ export class CollectionSchemaView extends CollectionViewBase { ) } + private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { const that = this; if (!rowInfo) { @@ -75,8 +74,7 @@ export class CollectionSchemaView extends CollectionViewBase { return { onClick: action((e: React.MouseEvent, handleOriginal: Function) => { that.selectedIndex = rowInfo.index; - const doc: Document = rowInfo.original; - console.log("Row clicked: ", doc.Title) + this._splitPercentage += 0.05; // bcz - ugh - needed to force Measure to do its thing and call onResize if (handleOriginal) { handleOriginal() @@ -118,70 +116,64 @@ export class CollectionSchemaView extends CollectionViewBase { } } + innerScreenToLocal(tx: number, ty: number) { + return () => this.props.ScreenToLocalTransform().transform(new Transform(-tx - 5 - COLLECTION_BORDER_WIDTH, -ty - COLLECTION_BORDER_WIDTH, 1)) + } - @observable - private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView + @observable _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView + @observable _dividerX = 0; + @observable _dividerY = 0; render() { - const { Document: Document, fieldKey: fieldKey } = this.props; - const children = Document.GetList(fieldKey, []); - const columns = Document.GetList(KeyStore.ColumnsKey, - [KeyStore.Title, KeyStore.Data, KeyStore.Author]) - let content =
+ const columns = this.props.Document.GetList(KeyStore.ColumnsKey, [KeyStore.Title, KeyStore.Data, KeyStore.Author]) + const children = this.props.Document.GetList(this.props.fieldKey, []); + const selected = children.length > this.selectedIndex ? children[this.selectedIndex] : undefined; let me = this; - if (this.selectedIndex != -1) { - content = ( + let content = this.selectedIndex == -1 || !selected ? (null) : ( + this._parentScaling = r.entry.width / selected.GetNumber(KeyStore.NativeWidth, r.entry.width))}> + {({ measureRef }) => +
+ +
+ } +
+ ) + return ( +
{ - var doc = children[this.selectedIndex]; - var n = doc.GetNumber(KeyStore.NativeWidth, 0); - if (n > 0 && r.entry.width > 0) { - this._parentScaling = r.entry.width / n; - } + this._dividerX = r.entry.width; })}> {({ measureRef }) => -
- Transform.Identity}//TODO This should probably be an actual transform - Scaling={this._parentScaling} - isTopMost={false} - ContainingCollectionView={me} /> +
+ { + return ( + { + Header: col.Name, + accessor: (doc: Document) => [doc, col], + id: col.Id + }) + })} + column={{ + ...ReactTableDefaults.column, + Cell: this.renderCell + }} + getTrProps={this.getTrProps} + />
} - ) - } - let nativeWidth = Document.GetNumber(KeyStore.NativeWidth, 0); - return ( -
-
- { - return ( - { - Header: col.Name, - accessor: (doc: Document) => [doc, col], - id: col.Id - }) - })} - column={{ - ...ReactTableDefaults.column, - Cell: this.renderCell - }} - getTrProps={this.getTrProps} - /> -
-
- -
-
- this._parentScaling = nativeWidth > 0 ? r.entry.width / nativeWidth : 1)}> - {({ measureRef }) =>
{content}
} -
+
+
+ {content}
) -- cgit v1.2.3-70-g09d2 From d218c0998b333c9bf6e905e999ce8b0bf02a72f7 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 20 Feb 2019 20:18:21 -0500 Subject: Added undo/redo --- src/client/util/UndoManager.ts | 121 +++++++++++++++++++++ src/client/views/Main.tsx | 24 ++++ .../views/collections/CollectionFreeFormView.tsx | 2 + src/fields/BasicField.ts | 11 +- src/fields/Document.ts | 10 +- src/fields/ListField.ts | 16 ++- 6 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 src/client/util/UndoManager.ts (limited to 'src/client/util') diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts new file mode 100644 index 000000000..34910bac3 --- /dev/null +++ b/src/client/util/UndoManager.ts @@ -0,0 +1,121 @@ +import { observable, action } from "mobx"; +import { Opt } from "../../fields/Field"; + +export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor): any { + let fn: (...args: any[]) => any; + let patchedFn: Opt<(...args: any[]) => any>; + + if (descriptor) { + fn = descriptor.value; + } + + return { + configurable: true, + enumerable: false, + get() { + if (!patchedFn) { + patchedFn = (...args: any[]) => { + try { + UndoManager.StartBatch() + return fn.call(this, ...args) + } finally { + UndoManager.EndBatch() + } + }; + } + return patchedFn; + }, + set(newFn: any) { + patchedFn = undefined; + fn = newFn; + } + } +} +export namespace UndoManager { + export interface UndoEvent { + undo: () => void; + redo: () => void; + } + type UndoBatch = UndoEvent[]; + + let undoStack: UndoBatch[] = observable([]); + let redoStack: UndoBatch[] = observable([]); + let currentBatch: UndoBatch | undefined; + let batchCounter = 0; + let undoing = false; + + export function AddEvent(event: UndoEvent): void { + if (currentBatch && batchCounter && !undoing) { + currentBatch.push(event); + } + } + + export function CanUndo(): boolean { + return undoStack.length > 0; + } + + export function CanRedo(): boolean { + return redoStack.length > 0; + } + + export function StartBatch(): void { + batchCounter++; + if (batchCounter > 0) { + currentBatch = []; + } + } + + export const EndBatch = action(() => { + batchCounter--; + if (batchCounter === 0 && currentBatch && currentBatch.length) { + undoStack.push(currentBatch); + redoStack.length = 0; + currentBatch = undefined; + } + }) + + export function RunInBatch(fn: () => void) { + StartBatch(); + fn(); + EndBatch(); + } + + export const Undo = action(() => { + if (undoStack.length === 0) { + return; + } + + let commands = undoStack.pop(); + if (!commands) { + return; + } + + undoing = true; + for (let i = commands.length - 1; i >= 0; i--) { + commands[i].undo(); + } + undoing = false; + + redoStack.push(commands); + }) + + export const Redo = action(() => { + if (redoStack.length === 0) { + return; + } + + let commands = redoStack.pop(); + if (!commands) { + return; + } + + undoing = true; + for (let i = 0; i < commands.length; i++) { + commands[i].redo(); + } + undoing = false; + + undoStack.push(commands); + }) + +} \ No newline at end of file diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index f44ad0a74..6d3d4d4c2 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -16,6 +16,7 @@ import { MessageStore, DocumentTransfer } from '../../server/Message'; import { Transform } from '../util/Transform'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { FieldWaiting } from '../../fields/Field'; +import { UndoManager } from '../util/UndoManager'; configure({ @@ -94,6 +95,11 @@ Documents.initProtos(() => { x: 0, y: 300, width: 200, height: 200, title: "added note" })); }) + let addSchemaNode = action(() => { + mainfreeform.GetList(KeyStore.Data, []).push(Documents.SchemaDocument([Documents.TextDocument()], { + x: 0, y: 300, width: 200, height: 200, title: "added note" + })); + }) let clearDatabase = action(() => { Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}); @@ -126,12 +132,30 @@ Documents.initProtos(() => { left: '0px', width: '150px' }} onClick={addColNode}>Add Collection + + +
), document.getElementById('root')); }) diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 54757cce5..a6f34dfdf 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -13,6 +13,7 @@ import { Documents } from "../../documents/Documents"; import { FieldWaiting } from "../../../fields/Field"; import { Transform } from "../../util/Transform"; import { DocumentView } from "../nodes/DocumentView"; +import { undoBatch } from "../../util/UndoManager"; @observer export class CollectionFreeFormView extends CollectionViewBase { @@ -37,6 +38,7 @@ export class CollectionFreeFormView extends CollectionViewBase { @computed get resizeScaling() { return this.isAnnotationOverlay ? this.props.Document.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; } + @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { const doc: DocumentView = de.data["document"]; diff --git a/src/fields/BasicField.ts b/src/fields/BasicField.ts index 8728b7145..91977b243 100644 --- a/src/fields/BasicField.ts +++ b/src/fields/BasicField.ts @@ -1,6 +1,7 @@ import { Field, FieldId } from "./Field" import { observable, computed, action } from "mobx"; import { Server } from "../client/Server"; +import { UndoManager } from "../client/util/UndoManager"; export abstract class BasicField extends Field { constructor(data: T, save: boolean, id?: FieldId) { @@ -27,9 +28,15 @@ export abstract class BasicField extends Field { } set Data(value: T) { - if (this.data != value) { - this.data = value; + if (this.data === value) { + return; } + let oldValue = this.data; + this.data = value; + UndoManager.AddEvent({ + undo: () => this.Data = oldValue, + redo: () => this.Data = value + }) Server.UpdateField(this); } diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 0c2ad0fdb..d8522fb5b 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -7,6 +7,7 @@ import { TextField } from "./TextField"; import { ListField } from "./ListField"; import { Server } from "../client/Server"; import { Types } from "../server/Message"; +import { UndoManager } from "../client/util/UndoManager"; export class Document extends Field { public fields: ObservableMap = new ObservableMap(); @@ -127,7 +128,8 @@ export class Document extends Field { @action Set(key: Key, field: Field | undefined): void { - console.log("Assign: " + key.Name + " = " + (field ? field.GetValue() : "") + " (" + (field ? field.Id : "") + ")"); + let old = this.fields.get(key.Id); + let oldField = old ? old.field : undefined; if (field) { this.fields.set(key.Id, { key, field }); this._proxies.set(key.Id, field.Id) @@ -137,6 +139,12 @@ export class Document extends Field { this._proxies.delete(key.Id) // Server.DeleteDocumentField(this, key); } + if (oldField || field) { + UndoManager.AddEvent({ + undo: () => this.Set(key, oldField), + redo: () => this.Set(key, field) + }) + } Server.UpdateField(this); } diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts index 2e192bf90..ad5374dc9 100644 --- a/src/fields/ListField.ts +++ b/src/fields/ListField.ts @@ -1,9 +1,10 @@ import { Field, FieldId, FieldValue, Opt } from "./Field"; import { BasicField } from "./BasicField"; import { Types } from "../server/Message"; -import { observe, action } from "mobx"; +import { observe, action, IArrayChange, IArraySplice, IObservableArray } from "mobx"; import { Server } from "../client/Server"; import { ServerUtils } from "../server/ServerUtil"; +import { UndoManager } from "../client/util/UndoManager"; export class ListField extends BasicField { private _proxies: string[] = [] @@ -13,8 +14,19 @@ export class ListField extends BasicField { if (save) { Server.UpdateField(this); } - observe(this.Data, () => { + observe(this.Data as IObservableArray, (change: IArrayChange | IArraySplice) => { this.updateProxies() + if (change.type == "splice") { + UndoManager.AddEvent({ + undo: () => this.Data.splice(change.index, change.addedCount, ...change.removed), + redo: () => this.Data.splice(change.index, change.removedCount, ...change.added) + }) + } else { + UndoManager.AddEvent({ + undo: () => this.Data[change.index] = change.oldValue, + redo: () => this.Data[change.index] = change.newValue + }) + } Server.UpdateField(this); }) } -- cgit v1.2.3-70-g09d2 From 7339b4b1f8e9f92160b753dfd3d81faf2887c02f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 20 Feb 2019 22:02:56 -0500 Subject: Kind of fixed undo decorator, more work needed to get it to work with arrow functions --- src/client/util/UndoManager.ts | 57 +++++++++++++--------- .../views/collections/CollectionFreeFormView.tsx | 12 +++-- 2 files changed, 44 insertions(+), 25 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 34910bac3..8e9e11a11 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -1,36 +1,49 @@ import { observable, action } from "mobx"; import { Opt } from "../../fields/Field"; -export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor): any { - let fn: (...args: any[]) => any; - let patchedFn: Opt<(...args: any[]) => any>; - - if (descriptor) { - fn = descriptor.value; - } - - return { +function propertyDecorator(target: any, key: string | symbol) { + Object.defineProperty(target, key, { configurable: true, enumerable: false, - get() { - if (!patchedFn) { - patchedFn = (...args: any[]) => { + get: function () { + return 5; + }, + set: function (value: any) { + Object.defineProperty(this, key, { + enumerable: false, + writable: true, + configurable: true, + value: function (...args: any[]) { try { - UndoManager.StartBatch() - return fn.call(this, ...args) + UndoManager.StartBatch(); + return value.apply(this, args); } finally { - UndoManager.EndBatch() + UndoManager.EndBatch(); } - }; - } - return patchedFn; - }, - set(newFn: any) { - patchedFn = undefined; - fn = newFn; + } + }) + } + }) +} +export function undoBatch(target: any, key: string | symbol, descriptor: TypedPropertyDescriptor): any { + if (!descriptor) { + propertyDecorator(target, key); + return; + } + const oldFunction = descriptor.value; + + descriptor.value = function (...args: any[]) { + try { + UndoManager.StartBatch() + return oldFunction.apply(this, args) + } finally { + UndoManager.EndBatch() } } + + return descriptor; } + export namespace UndoManager { export interface UndoEvent { undo: () => void; diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 3a66ebb75..07e9c0899 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -4,7 +4,7 @@ import { action, computed } from "mobx"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DragManager } from "../../util/DragManager"; import "./CollectionFreeFormView.scss"; -import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase"; +import { CollectionViewBase, COLLECTION_BORDER_WIDTH, CollectionViewProps } from "./CollectionViewBase"; import { KeyStore } from "../../../fields/KeyStore"; import { Document } from "../../../fields/Document"; import { ListField } from "../../../fields/ListField"; @@ -38,9 +38,15 @@ export class CollectionFreeFormView extends CollectionViewBase { @computed get resizeScaling() { return this.isAnnotationOverlay ? this.props.Document.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; } - @undoBatch + constructor(props: CollectionViewProps) { + super(props); + + this.drop = this.drop.bind(this); + } + @action - drop = (e: Event, de: DragManager.DropEvent) => { + @undoBatch + drop(e: Event, de: DragManager.DropEvent) { const doc: DocumentView = de.data["document"]; if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) { doc.props.ContainingCollectionView.removeDocument(doc.props.Document); -- cgit v1.2.3-70-g09d2 From 8e56ee4c6f1f16402edd8abee9daa55678117466 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 21 Feb 2019 13:44:58 -0500 Subject: everything works. --- src/client/util/UndoManager.ts | 2 +- src/client/views/Main.tsx | 2 +- src/client/views/collections/CollectionDockingView.tsx | 2 ++ src/client/views/collections/CollectionFreeFormView.tsx | 6 ++---- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 8e9e11a11..edb75b55f 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -25,7 +25,7 @@ function propertyDecorator(target: any, key: string | symbol) { } }) } -export function undoBatch(target: any, key: string | symbol, descriptor: TypedPropertyDescriptor): any { +export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor): any { if (!descriptor) { propertyDecorator(target, key); return; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index f35362fd4..c7a6a44e8 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -76,7 +76,7 @@ Documents.initProtos(() => { var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc)); mainContainer.SetText(KeyStore.Data, JSON.stringify({ content: [{ type: 'row', content: docs }] })); mainContainer.Set(KeyStore.ActiveFrame, mainfreeform); - }, 25); + }, 0); } let addImageNode = action(() => { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index e8a1eaf92..35b130a9a 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -16,6 +16,7 @@ import { Server } from "../../Server"; import { observer } from "mobx-react"; import { KeyStore } from "../../../fields/KeyStore"; import { Opt } from "../../../fields/Field"; +import { undoBatch } from "../../util/UndoManager"; @observer export class CollectionDockingView extends CollectionViewBase { @@ -201,6 +202,7 @@ export class CollectionDockingView extends CollectionViewBase { } } + @undoBatch stateChanged = () => { var json = JSON.stringify(this._goldenLayout.toConfig()); this.props.Document.SetText(KeyStore.Data, json) diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 07e9c0899..986bcdcee 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -40,13 +40,11 @@ export class CollectionFreeFormView extends CollectionViewBase { constructor(props: CollectionViewProps) { super(props); - - this.drop = this.drop.bind(this); } - @action @undoBatch - drop(e: Event, de: DragManager.DropEvent) { + @action + drop = (e: Event, de: DragManager.DropEvent) => { const doc: DocumentView = de.data["document"]; if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) { doc.props.ContainingCollectionView.removeDocument(doc.props.Document); -- cgit v1.2.3-70-g09d2 From 3f9e4363e6601eac175ff71192d414fd6051d921 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 21 Feb 2019 14:13:44 -0500 Subject: clean up --- src/client/util/UndoManager.ts | 1 - .../views/collections/CollectionDockingView.tsx | 21 ++++++++++----------- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 12 +++--------- src/fields/Document.ts | 5 ----- src/fields/ListField.ts | 9 ++++----- 6 files changed, 18 insertions(+), 32 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index edb75b55f..46ad558f3 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -1,5 +1,4 @@ import { observable, action } from "mobx"; -import { Opt } from "../../fields/Field"; function propertyDecorator(target: any, key: string | symbol) { Object.defineProperty(target, key, { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 35b130a9a..60dc24b5f 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -1,22 +1,21 @@ import * as GoldenLayout from "golden-layout"; import 'golden-layout/src/css/goldenlayout-base.css'; import 'golden-layout/src/css/goldenlayout-dark-theme.css'; -import { action, computed, observable, reaction, trace, untracked } from "mobx"; -import { DragManager } from "../../util/DragManager"; -import { DocumentView } from "../nodes/DocumentView"; -import { Document } from "../../../fields/Document"; -import "./CollectionDockingView.scss"; -import { CollectionViewBase, COLLECTION_BORDER_WIDTH, CollectionViewProps } from "./CollectionViewBase"; -import React = require("react"); +import { action, computed, observable, reaction } from "mobx"; +import { observer } from "mobx-react"; import * as ReactDOM from 'react-dom'; import Measure from "react-measure"; +import { Document } from "../../../fields/Document"; +import { FieldId, Opt } from "../../../fields/Field"; +import { KeyStore } from "../../../fields/KeyStore"; import { Utils } from "../../../Utils"; -import { FieldId } from "../../../fields/Field"; import { Server } from "../../Server"; -import { observer } from "mobx-react"; -import { KeyStore } from "../../../fields/KeyStore"; -import { Opt } from "../../../fields/Field"; +import { DragManager } from "../../util/DragManager"; import { undoBatch } from "../../util/UndoManager"; +import { DocumentView } from "../nodes/DocumentView"; +import "./CollectionDockingView.scss"; +import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase"; +import React = require("react"); @observer export class CollectionDockingView extends CollectionViewBase { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f3217d55d..5ec288b13 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -1,5 +1,5 @@ import React = require("react") -import { action, computed, observable } from "mobx"; +import { action, observable } from "mobx"; import { observer } from "mobx-react"; import Measure from "react-measure"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7cad6ffc1..5568935fa 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,17 +1,11 @@ -import { action, computed } from "mobx"; +import { computed } from "mobx"; import { observer } from "mobx-react"; import { KeyStore } from "../../../fields/KeyStore"; import { NumberField } from "../../../fields/NumberField"; -import { DragManager } from "../../util/DragManager"; -import { SelectionManager } from "../../util/SelectionManager"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"; -import { ContextMenu } from "../ContextMenu"; +import { Transform } from "../../util/Transform"; +import { DocumentView, DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import React = require("react"); -import { DocumentView, DocumentViewProps } from "./DocumentView"; -import { Utils } from "../../../Utils"; -import { Transform } from "../../util/Transform"; @observer diff --git a/src/fields/Document.ts b/src/fields/Document.ts index d8522fb5b..6667485b6 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -152,16 +152,13 @@ export class Document extends Field { SetData(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) { let field = this.Get(key, true); - //if (field != WAITING) { // do we want to wait for the field to come back from the server to set it, or do we overwrite? if (field instanceof ctor) { field.Data = value; - // Server.SetFieldValue(field, value); } else if (!field || replaceWrongType) { let newField = new ctor(); newField.Data = value; this.Set(key, newField); } - //} } @action @@ -213,14 +210,12 @@ export class Document extends Field { } ToJson(): { type: Types, data: [string, string][], _id: string } { - // console.log(this.fields) let fields: [string, string][] = [] this._proxies.forEach((field, key) => { if (field) { fields.push([key, field as string]) } }); - // console.log(fields) return { type: Types.Document, diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts index ad5374dc9..75c2eb343 100644 --- a/src/fields/ListField.ts +++ b/src/fields/ListField.ts @@ -1,10 +1,9 @@ -import { Field, FieldId, FieldValue, Opt } from "./Field"; -import { BasicField } from "./BasicField"; -import { Types } from "../server/Message"; -import { observe, action, IArrayChange, IArraySplice, IObservableArray } from "mobx"; +import { action, IArrayChange, IArraySplice, IObservableArray, observe } from "mobx"; import { Server } from "../client/Server"; -import { ServerUtils } from "../server/ServerUtil"; import { UndoManager } from "../client/util/UndoManager"; +import { Types } from "../server/Message"; +import { BasicField } from "./BasicField"; +import { Field, FieldId } from "./Field"; export class ListField extends BasicField { private _proxies: string[] = [] -- cgit v1.2.3-70-g09d2 From 9b23c5123abf42c3751938d831556cdb94ad3951 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 22 Feb 2019 13:42:25 -0500 Subject: moved common code into CollectionViewBase. --- src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 1 + .../views/collections/CollectionDockingView.tsx | 3 +- .../views/collections/CollectionFreeFormView.tsx | 59 ++-------------- .../views/collections/CollectionSchemaView.tsx | 13 ++-- src/client/views/collections/CollectionView.tsx | 20 +----- .../views/collections/CollectionViewBase.tsx | 82 ++++++++++++++++++++++ 7 files changed, 102 insertions(+), 78 deletions(-) create mode 100644 src/client/views/collections/CollectionViewBase.tsx (limited to 'src/client/util') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index bfa6cb7a9..156a09316 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -13,7 +13,7 @@ import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormV import { FieldId } from "../../fields/Field"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; -interface DocumentOptions { +export interface DocumentOptions { x?: number; y?: number; width?: number; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 6d5fe12a7..eb4b3aeaa 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -44,6 +44,7 @@ export namespace DragManager { drop: (e: Event, de: DropEvent) => void; } + export function MakeDropTarget(element: HTMLElement, options: DropOptions): DragDropDisposer { if ("canDrop" in element.dataset) { throw new Error("Element is already droppable, can't make it droppable again"); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 752007439..857af023d 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -14,8 +14,9 @@ import { DragManager } from "../../util/DragManager"; import { undoBatch } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import "./CollectionDockingView.scss"; -import { CollectionViewProps, COLLECTION_BORDER_WIDTH, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import React = require("react"); +import { SubCollectionViewProps } from "./CollectionViewBase"; @observer export class CollectionDockingView extends React.Component { diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index b78b1a3b6..b8312aff7 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -4,20 +4,18 @@ import { action, computed, trace } from "mobx"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DragManager } from "../../util/DragManager"; import "./CollectionFreeFormView.scss"; -import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { KeyStore } from "../../../fields/KeyStore"; import { Document } from "../../../fields/Document"; import { ListField } from "../../../fields/ListField"; -import { NumberField } from "../../../fields/NumberField"; -import { Documents } from "../../documents/Documents"; import { FieldWaiting } from "../../../fields/Field"; import { Transform } from "../../util/Transform"; import { DocumentView } from "../nodes/DocumentView"; import { undoBatch } from "../../util/UndoManager"; -import { jSXElement } from "babel-types"; +import { CollectionViewBase, SubCollectionViewProps } from "./CollectionViewBase"; @observer -export class CollectionFreeFormView extends React.Component { +export class CollectionFreeFormView extends CollectionViewBase { private _canvasRef = React.createRef(); private _lastX: number = 0; private _lastY: number = 0; @@ -45,13 +43,8 @@ export class CollectionFreeFormView extends React.Component { + super.drop(e, de); const doc: DocumentView = de.data["document"]; - if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) { - if (doc.props.RemoveDocument) { - doc.props.RemoveDocument(doc.props.Document); - } - this.props.addDocument(doc.props.Document); - } const xOffset = de.data["xOffset"] as number || 0; const yOffset = de.data["yOffset"] as number || 0; //this should be able to use translate and scale methods on an Identity transform, no? @@ -62,21 +55,6 @@ export class CollectionFreeFormView extends React.Component { - if (this.dropDisposer) { - this.dropDisposer(); - } - if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { - handlers: { - drop: this.drop - } - }); - } } @action @@ -148,36 +126,11 @@ export class CollectionFreeFormView extends React.Component { - e.stopPropagation() - e.preventDefault() - let fReader = new FileReader() - let file = e.dataTransfer.items[0].getAsFile(); - let that = this; const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0); const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0); let x = e.pageX - panx let y = e.pageY - pany - - fReader.addEventListener("load", action("drop", () => { - if (fReader.result) { - let url = "" + fReader.result; - let doc = Documents.ImageDocument(url, { - x: x, y: y - }) - let docs = that.props.Document.GetT(KeyStore.Data, ListField); - if (docs != FieldWaiting) { - if (!docs) { - docs = new ListField(); - that.props.Document.Set(KeyStore.Data, docs) - } - docs.Data.push(doc); - } - } - }), false) - - if (file) { - fReader.readAsDataURL(file) - } + super.onDrop(e, { x: x, y: y }); } onDragOver = (): void => { @@ -249,7 +202,7 @@ export class CollectionFreeFormView extends React.Component e.preventDefault()} - onDrop={this.onDrop} + onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px`, }} ref={this.createDropTarget}> diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f25e721c0..df732308a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -5,7 +5,7 @@ import Measure from "react-measure"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; import "react-table/react-table.css"; import { Document } from "../../../fields/Document"; -import { Field } from "../../../fields/Field"; +import { Field, FieldWaiting } from "../../../fields/Field"; import { KeyStore } from "../../../fields/KeyStore"; import { CompileScript, ToField } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; @@ -13,10 +13,11 @@ import { EditableView } from "../EditableView"; import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; -import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; +import { CollectionViewBase } from "./CollectionViewBase"; @observer -export class CollectionSchemaView extends React.Component { +export class CollectionSchemaView extends CollectionViewBase { private _mainCont = React.createRef(); private DIVIDER_WIDTH = 5; @@ -117,6 +118,7 @@ export class CollectionSchemaView extends React.Component { return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._parentScaling); } @@ -181,7 +183,10 @@ export class CollectionSchemaView extends React.Component
-
+
this.onDrop(e, {})} + ref={this.createDropTarget} + style={{ position: "relative", float: "left", width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)`, height: "100%" }}> {content}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 651d85879..ff1803ec3 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,36 +1,18 @@ import { action, computed } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; -import { Key } from "../../../fields/Key"; import { ListField } from "../../../fields/ListField"; import { SelectionManager } from "../../util/SelectionManager"; import { ContextMenu } from "../ContextMenu"; import React = require("react"); -import { Transform } from "../../util/Transform"; import { KeyStore } from "../../../fields/KeyStore"; import { NumberField } from "../../../fields/NumberField"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; import { CollectionDockingView } from "./CollectionDockingView"; import { CollectionSchemaView } from "./CollectionSchemaView"; -import { Opt } from "../../../fields/Field"; +import { CollectionViewProps } from "./CollectionViewBase"; -export interface CollectionViewProps { - fieldKey: Key; - Document: Document; - ScreenToLocalTransform: () => Transform; - isSelected: () => boolean; - isTopMost: boolean; - select: (ctrlPressed: boolean) => void; - BackgroundView?: () => JSX.Element; -} - -export interface SubCollectionViewProps extends CollectionViewProps { - active: () => boolean; - addDocument: (doc: Document) => void; - removeDocument: (doc: Document) => boolean; - CollectionView: Opt; -} export enum CollectionViewType { Invalid, diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx new file mode 100644 index 000000000..06de56383 --- /dev/null +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -0,0 +1,82 @@ +import { action, computed } from "mobx"; +import { Document } from "../../../fields/Document"; +import { ListField } from "../../../fields/ListField"; +import React = require("react"); +import { KeyStore } from "../../../fields/KeyStore"; +import { Opt, FieldWaiting } from "../../../fields/Field"; +import { undoBatch } from "../../util/UndoManager"; +import { DragManager } from "../../util/DragManager"; +import { DocumentView } from "../nodes/DocumentView"; +import { Documents, DocumentOptions } from "../../documents/Documents"; +import { Key } from "../../../fields/Key"; +import { Transform } from "../../util/Transform"; + + +export interface CollectionViewProps { + fieldKey: Key; + Document: Document; + ScreenToLocalTransform: () => Transform; + isSelected: () => boolean; + isTopMost: boolean; + select: (ctrlPressed: boolean) => void; + BackgroundView?: () => JSX.Element; +} +export interface SubCollectionViewProps extends CollectionViewProps { + active: () => boolean; + addDocument: (doc: Document) => void; + removeDocument: (doc: Document) => boolean; + CollectionView: any; +} + +export class CollectionViewBase extends React.Component { + private dropDisposer?: DragManager.DragDropDisposer; + protected createDropTarget = (ele: HTMLDivElement) => { + if (this.dropDisposer) { + this.dropDisposer(); + } + if (ele) { + this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + } + } + + @undoBatch + @action + protected drop(e: Event, de: DragManager.DropEvent) { + const doc: DocumentView = de.data["document"]; + if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) { + if (doc.props.RemoveDocument) { + doc.props.RemoveDocument(doc.props.Document); + } + this.props.addDocument(doc.props.Document); + } + e.stopPropagation(); + } + + @action + protected onDrop(e: React.DragEvent, options: DocumentOptions): void { + e.stopPropagation() + e.preventDefault() + let fReader = new FileReader() + let file = e.dataTransfer.items[0].getAsFile(); + let that = this; + + fReader.addEventListener("load", action("drop", () => { + if (fReader.result) { + let url = "" + fReader.result; + let doc = Documents.ImageDocument(url, options) + let docs = that.props.Document.GetT(KeyStore.Data, ListField); + if (docs != FieldWaiting) { + if (!docs) { + docs = new ListField(); + that.props.Document.Set(KeyStore.Data, docs) + } + docs.Data.push(doc); + } + } + }), false) + + if (file) { + fReader.readAsDataURL(file) + } + } +} -- cgit v1.2.3-70-g09d2