diff options
author | bobzel <zzzman@gmail.com> | 2019-02-05 23:19:26 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2019-02-05 23:19:26 -0500 |
commit | e59dbb02175ec394a35c496201da71c90cd6a50a (patch) | |
tree | cf56fe399dca0fb64fece2ee1ed22044d95ea25c /src | |
parent | 4ac7a62d813738b0047caefbcf40d3063ec9e6c1 (diff) |
mostly working version, but confused about LayoutKeys needing to inquire value seemingly unecessarily
Diffstat (limited to 'src')
-rw-r--r-- | src/Main.tsx | 2 | ||||
-rw-r--r-- | src/documents/Documents.ts | 2 | ||||
-rw-r--r-- | src/fields/FieldUpdatedArgs.ts | 27 | ||||
-rw-r--r-- | src/stores/NodeCollectionStore.ts | 26 | ||||
-rw-r--r-- | src/stores/NodeStore.ts | 24 | ||||
-rw-r--r-- | src/stores/StaticTextNodeStore.ts | 16 | ||||
-rw-r--r-- | src/stores/VideoNodeStore.ts | 17 | ||||
-rw-r--r-- | src/views/collections/CollectionDockingView.tsx | 4 | ||||
-rw-r--r-- | src/views/collections/CollectionFreeFormView.tsx | 2 | ||||
-rw-r--r-- | src/views/collections/CollectionSchemaView.tsx | 2 | ||||
-rw-r--r-- | src/views/nodes/CollectionFreeFormDocumentView.tsx | 5 | ||||
-rw-r--r-- | src/views/nodes/DocumentView.tsx | 13 | ||||
-rw-r--r-- | src/views/nodes/FieldTextBox.scss | 14 | ||||
-rw-r--r-- | src/views/nodes/ImageBox.tsx | 48 | ||||
-rw-r--r-- | src/views/nodes/TextNodeView.tsx | 28 | ||||
-rw-r--r-- | src/views/nodes/TopBar.tsx | 46 | ||||
-rw-r--r-- | src/views/nodes/VideoNodeView.scss | 5 | ||||
-rw-r--r-- | src/views/nodes/VideoNodeView.tsx | 29 |
18 files changed, 275 insertions, 35 deletions
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(( <div style={{ position: "absolute", width: "100%", height: "100%" }}> - <DocumentView Document={mainContainer} ContainingCollectionView={undefined} DocumentView={undefined} Data={mainContainer.GetField(KeyStore.Data)} /> + <DocumentView Document={mainContainer} ContainingCollectionView={undefined} DocumentView={undefined} /> <DocumentDecorations /> <ContextMenu /> </div>), 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('<div style={"background-image: " + {Data}} />')); + // 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<Field>; + newValue: Opt<Field>; + + 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<NodeStore>(); + + @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<StaticTextNodeStore>) { + 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<VideoNodeStore>) { + 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 (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} DocumentView={undefined} Data={data} />); + return (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} DocumentView={undefined} />); } } if (component === "text") { @@ -242,7 +242,7 @@ export class CollectionDockingView extends CollectionViewBase { setTimeout(function () { var data = state.doc.GetField(KeyStore.Data); ReactDOM.render(( - <DocumentView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} DocumentView={undefined} Data={data} /> + <DocumentView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} DocumentView={undefined} /> ), 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 { <div className="node-container" ref={this._nodeContainerRef}> {value.map(doc => { - return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentView={undefined} Data={data} />); + return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentView={undefined} />); })} </div> </div> 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 = (<DocumentView Document={children[this.selectedIndex]} DocumentView={undefined} ContainingCollectionView={this} Data={data} />) + content = (<DocumentView Document={children[this.selectedIndex]} DocumentView={undefined} ContainingCollectionView={this} />) } else { content = <div /> } 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 ( <div className="node" ref={this._mainCont} style={{ transform: freestyling ? this.transform : "", @@ -220,7 +219,7 @@ export class CollectionFreeFormDocumentView extends DocumentView { onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown}> - <DocumentView {...this.props} DocumentView={this} Data={data} /> + <DocumentView {...this.props} DocumentView={this} /> </div> ); } 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<DocumentView> // needed only to set ContainingDocumentView on CollectionViewProps when invoked from JsxParser -- is there a better way? ContainingCollectionView: Opt<CollectionViewBase>; - Data: any; } @observer export class DocumentView extends React.Component<DocumentViewProps> { @@ -128,19 +127,19 @@ export class DocumentView extends React.Component<DocumentViewProps> { 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 ( <div className="node" ref={this._mainCont} style={{ width: "100%", height: "100%", }}> <JsxParser diff --git a/src/views/nodes/FieldTextBox.scss b/src/views/nodes/FieldTextBox.scss new file mode 100644 index 000000000..b6ce2fabc --- /dev/null +++ b/src/views/nodes/FieldTextBox.scss @@ -0,0 +1,14 @@ +.ProseMirror { + margin-top: -1em; + width: 100%; + height: 100%; +} + +.ProseMirror:focus { + outline: none !important +} + +.fieldTextBox-cont { + background: white; + padding: 1vw; +}
\ No newline at end of file diff --git a/src/views/nodes/ImageBox.tsx b/src/views/nodes/ImageBox.tsx index fa55c6811..9b086d373 100644 --- a/src/views/nodes/ImageBox.tsx +++ b/src/views/nodes/ImageBox.tsx @@ -17,7 +17,7 @@ interface ImageBoxState { export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> { - public static LayoutString() { return FieldView.LayoutString("ImageBox"); } + public static LayoutString() { return FieldView.LayoutString("ImageBox DataVal={Data} "); } private _ref: React.RefObject<HTMLDivElement>; private _downX: number = 0; private _downY: number = 0; @@ -60,33 +60,41 @@ export class ImageBox extends React.Component<FieldViewProps, ImageBoxState> { 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 (<Lightbox + mainSrc={images[photoIndex]} + nextSrc={images[(photoIndex + 1) % images.length]} + prevSrc={images[(photoIndex + images.length - 1) % images.length]} + onCloseRequest={() => 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 (<Lightbox - mainSrc={images[photoIndex]} - nextSrc={images[(photoIndex + 1) % images.length]} - prevSrc={images[(photoIndex + images.length - 1) % images.length]} - onCloseRequest={() => this.setState({ isOpen: false })} - onMovePrevRequest={() => - this.setState({ photoIndex: (photoIndex + images.length - 1) % images.length, }) - } - onMoveNextRequest={() => - this.setState({ photoIndex: (photoIndex + 1) % images.length, }) - } - />) - } - } + return ( <div className="imageBox-cont" onPointerDown={this.onPointerDown} ref={this._ref} > <img src={path} width="100%" alt="Image not found" /> - {lightbox()} + {this.lightbox(path)} </div>) } }
\ 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<IProps> { + + render() { + let store = this.props.store; + return ( + <div className="node text-node" style={{transform: store.Transform}}> + <TopBar store={store} /> + <div className="scroll-box"> + <div className="content"> + <h3 className="title">{store.Title}</h3> + <p className="paragraph">{store.Text}</p> + </div> + </div> + </div> + ); + } +}
\ 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<IProps> { + + 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 <div className="top" onPointerDown={this.onPointerDown}></div> + } +} 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<IProps> { + + render() { + let store = this.props.store; + return ( + <div className="node text-node" style={{ transform: store.Transform }}> + <TopBar store={store} /> + <div className="scroll-box"> + <div className="content"> + <h3 className="title">{store.Title}</h3> + <video src={store.Url} controls /> + </div> + </div> + </div> + ); + } +}
\ No newline at end of file |