aboutsummaryrefslogtreecommitdiff
path: root/src/views
diff options
context:
space:
mode:
authormadelinegr <mgriswold99@gmail.com>2019-02-12 18:55:11 -0500
committermadelinegr <mgriswold99@gmail.com>2019-02-12 18:55:11 -0500
commit1d667d19f5402dc9f9069e0a57008dac96f6de2a (patch)
tree59572ebc84ae0dea9780c96a6d43a811a21fed10 /src/views
parent7a93f60c9529e5d175e617fc7c07145a9b33e572 (diff)
set up web box classes
Diffstat (limited to 'src/views')
-rw-r--r--src/views/freeformcanvas/CollectionFreeFormView.scss15
-rw-r--r--src/views/freeformcanvas/CollectionFreeFormView.tsx98
-rw-r--r--src/views/freeformcanvas/FreeFormCanvas.scss15
-rw-r--r--src/views/freeformcanvas/FreeFormCanvas.tsx86
-rw-r--r--src/views/nodes/DocumentView.tsx134
-rw-r--r--src/views/nodes/FieldTextBox.tsx117
-rw-r--r--src/views/nodes/NodeView.scss31
-rw-r--r--src/views/nodes/RichTextView.tsx0
-rw-r--r--src/views/nodes/TextNodeView.tsx28
-rw-r--r--src/views/nodes/TopBar.tsx46
-rw-r--r--src/views/nodes/VideoNodeView.scss5
-rw-r--r--src/views/nodes/VideoNodeView.tsx29
12 files changed, 604 insertions, 0 deletions
diff --git a/src/views/freeformcanvas/CollectionFreeFormView.scss b/src/views/freeformcanvas/CollectionFreeFormView.scss
new file mode 100644
index 000000000..cb4805eb3
--- /dev/null
+++ b/src/views/freeformcanvas/CollectionFreeFormView.scss
@@ -0,0 +1,15 @@
+.collectionfreeformview-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+
+ .collectionfreeformview {
+ position: absolute;
+ top: 0;
+ left: 0;
+ }
+}
+
diff --git a/src/views/freeformcanvas/CollectionFreeFormView.tsx b/src/views/freeformcanvas/CollectionFreeFormView.tsx
new file mode 100644
index 000000000..d5343536d
--- /dev/null
+++ b/src/views/freeformcanvas/CollectionFreeFormView.tsx
@@ -0,0 +1,98 @@
+import { observer } from "mobx-react";
+import { Key, KeyStore } from "../../fields/Key";
+import "./FreeFormCanvas.scss";
+import React = require("react");
+import { action } from "mobx";
+import { Document } from "../../fields/Document";
+import { DocumentViewModel } from "../../viewmodels/DocumentViewModel";
+import { DocumentView } from "../nodes/DocumentView";
+import { ListField } from "../../fields/ListField";
+import { NumberField } from "../../fields/NumberField";
+import { SSL_OP_SINGLE_DH_USE } from "constants";
+
+interface IProps {
+ fieldKey: Key;
+ doc: Document;
+}
+
+@observer
+export class CollectionFreeFormView extends React.Component<IProps> {
+
+ private _isPointerDown: boolean = false;
+
+ constructor(props: IProps) {
+ super(props);
+ }
+
+ @action
+ onPointerDown = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ if (e.button === 2) {
+ this._isPointerDown = true;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ document.addEventListener("pointerup", this.onPointerUp);
+ }
+ }
+
+ @action
+ onPointerUp = (e: PointerEvent): void => {
+ e.stopPropagation();
+ if (e.button === 2) {
+ this._isPointerDown = false;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ }
+ }
+
+ @action
+ onPointerMove = (e: PointerEvent): void => {
+ e.preventDefault();
+ e.stopPropagation();
+ if (!this._isPointerDown) {
+ return;
+ }
+ const { doc } = this.props;
+ let x = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
+ let y = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
+ doc.SetFieldValue(KeyStore.PanX, x + e.movementX, NumberField);
+ doc.SetFieldValue(KeyStore.PanY, y + e.movementY, NumberField);
+ }
+
+ @action
+ onPointerWheel = (e: React.WheelEvent): void => {
+ e.stopPropagation();
+
+ let scaleAmount = 1 - (e.deltaY / 1000);
+ //this.props.store.Scale *= scaleAmount;
+ }
+
+ render() {
+ const { fieldKey, doc } = this.props;
+ const value: Document[] = doc.GetFieldValue(fieldKey, ListField, []);
+ const panx: number = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
+ const pany: number = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
+ return (
+
+ <div className="border" style={{
+ borderStyle: "solid",
+ borderWidth: "2px"
+ }}>
+ <div className="collectionfreeformview-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel} onContextMenu={(e) => e.preventDefault()} style={{
+ width: "100%",
+ height: "calc(100% - 4px)",
+ overflow: "hidden"
+ }}>
+ <div className="collectionfreeformview" style={{ transform: `translate(${panx}px, ${pany}px)`, transformOrigin: '50% 50%' }}>
+ <div className="node-container">
+ {value.map(doc => {
+ return (<DocumentView key={doc.Id} dvm={new DocumentViewModel(doc)} />);
+ })}
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+} \ No newline at end of file
diff --git a/src/views/freeformcanvas/FreeFormCanvas.scss b/src/views/freeformcanvas/FreeFormCanvas.scss
new file mode 100644
index 000000000..884ef90e6
--- /dev/null
+++ b/src/views/freeformcanvas/FreeFormCanvas.scss
@@ -0,0 +1,15 @@
+.freeformcanvas-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+
+ .freeformcanvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+ }
+}
+
diff --git a/src/views/freeformcanvas/FreeFormCanvas.tsx b/src/views/freeformcanvas/FreeFormCanvas.tsx
new file mode 100644
index 000000000..9ef5ab8f7
--- /dev/null
+++ b/src/views/freeformcanvas/FreeFormCanvas.tsx
@@ -0,0 +1,86 @@
+import { observer } from "mobx-react";
+import { Key } from "../../fields/Key";
+import { NodeCollectionStore } from "../../stores/NodeCollectionStore";
+import "./FreeFormCanvas.scss";
+import React = require("react");
+import { action } from "mobx";
+import { Document } from "../../fields/Document";
+import {DocumentViewModel} from "../../viewmodels/DocumentViewModel";
+import {DocumentView} from "../nodes/DocumentView";
+import {TextField} from "../../fields/TextField";
+import {ListField} from "../../fields/ListField";
+import {Field} from "../../fields/Field";
+
+interface IProps {
+ store: NodeCollectionStore;
+}
+
+@observer
+export class FreeFormCanvas extends React.Component<IProps> {
+
+ private _isPointerDown: boolean = false;
+
+ constructor(props:IProps) {
+ super(props);
+ }
+
+ @action
+ onPointerDown = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ if (e.button === 2) {
+ this._isPointerDown = true;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ document.addEventListener("pointerup", this.onPointerUp);
+ }
+ }
+
+ @action
+ onPointerUp = (e: PointerEvent): void => {
+ e.stopPropagation();
+ if (e.button === 2) {
+ this._isPointerDown = false;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ }
+
+ // let doc = this.props.store.Docs[0];
+ // let dataField = doc.GetFieldT(KeyStore.Data, TextField);
+ // let data = dataField ? dataField.Data : "";
+ // this.props.store.Docs[0].SetFieldValue(KeyStore.Data, data + " hello", TextField);
+ }
+
+ @action
+ onPointerMove = (e: PointerEvent): void => {
+ e.stopPropagation();
+ if (!this._isPointerDown) {
+ return;
+ }
+ this.props.store.X += e.movementX;
+ this.props.store.Y += e.movementY;
+ }
+
+ @action
+ onPointerWheel = (e: React.WheelEvent): void => {
+ e.stopPropagation();
+
+ let scaleAmount = 1 - (e.deltaY / 1000);
+ this.props.store.Scale *= scaleAmount;
+ }
+
+ render() {
+ let store = this.props.store;
+ return (
+ <div className="freeformcanvas-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel} onContextMenu={(e) => e.preventDefault()}>
+ <div className="freeformcanvas" style={{ transform: store.Transform, transformOrigin: '50% 50%' }}>
+ <div className="node-container">
+ {this.props.store.Docs.map(doc => {
+ return (<DocumentView key={doc.Id} dvm={new DocumentViewModel(doc)} />);
+ })}
+ </div>
+ </div>
+ </div>
+ );
+ }
+} \ No newline at end of file
diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx
new file mode 100644
index 000000000..f955a8c39
--- /dev/null
+++ b/src/views/nodes/DocumentView.tsx
@@ -0,0 +1,134 @@
+import { observer } from "mobx-react";
+import React = require("react");
+import { computed } from "mobx";
+import { KeyStore, Key } from "../../fields/Key";
+import { NumberField } from "../../fields/NumberField";
+import { TextField } from "../../fields/TextField";
+import { DocumentViewModel } from "../../viewmodels/DocumentViewModel";
+import { ListField } from "../../fields/ListField";
+import { FieldTextBox } from "../nodes/FieldTextBox"
+import { FreeFormCanvas } from "../freeformcanvas/FreeFormCanvas"
+import { CollectionFreeFormView } from "../freeformcanvas/CollectionFreeFormView"
+import "./NodeView.scss"
+const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
+
+interface IProps {
+ dvm: DocumentViewModel;
+}
+
+@observer
+export class DocumentView extends React.Component<IProps> {
+ @computed
+ get x(): number {
+ return this.props.dvm.Doc.GetFieldValue(KeyStore.X, NumberField, Number(0));
+ }
+
+ @computed
+ get y(): number {
+ return this.props.dvm.Doc.GetFieldValue(KeyStore.Y, NumberField, Number(0));
+ }
+
+ set x(x: number) {
+ this.props.dvm.Doc.SetFieldValue(KeyStore.X, x, NumberField)
+ }
+
+ set y(y: number) {
+ this.props.dvm.Doc.SetFieldValue(KeyStore.Y, y, NumberField)
+ }
+
+ @computed
+ get transform(): string {
+ return `translate(${this.x}px, ${this.y}px)`;
+ }
+
+ @computed
+ get width(): number {
+ return this.props.dvm.Doc.GetFieldValue(KeyStore.Width, NumberField, Number(0));
+ }
+
+ @computed
+ get height(): number {
+ return this.props.dvm.Doc.GetFieldValue(KeyStore.Height, NumberField, Number(0));
+ }
+
+ @computed
+ get layout(): string {
+ return this.props.dvm.Doc.GetFieldValue(KeyStore.Layout, TextField, String("<p>Error loading layout data</p>"));
+ }
+
+ @computed
+ get layoutKeys(): Key[] {
+ return this.props.dvm.Doc.GetFieldValue(KeyStore.LayoutKeys, ListField, new Array<Key>());
+ }
+
+ @computed
+ get layoutFields(): Key[] {
+ return this.props.dvm.Doc.GetFieldValue(KeyStore.LayoutFields, ListField, new Array<Key>());
+ }
+
+ private _isPointerDown = false;
+
+ onPointerDown = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ if (e.button === 2) {
+ 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();
+ if (e.button === 2) {
+ 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.x += e.movementX;
+ this.y += e.movementY;
+ }
+
+ render() {
+ let doc = this.props.dvm.Doc;
+ let bindings: any = {
+ doc: doc
+ };
+ for (const key of this.layoutKeys) {
+ bindings[key.Name + "Key"] = key;
+ }
+ for (const key of this.layoutFields) {
+ let field = doc.GetField(key);
+ if (field) {
+ bindings[key.Name] = field.GetValue();
+ }
+ }
+ return (
+ <div className="node" style={{
+ transform: this.transform,
+ width: this.width,
+ height: this.height
+ }} onPointerDown={this.onPointerDown} onContextMenu={
+ (e) => {
+ e.preventDefault()
+ }}>
+ <JsxParser
+ components={{ FieldTextBox, FreeFormCanvas, CollectionFreeFormView }}
+ bindings={bindings}
+ jsx={this.layout}
+ />
+ </div>
+ );
+ }
+
+} \ No newline at end of file
diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx
new file mode 100644
index 000000000..dbac3906a
--- /dev/null
+++ b/src/views/nodes/FieldTextBox.tsx
@@ -0,0 +1,117 @@
+import { Key, KeyStore } from "../../fields/Key";
+import { Document } from "../../fields/Document";
+import { observer } from "mobx-react";
+import { TextField } from "../../fields/TextField";
+import React = require("react")
+import { action, observable, reaction, IReactionDisposer } from "mobx";
+
+import {schema} from "prosemirror-schema-basic";
+import {EditorState, Transaction} from "prosemirror-state"
+import {EditorView} from "prosemirror-view"
+import {keymap} from "prosemirror-keymap"
+import {baseKeymap} from "prosemirror-commands"
+import {undo, redo, history} from "prosemirror-history"
+import { Opt } from "../../fields/Field";
+
+interface IProps {
+ fieldKey:Key;
+ doc:Document;
+}
+
+// FieldTextBox: Displays an editable plain text node that maps to a specified Key of a Document
+//
+// HTML Markup: <FieldTextBox Doc={Document's ID} FieldKey={Key's name + "Key"}
+//
+// In Code, the node's HTML is specified in the document's parameterized structure as:
+// document.SetField(KeyStore.Layout, "<FieldTextBox doc={doc} fieldKey={<KEYNAME>Key} />");
+// and the node's binding to the specified document KEYNAME as:
+// document.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.<KEYNAME>]));
+// The Jsx parser at run time will bind:
+// 'fieldKey' property to the Key stored in LayoutKeys
+// and 'doc' property to the document that is being rendered
+//
+// When rendered() by React, this extracts the TextController from the Document stored at the
+// specified Key and assigns it to an HTML input node. When changes are made tot his node,
+// this will edit the document and assign the new value to that field.
+//
+@observer
+export class FieldTextBox extends React.Component<IProps> {
+ private _ref: React.RefObject<HTMLDivElement>;
+ private _editorView: Opt<EditorView>;
+ private _reactionDisposer: Opt<IReactionDisposer>;
+
+ constructor(props:IProps) {
+ 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.SetFieldValue(fieldKey, JSON.stringify(state.toJSON()), TextField);
+ }
+ }
+
+ componentDidMount() {
+ let state:EditorState;
+ const {doc, fieldKey} = this.props;
+ const config = {
+ schema,
+ plugins: [
+ history(),
+ keymap({"Mod-z": undo, "Mod-y": redo}),
+ keymap(baseKeymap)
+ ]
+ };
+
+ let field = doc.GetFieldT(fieldKey, TextField);
+ if(field) {
+ 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
+ });
+ }
+
+ this._reactionDisposer = reaction(() => {
+ const field = this.props.doc.GetFieldT(this.props.fieldKey, TextField);
+ return field ? field.Data : undefined;
+ }, (field) => {
+ if(field && this._editorView) {
+ this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field)));
+ }
+ })
+ }
+
+ componentWillUnmount() {
+ if(this._editorView) {
+ this._editorView.destroy();
+ }
+ if(this._reactionDisposer) {
+ this._reactionDisposer();
+ }
+ }
+
+ shouldComponentUpdate() {
+ return false;
+ }
+
+ @action
+ onChange(e: React.ChangeEvent<HTMLInputElement>) {
+ const {fieldKey, doc} = this.props;
+ doc.SetFieldValue(fieldKey, e.target.value, TextField);
+ }
+
+ render() {
+ return (<div ref={this._ref} />)
+ }
+} \ No newline at end of file
diff --git a/src/views/nodes/NodeView.scss b/src/views/nodes/NodeView.scss
new file mode 100644
index 000000000..a68335f87
--- /dev/null
+++ b/src/views/nodes/NodeView.scss
@@ -0,0 +1,31 @@
+.node {
+ position: absolute;
+ background: #cdcdcd;
+
+ overflow: hidden;
+
+
+ &.minimized {
+ width: 30px;
+ height: 30px;
+ }
+
+ .top {
+ background: #232323;
+ height: 20px;
+ cursor: pointer;
+ }
+
+ .content {
+ padding: 20px 20px;
+ height: auto;
+ box-sizing: border-box;
+
+ }
+
+ .scroll-box {
+ overflow-y: scroll;
+ height: calc(100% - 20px);
+ }
+}
+
diff --git a/src/views/nodes/RichTextView.tsx b/src/views/nodes/RichTextView.tsx
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/views/nodes/RichTextView.tsx
diff --git a/src/views/nodes/TextNodeView.tsx b/src/views/nodes/TextNodeView.tsx
new file mode 100644
index 000000000..4831e658c
--- /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