aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx33
-rw-r--r--src/client/views/nodes/DocumentView.tsx255
-rw-r--r--src/client/views/nodes/FieldView.tsx9
-rw-r--r--src/client/views/nodes/FormattedTextBox.scss6
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx6
-rw-r--r--src/client/views/nodes/ImageBox.scss3
-rw-r--r--src/client/views/nodes/ImageBox.tsx8
-rw-r--r--src/client/views/nodes/WebView.tsx22
8 files changed, 179 insertions, 163 deletions
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 57527076b..17123bf52 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,16 +1,11 @@
-import { action, computed } from "mobx";
+import { computed, trace } from "mobx";
import { observer } from "mobx-react";
-import { Key, KeyStore } from "../../../fields/Key";
+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 { Transform } from "../../util/Transform";
@observer
@@ -29,7 +24,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
@computed
get transform(): string {
- return `scale(${this.props.Scaling}, ${this.props.Scaling}) translate(${this.props.Document.GetNumber(KeyStore.X, 0)}px, ${this.props.Document.GetNumber(KeyStore.Y, 0)}px)`;
+ return `scale(${this.props.ContentScaling()}, ${this.props.ContentScaling()}) translate(${this.props.Document.GetNumber(KeyStore.X, 0)}px, ${this.props.Document.GetNumber(KeyStore.Y, 0)}px)`;
}
@computed
@@ -74,13 +69,24 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
this.props.Document.SetData(KeyStore.ZIndex, h, NumberField)
}
+ contentScaling = () => {
+ return this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
+ }
getTransform = (): Transform => {
- return this.props.ScreenToLocalTransform().translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0));
+ return this.props.ScreenToLocalTransform().
+ translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / this.contentScaling());
+ }
+
+ @computed
+ get docView() {
+ return <DocumentView {...this.props}
+ ContentScaling={this.contentScaling}
+ ScreenToLocalTransform={this.getTransform}
+ />
}
render() {
- var parentScaling = this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
return (
<div ref={this._mainCont} style={{
transformOrigin: "left top",
@@ -91,8 +97,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
zIndex: this.zIndex,
backgroundColor: "transparent"
}} >
-
- <DocumentView {...this.props} Scaling={this.width / this.nativeWidth} ScreenToLocalTransform={this.getTransform} />
+ {this.docView}
</div>
);
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8e2f1afe7..d8e2f3401 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -2,36 +2,80 @@ import { action, computed, runInAction } from "mobx";
import { observer } from "mobx-react";
import { observable } from "mobx";
import { Document } from "../../../fields/Document";
-import { Opt, FieldWaiting } from "../../../fields/Field";
-import { Key, KeyStore } from "../../../fields/Key";
+import { Field, FieldWaiting, Opt } from "../../../fields/Field";
+import { Key } from "../../../fields/Key";
+import { KeyStore } from "../../../fields/KeyStore";
import { ListField } from "../../../fields/ListField";
-import { Utils } from "../../../Utils";
+import { DragManager } from "../../util/DragManager";
+import { SelectionManager } from "../../util/SelectionManager";
+import { Transform } from "../../util/Transform";
import { CollectionDockingView } from "../collections/CollectionDockingView";
import { CollectionFreeFormView } from "../collections/CollectionFreeFormView";
import { CollectionSchemaView } from "../collections/CollectionSchemaView";
-import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "../collections/CollectionViewBase";
+import { CollectionView, CollectionViewType } from "../collections/CollectionView";
+import { WebView } from "./WebView";
+import { ContextMenu } from "../ContextMenu";
import { FormattedTextBox } from "../nodes/FormattedTextBox";
import { ImageBox } from "../nodes/ImageBox";
import "./DocumentView.scss";
import React = require("react");
-import { Transform } from "../../util/Transform";
import { DocumentManager } from "../DocumentManager";
-import { SelectionManager } from "../../util/SelectionManager";
-import { DragManager } from "../../util/DragManager";
-import { ContextMenu } from "../ContextMenu";
import { TextField } from "../../../fields/TextField";
const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
export interface DocumentViewProps {
- DocumentView: Opt<DocumentView> // needed only to set ContainingDocumentView on CollectionViewProps when invoked from JsxParser -- is there a better way?
- ContainingCollectionView: Opt<CollectionViewBase>;
+ ContainingCollectionView: Opt<CollectionView>;
Document: Document;
AddDocument?: (doc: Document) => void;
RemoveDocument?: (doc: Document) => boolean;
ScreenToLocalTransform: () => Transform;
isTopMost: boolean;
- Scaling: number;
+ //tfs: This shouldn't be necessary I don't think
+ ContentScaling: () => number;
+ PanelWidth: () => number;
+ PanelHeight: () => number;
+}
+export interface JsxArgs extends DocumentViewProps {
+ Keys: { [name: string]: Key }
+ Fields: { [name: string]: Field }
+}
+
+/*
+This function is pretty much a hack that lets us fill out the fields in JsxArgs with something that
+jsx-to-string can recover the jsx from
+Example usage of this function:
+ public static LayoutString() {
+ let args = FakeJsxArgs(["Data"]);
+ return jsxToString(
+ <CollectionFreeFormView
+ doc={args.Document}
+ fieldKey={args.Keys.Data}
+ DocumentViewForField={args.DocumentView} />,
+ { useFunctionCode: true, functionNameOnly: true }
+ )
+ }
+*/
+export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
+ let Keys: { [name: string]: any } = {}
+ let Fields: { [name: string]: any } = {}
+ for (const key of keys) {
+ let fn = () => { }
+ Object.defineProperty(fn, "name", { value: key + "Key" })
+ Keys[key] = fn;
+ }
+ for (const field of fields) {
+ let fn = () => { }
+ Object.defineProperty(fn, "name", { value: field })
+ Fields[field] = fn;
+ }
+ let args: JsxArgs = {
+ Document: function Document() { },
+ DocumentView: function DocumentView() { },
+ Keys,
+ Fields
+ } as any;
+ return args;
}
@observer
@@ -48,78 +92,40 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
private _mainCont = React.createRef<HTMLDivElement>();
- get MainContent() {
- return this._mainCont;
- }
- get screenRect(): ClientRect | DOMRect {
- if (this._mainCont.current) {
- return this._mainCont.current.getBoundingClientRect();
- }
- return new DOMRect();
- }
- @computed
- get layout(): string {
- return this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>");
- }
-
- @computed
- get backgroundLayout(): string | undefined {
- let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField);
- if (field && field !== "<Waiting>") {
- return field.Data;
- }
- }
-
- @computed
- get layoutKeys(): Key[] {
- return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array<Key>());
- }
-
- @computed
- get layoutFields(): Key[] {
- return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array<Key>());
- }
-
- @computed
- get active(): boolean {
- return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined ||
- this.props.ContainingCollectionView.active;
- }
-
+ private _documentBindings: any = null;
private _contextMenuCanOpen = false;
private _downX: number = 0;
private _downY: number = 0;
+
+ @computed get active(): boolean { return SelectionManager.IsSelected(this) || !this.props.ContainingCollectionView || this.props.ContainingCollectionView.active(); }
+ @computed get topMost(): boolean { return !this.props.ContainingCollectionView || this.props.ContainingCollectionView.collectionViewType == CollectionViewType.Docking; }
+ @computed get layout(): string { return this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>"); }
+ @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array<Key>()); }
+ @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array<Key>()); }
+
+ screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect();
+
onPointerDown = (e: React.PointerEvent): void => {
this._downX = e.clientX;
this._downY = e.clientY;
- var me = this;
if (e.shiftKey && e.buttons === 1) {
- CollectionDockingView.StartOtherDrag(this._mainCont.current!, this.props.Document);
- e.stopPropagation();
- return;
- }
- this._contextMenuCanOpen = e.button == 2;
- if (this.active && !e.isDefaultPrevented()) {
+ CollectionDockingView.Instance.StartOtherDrag(this._mainCont.current!, this.props.Document);
e.stopPropagation();
- if (e.buttons === 2) {
- e.preventDefault();
+ } else {
+ this._contextMenuCanOpen = true;
+ if (this.active && !e.isDefaultPrevented()) {
+ e.stopPropagation();
+ if (e.buttons === 2) {
+ e.preventDefault();
+ }
+ document.removeEventListener("pointermove", this.onPointerMove)
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp)
+ document.addEventListener("pointerup", this.onPointerUp);
}
- document.removeEventListener("pointermove", this.onPointerMove)
- document.addEventListener("pointermove", this.onPointerMove);
- document.removeEventListener("pointerup", this.onPointerUp)
- document.addEventListener("pointerup", this.onPointerUp);
}
}
- @action
- dragComplete = (e: DragManager.DragCompleteEvent) => {
- }
-
- @computed
- get topMost(): boolean {
- return this.props.ContainingCollectionView == undefined || this.props.ContainingCollectionView instanceof CollectionDockingView;
- }
-
onPointerMove = (e: PointerEvent): void => {
if (e.cancelBubble) {
this._contextMenuCanOpen = false;
@@ -136,7 +142,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
dragData["yOffset"] = e.y - top;
DragManager.StartDrag(this._mainCont.current, dragData, {
handlers: {
- dragComplete: this.dragComplete,
+ dragComplete: action((e: DragManager.DragCompleteEvent) => { }),
},
hideSource: true
})
@@ -155,25 +161,19 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
}
- openRight = (e: React.MouseEvent): void => {
- CollectionDockingView.AddRightSplit(this.props.Document);
- }
-
deleteClicked = (e: React.MouseEvent): void => {
if (this.props.RemoveDocument) {
this.props.RemoveDocument(this.props.Document);
}
}
- @action
fullScreenClicked = (e: React.MouseEvent): void => {
- CollectionDockingView.OpenFullScreen(this.props.Document);
+ CollectionDockingView.Instance.OpenFullScreen(this.props.Document);
ContextMenu.Instance.clearItems();
ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked });
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
}
- @action
closeFullScreenClicked = (e: React.MouseEvent): void => {
- CollectionDockingView.CloseFullScreen();
+ CollectionDockingView.Instance.CloseFullScreen();
ContextMenu.Instance.clearItems();
ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
@@ -188,12 +188,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
@action
onContextMenu = (e: React.MouseEvent): void => {
- if (!SelectionManager.IsSelected(this)) {
- return;
- }
e.preventDefault()
-
- if (!this._contextMenuCanOpen) {
+ e.stopPropagation();
+ if (!SelectionManager.IsSelected(this) || !this._contextMenuCanOpen) {
return;
}
@@ -203,34 +200,33 @@ export class DocumentView extends React.Component<DocumentViewProps> {
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
}
else {
- // DocumentViews should stop propogation of this event
+ // DocumentViews should stop propagation of this event
e.stopPropagation();
ContextMenu.Instance.clearItems();
ContextMenu.Instance.addItem({ description: "Center", event: this.Center })
ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
- ContextMenu.Instance.addItem({ description: "Open Right", event: this.openRight })
+ ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) })
ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked })
+ ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) })
+ ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) })
+ ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) })
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
SelectionManager.SelectDoc(this, e.ctrlKey);
}
}
- //
- // returns the cumulative scaling between the document and the screen
- //
- @computed
- public get ScalingToScreenSpace(): number {
- if (this.props.ContainingCollectionView != undefined &&
- this.props.ContainingCollectionView.props.ContainingDocumentView != undefined) {
- let ss = this.props.ContainingCollectionView.props.DocumentForCollection.GetNumber(KeyStore.Scale, 1);
- return this.props.ContainingCollectionView.props.ContainingDocumentView.ScalingToScreenSpace * ss;
- }
- return 1;
+ @computed get mainContent() {
+ return <JsxParser
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebView }}
+ bindings={this._documentBindings}
+ jsx={this.layout}
+ showWarnings={true}
+ onError={(test: any) => { console.log(test) }}
+ />
}
//adds doc to global list
- @action
componentDidMount: () => void = () => {
runInAction(() => {
DocumentManager.Instance.DocumentViews.push(this);
@@ -238,7 +234,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
//removes doc from global list
- @action
componentWillUnmount: () => void = () => {
runInAction(() => {
for (let node of DocumentManager.Instance.DocumentViews) {
@@ -257,50 +252,40 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
render() {
- let bindings = { ...this.props } as any;
- bindings.isSelected = this.isSelected;
- bindings.select = this.select;
+ if (!this.props.Document)
+ return <div></div>
+ let lkeys = this.props.Document.GetT(KeyStore.LayoutKeys, ListField);
+ if (!lkeys || lkeys === "<Waiting>") {
+ return <p>Error loading layout keys</p>;
+ }
+ this._documentBindings = {
+ ...this.props,
+ isSelected: this.isSelected,
+ select: this.select
+ };
for (const key of this.layoutKeys) {
- bindings[key.Name + "Key"] = key; // this maps string values of the form <keyname>Key to an actual key Kestore.keyname e.g, "DataKey" => KeyStore.Data
+ this._documentBindings[key.Name + "Key"] = key; // this maps string values of the form <keyname>Key to an actual key Kestore.keyname e.g, "DataKey" => KeyStore.Data
}
for (const key of this.layoutFields) {
let field = this.props.Document.Get(key);
- bindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field;
- }
- /*
- Should this be moved to CollectionFreeformView or another component that renders
- Document backgrounds (or contents based on a layout key, which could be used here as well)
- that CollectionFreeformView uses? It seems like a lot for it to be here considering only one view currently uses it...
- */
- let backgroundLayout = this.backgroundLayout;
- if (backgroundLayout) {
- let backgroundView = () => (<JsxParser
- components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
- bindings={bindings}
- jsx={this.backgroundLayout}
- showWarnings={true}
- onError={(test: any) => { console.log(test) }}
- />);
- bindings.BackgroundView = backgroundView;
+ this._documentBindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field;
}
+ this._documentBindings.bindings = this._documentBindings;
- bindings.DocumentView = this;
-
- var width = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
- var strwidth = width > 0 ? width.toString() + "px" : "100%";
- var height = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
- var strheight = height > 0 ? height.toString() + "px" : "100%";
+ var scaling = this.props.ContentScaling();
+ var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
+ var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
return (
- <div className="documentView-node" ref={this._mainCont} style={{ borderColor: this.Border, width: strwidth, height: strheight, transformOrigin: "left top", transform: `scale(${this.props.Scaling},${this.props.Scaling})` }}
+ <div className="documentView-node" ref={this._mainCont}
+ style={{
+ width: nativeWidth > 0 ? nativeWidth.toString() + "px" : "100%",
+ height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%",
+ transformOrigin: "left top",
+ transform: `scale(${scaling},${scaling})`
+ }}
onContextMenu={this.onContextMenu}
onPointerDown={this.onPointerDown} >
- <JsxParser
- components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }}
- bindings={bindings}
- jsx={this.layout}
- showWarnings={true}
- onError={(test: any) => { console.log(test) }}
- />
+ {this.mainContent}
</div>
)
}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 08de53e1c..1a9d325db 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -10,6 +10,8 @@ import { ImageField } from "../../../fields/ImageField";
import { Key } from "../../../fields/Key";
import { FormattedTextBox } from "./FormattedTextBox";
import { ImageBox } from "./ImageBox";
+import { HtmlField } from "../../../fields/HtmlField";
+import { WebView } from "./WebView";
//
// these properties get assigned through the render() method of the DocumentView when it creates this node.
@@ -20,12 +22,15 @@ export interface FieldViewProps {
fieldKey: Key;
doc: Document;
isSelected: () => boolean;
+ select: () => void;
isTopMost: boolean;
+ bindings: any;
}
@observer
export class FieldView extends React.Component<FieldViewProps> {
- public static LayoutString(fieldType: string) { return `<${fieldType} doc={Document} DocumentViewForField={DocumentView} fieldKey={DataKey} isSelected={isSelected} isTopMost={isTopMost} />`; }
+ public static LayoutString(fieldType: { name: string }, fieldStr: string = "DataKey") { return `<${fieldType.name} doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={${fieldStr}} isSelected={isSelected} select={select} isTopMost={isTopMost} />`; }
+
@computed
get field(): FieldValue<Field> {
const { doc, fieldKey } = this.props;
@@ -47,6 +52,8 @@ export class FieldView extends React.Component<FieldViewProps> {
}
else if (field instanceof NumberField) {
return <p>{field.Data}</p>
+ } else if (field instanceof HtmlField) {
+ return <WebView {...this.props} />
} else if (field != FieldWaiting) {
return <p>{field.GetValue}</p>
} else
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 5139d5d6b..226456fab 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -1,7 +1,7 @@
.ProseMirror {
- margin-top: -1em;
width: 100%;
- height: 100%;
+ height: auto;
+ min-height: 100%
}
.ProseMirror:focus {
@@ -10,5 +10,5 @@
.formattedTextBox-cont {
background: beige;
- padding: 1vw;
+ padding: 0;
} \ No newline at end of file
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 2e3d396c1..c0969a8c3 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -6,13 +6,10 @@ import { schema } from "prosemirror-schema-basic";
import { EditorState, Transaction } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { Opt, FieldWaiting, FieldValue } from "../../../fields/Field";
-import { SelectionManager } from "../../util/SelectionManager";
import "./FormattedTextBox.scss";
import React = require("react")
import { RichTextField } from "../../../fields/RichTextField";
import { FieldViewProps, FieldView } from "./FieldView";
-import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
-import { observer } from "mobx-react";
// FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
@@ -33,7 +30,7 @@ import { observer } from "mobx-react";
//]
export class FormattedTextBox extends React.Component<FieldViewProps> {
- public static LayoutString() { return FieldView.LayoutString("FormattedTextBox"); }
+ public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(FormattedTextBox, fieldStr) }
private _ref: React.RefObject<HTMLDivElement>;
private _editorView: Opt<EditorView>;
private _reactionDisposer: Opt<IReactionDisposer>;
@@ -119,6 +116,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
style={{
color: "initial",
whiteSpace: "initial",
+ height: "auto"
}}
onPointerDown={this.onPointerDown}
ref={this._ref} />)
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index 36f5e0fe0..5b15b3329 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -1,7 +1,8 @@
.imageBox-cont {
padding: 0vw;
- position: absolute;
+ position: relative;
+ text-align: center;
width: 100%;
max-width: 100%;
max-height: 100%
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index e1fa26e2f..b5ce8b28c 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,21 +1,19 @@
import Lightbox from 'react-image-lightbox';
import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
-import { SelectionManager } from "../../util/SelectionManager";
import "./ImageBox.scss";
import React = require("react")
import { ImageField } from '../../../fields/ImageField';
import { FieldViewProps, FieldView } from './FieldView';
-import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView';
import { FieldWaiting } from '../../../fields/Field';
import { observer } from "mobx-react"
-import { observable, action, spy } from 'mobx';
-import { KeyStore } from '../../../fields/Key';
+import { observable, action } from 'mobx';
+import { KeyStore } from '../../../fields/KeyStore';
@observer
export class ImageBox extends React.Component<FieldViewProps> {
- public static LayoutString() { return FieldView.LayoutString("ImageBox"); }
+ public static LayoutString() { return FieldView.LayoutString(ImageBox) }
private _ref: React.RefObject<HTMLDivElement>;
private _downX: number = 0;
private _downY: number = 0;
diff --git a/src/client/views/nodes/WebView.tsx b/src/client/views/nodes/WebView.tsx
new file mode 100644
index 000000000..717aa8bf5
--- /dev/null
+++ b/src/client/views/nodes/WebView.tsx
@@ -0,0 +1,22 @@
+import { FieldViewProps, FieldView } from "./FieldView";
+import { computed } from "mobx";
+import { observer } from "mobx-react";
+import { KeyStore } from "../../../fields/KeyStore";
+import React = require('react')
+import { TextField } from "../../../fields/TextField";
+import { HtmlField } from "../../../fields/HtmlField";
+import { RichTextField } from "../../../fields/RichTextField";
+
+@observer
+export class WebView extends React.Component<FieldViewProps> {
+ public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(WebView, fieldStr) }
+
+ @computed
+ get html(): string {
+ return this.props.doc.GetData(KeyStore.Data, HtmlField, "" as string);
+ }
+
+ render() {
+ return <span dangerouslySetInnerHTML={{ __html: this.html }}></span>
+ }
+} \ No newline at end of file