From e59dbb02175ec394a35c496201da71c90cd6a50a Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 5 Feb 2019 23:19:26 -0500 Subject: mostly working version, but confused about LayoutKeys needing to inquire value seemingly unecessarily --- src/Main.tsx | 2 +- src/documents/Documents.ts | 2 + src/fields/FieldUpdatedArgs.ts | 27 ++++++++++++ src/stores/NodeCollectionStore.ts | 26 ++++++++++++ src/stores/NodeStore.ts | 24 +++++++++++ src/stores/StaticTextNodeStore.ts | 16 ++++++++ src/stores/VideoNodeStore.ts | 17 ++++++++ src/views/collections/CollectionDockingView.tsx | 4 +- src/views/collections/CollectionFreeFormView.tsx | 2 +- src/views/collections/CollectionSchemaView.tsx | 2 +- src/views/nodes/CollectionFreeFormDocumentView.tsx | 5 +-- src/views/nodes/DocumentView.tsx | 13 +++--- src/views/nodes/FieldTextBox.scss | 14 +++++++ src/views/nodes/ImageBox.tsx | 48 +++++++++++++--------- src/views/nodes/TextNodeView.tsx | 28 +++++++++++++ src/views/nodes/TopBar.tsx | 46 +++++++++++++++++++++ src/views/nodes/VideoNodeView.scss | 5 +++ src/views/nodes/VideoNodeView.tsx | 29 +++++++++++++ 18 files changed, 275 insertions(+), 35 deletions(-) create mode 100644 src/fields/FieldUpdatedArgs.ts create mode 100644 src/stores/NodeCollectionStore.ts create mode 100644 src/stores/NodeStore.ts create mode 100644 src/stores/StaticTextNodeStore.ts create mode 100644 src/stores/VideoNodeStore.ts create mode 100644 src/views/nodes/FieldTextBox.scss create mode 100644 src/views/nodes/TextNodeView.tsx create mode 100644 src/views/nodes/TopBar.tsx create mode 100644 src/views/nodes/VideoNodeView.scss create mode 100644 src/views/nodes/VideoNodeView.tsx (limited to 'src') diff --git a/src/Main.tsx b/src/Main.tsx index 2b805071f..de4a1de5d 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -80,7 +80,7 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) { ReactDOM.render((
- +
), diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts index 869e9ab90..c51feedf5 100644 --- a/src/documents/Documents.ts +++ b/src/documents/Documents.ts @@ -117,7 +117,9 @@ export namespace Documents { imageProto.SetFieldValue(KeyStore.Height, 300, NumberField); imageProto.SetFieldValue(KeyStore.Layout, ImageBox.LayoutString(), TextField); // imageProto.SetField(KeyStore.Layout, new TextField('
')); + // bcz: use LayoutKeys or LayoutFields? imageProto.SetFieldValue(KeyStore.LayoutKeys, [KeyStore.Data], ListField); + //imageProto.SetFieldValue(KeyStore.LayoutFields, [KeyStore.Data], ListField); } return imageProto; } diff --git a/src/fields/FieldUpdatedArgs.ts b/src/fields/FieldUpdatedArgs.ts new file mode 100644 index 000000000..23ccf2a5a --- /dev/null +++ b/src/fields/FieldUpdatedArgs.ts @@ -0,0 +1,27 @@ +import { Field, Opt } from "./Field"; +import { Document } from "./Document"; +import { Key } from "./Key"; + +export enum FieldUpdatedAction { + Add, + Remove, + Replace, + Update +} + +export interface FieldUpdatedArgs { + field: Field; + action: FieldUpdatedAction; +} + +export interface DocumentUpdatedArgs { + field: Document; + key: Key; + + oldValue: Opt; + newValue: Opt; + + fieldArgs?: FieldUpdatedArgs; + + action: FieldUpdatedAction; +} diff --git a/src/stores/NodeCollectionStore.ts b/src/stores/NodeCollectionStore.ts new file mode 100644 index 000000000..7fac83d51 --- /dev/null +++ b/src/stores/NodeCollectionStore.ts @@ -0,0 +1,26 @@ +import { computed, observable, action } from "mobx"; +import { NodeStore } from "./NodeStore"; +import { Document } from "../fields/Document"; + +export class NodeCollectionStore extends NodeStore { + + @observable + public Scale: number = 1; + + @observable + public Nodes: NodeStore[] = new Array(); + + @observable + public Docs: Document[] = []; + + @computed + public get Transform(): string { + const halfWidth = window.innerWidth / 2, halfHeight = window.innerHeight / 2; + return `translate(${this.X + halfWidth}px, ${this.Y + halfHeight}px) scale(${this.Scale}) translate(${-halfWidth}px, ${-halfHeight}px)`; + } + + @action + public AddNodes(stores: NodeStore[]): void { + stores.forEach(store => this.Nodes.push(store)); + } +} \ No newline at end of file diff --git a/src/stores/NodeStore.ts b/src/stores/NodeStore.ts new file mode 100644 index 000000000..6a734cf44 --- /dev/null +++ b/src/stores/NodeStore.ts @@ -0,0 +1,24 @@ +import { computed, observable } from "mobx"; +import { Utils } from "../Utils"; + +export class NodeStore { + + public Id: string = Utils.GenerateGuid(); + + @observable + public X: number = 0; + + @observable + public Y: number = 0; + + @observable + public Width: number = 0; + + @observable + public Height: number = 0; + + @computed + public get Transform(): string { + return "translate(" + this.X + "px, " + this.Y + "px)"; + } +} \ No newline at end of file diff --git a/src/stores/StaticTextNodeStore.ts b/src/stores/StaticTextNodeStore.ts new file mode 100644 index 000000000..7c342a7a2 --- /dev/null +++ b/src/stores/StaticTextNodeStore.ts @@ -0,0 +1,16 @@ +import { observable } from "mobx"; +import { NodeStore } from "./NodeStore"; + +export class StaticTextNodeStore extends NodeStore { + + constructor(initializer: Partial) { + super(); + Object.assign(this, initializer); + } + + @observable + public Title: string = ""; + + @observable + public Text: string = ""; +} \ No newline at end of file diff --git a/src/stores/VideoNodeStore.ts b/src/stores/VideoNodeStore.ts new file mode 100644 index 000000000..e5187ab07 --- /dev/null +++ b/src/stores/VideoNodeStore.ts @@ -0,0 +1,17 @@ +import { observable } from "mobx"; +import { NodeStore } from "./NodeStore"; + +export class VideoNodeStore extends NodeStore { + + constructor(initializer: Partial) { + super(); + Object.assign(this, initializer); + } + + @observable + public Title: string = ""; + + @observable + public Url: string = ""; + +} \ No newline at end of file diff --git a/src/views/collections/CollectionDockingView.tsx b/src/views/collections/CollectionDockingView.tsx index adb885859..4bbbeeecd 100644 --- a/src/views/collections/CollectionDockingView.tsx +++ b/src/views/collections/CollectionDockingView.tsx @@ -100,7 +100,7 @@ export class CollectionDockingView extends CollectionViewBase { for (var i: number = 0; i < value.length; i++) { if (value[i].Id === component) { var data = value[i].GetField(KeyStore.Data); - return (); + return (); } } if (component === "text") { @@ -242,7 +242,7 @@ export class CollectionDockingView extends CollectionViewBase { setTimeout(function () { var data = state.doc.GetField(KeyStore.Data); ReactDOM.render(( - + ), document.getElementById(containingDiv) ); diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx index ad470f9e2..d48d096ce 100644 --- a/src/views/collections/CollectionFreeFormView.tsx +++ b/src/views/collections/CollectionFreeFormView.tsx @@ -206,7 +206,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
{value.map(doc => { - return (); + return (); })}
diff --git a/src/views/collections/CollectionSchemaView.tsx b/src/views/collections/CollectionSchemaView.tsx index bde727fea..59d54e8c4 100644 --- a/src/views/collections/CollectionSchemaView.tsx +++ b/src/views/collections/CollectionSchemaView.tsx @@ -75,7 +75,7 @@ export class CollectionSchemaView extends CollectionViewBase { let content; if (this.selectedIndex != -1) { var data = this.props.DocumentForCollection.GetField(KS.Data); - content = () + content = () } else { content =
} diff --git a/src/views/nodes/CollectionFreeFormDocumentView.tsx b/src/views/nodes/CollectionFreeFormDocumentView.tsx index 9f13733c9..06ea0c64b 100644 --- a/src/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/views/nodes/CollectionFreeFormDocumentView.tsx @@ -207,8 +207,7 @@ export class CollectionFreeFormDocumentView extends DocumentView { render() { var freestyling = this.props.ContainingCollectionView instanceof CollectionFreeFormView; - let data = this.props.Document.GetFieldT(KeyStore.Data, ImageField); - console.log("CollectionFFDocView " + this.props.Document.Title + "<" + data + "> x=" + this.x); + console.log("CollectionFFDocView " + this.props.Document.Title); return (
- +
); } diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index 94fe0440f..69184cf16 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -21,7 +21,6 @@ export interface DocumentViewProps { Document: Document; DocumentView: Opt // needed only to set ContainingDocumentView on CollectionViewProps when invoked from JsxParser -- is there a better way? ContainingCollectionView: Opt; - Data: any; } @observer export class DocumentView extends React.Component { @@ -128,19 +127,19 @@ export class DocumentView extends React.Component { render() { - let doc = this.props.Document; let bindings = { ...this.props } as any; for (const key of this.layoutKeys) { + //let val = this.props.Document.GetField(key); // bcz: ARGH! Why do I need to call this here? (e.g., it's needed and used in ImageBox- shouldn't that trigger a re-render?) bindings[key.Name + "Key"] = key; - let val = this.props.Document.GetField(key); } - if (bindings.DocumentView === undefined) - bindings.DocumentView = this; for (const key of this.layoutFields) { - let field = doc.GetField(key); + let field = this.props.Document.GetField(key); bindings[key.Name] = field && field != WAITING ? field.GetValue() : field; } - console.log("DocumentView Rendering " + doc.Title + " data = " + this.props.Data); + if (bindings.DocumentView === undefined) { + bindings.DocumentView = this; + } + console.log("DocumentView Rendering " + this.props.Document.Title); return (
{ - public static LayoutString() { return FieldView.LayoutString("ImageBox"); } + public static LayoutString() { return FieldView.LayoutString("ImageBox DataVal={Data} "); } private _ref: React.RefObject; private _downX: number = 0; private _downY: number = 0; @@ -60,33 +60,41 @@ export class ImageBox extends React.Component { e.stopPropagation(); } + lightbox = (path: string) => { + const images = [path, "http://www.cs.brown.edu/~bcz/face.gif"]; + const { photoIndex } = this.state; + if (this.state.isOpen && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) { + return ( this.setState({ isOpen: false })} + onMovePrevRequest={() => + this.setState({ photoIndex: (photoIndex + images.length - 1) % images.length, }) + } + onMoveNextRequest={() => + this.setState({ photoIndex: (photoIndex + 1) % images.length, }) + } + />) + } + } + render() { + + // bcz: use LayoutFields (here) or LayoutKeys (below)? + // let field = (this.props as any).DataVal;//this.props.doc.GetFieldT(this.props.fieldKey, ImageField); + // let path = field == WAITING ? "https://image.flaticon.com/icons/svg/66/66163.svg" : + // field instanceof URL ? field.href : ""; + let field = this.props.doc.GetFieldT(this.props.fieldKey, ImageField); let path = field == WAITING ? "https://image.flaticon.com/icons/svg/66/66163.svg" : field instanceof ImageField ? field.Data.href : ""; console.log("ImageBox Rendering " + this.props.doc.Title); - var lightbox = () => { - const images = [path, "http://www.cs.brown.edu/~bcz/face.gif"]; - const { photoIndex } = this.state; - if (this.state.isOpen && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) { - return ( this.setState({ isOpen: false })} - onMovePrevRequest={() => - this.setState({ photoIndex: (photoIndex + images.length - 1) % images.length, }) - } - onMoveNextRequest={() => - this.setState({ photoIndex: (photoIndex + 1) % images.length, }) - } - />) - } - } + return (
Image not found - {lightbox()} + {this.lightbox(path)}
) } } \ No newline at end of file diff --git a/src/views/nodes/TextNodeView.tsx b/src/views/nodes/TextNodeView.tsx new file mode 100644 index 000000000..ab762df12 --- /dev/null +++ b/src/views/nodes/TextNodeView.tsx @@ -0,0 +1,28 @@ +import {observer} from "mobx-react"; +import {StaticTextNodeStore} from "../../stores/StaticTextNodeStore"; +import "./NodeView.scss"; +import {TopBar} from "./TopBar"; +import React = require("react"); + +interface IProps { + store: StaticTextNodeStore; +} + +@observer +export class TextNodeView extends React.Component { + + render() { + let store = this.props.store; + return ( +
+ +
+
+

{store.Title}

+

{store.Text}

+
+
+
+ ); + } +} \ No newline at end of file diff --git a/src/views/nodes/TopBar.tsx b/src/views/nodes/TopBar.tsx new file mode 100644 index 000000000..bb126e8b5 --- /dev/null +++ b/src/views/nodes/TopBar.tsx @@ -0,0 +1,46 @@ +import { observer } from "mobx-react"; +import { NodeStore } from "../../stores/NodeStore"; +import "./NodeView.scss"; +import React = require("react"); + +interface IProps { + store: NodeStore; +} + +@observer +export class TopBar extends React.Component { + + private _isPointerDown = false; + + onPointerDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + this._isPointerDown = true; + document.removeEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointerup", this.onPointerUp); + } + + onPointerUp = (e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + this._isPointerDown = false; + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + } + + onPointerMove = (e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + if (!this._isPointerDown) { + return; + } + this.props.store.X += e.movementX; + this.props.store.Y += e.movementY; + } + + render() { + return
+ } +} diff --git a/src/views/nodes/VideoNodeView.scss b/src/views/nodes/VideoNodeView.scss new file mode 100644 index 000000000..f412c3519 --- /dev/null +++ b/src/views/nodes/VideoNodeView.scss @@ -0,0 +1,5 @@ +.node { + video { + width: 100%; + } +} \ No newline at end of file diff --git a/src/views/nodes/VideoNodeView.tsx b/src/views/nodes/VideoNodeView.tsx new file mode 100644 index 000000000..0a7b3d174 --- /dev/null +++ b/src/views/nodes/VideoNodeView.tsx @@ -0,0 +1,29 @@ +import { observer } from "mobx-react"; +import { VideoNodeStore } from "../../stores/VideoNodeStore"; +import "./NodeView.scss"; +import { TopBar } from "./TopBar"; +import "./VideoNodeView.scss"; +import React = require("react"); + +interface IProps { + store: VideoNodeStore; +} + +@observer +export class VideoNodeView extends React.Component { + + render() { + let store = this.props.store; + return ( +
+ +
+
+

{store.Title}

+
+
+
+ ); + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2