aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/ContextMenu.tsx14
-rw-r--r--src/client/views/ContextMenuItem.tsx4
-rw-r--r--src/client/views/DocumentDecorations.tsx154
-rw-r--r--src/client/views/EditableView.tsx14
-rw-r--r--src/client/views/InkingCanvas.scss3
-rw-r--r--src/client/views/InkingCanvas.tsx43
-rw-r--r--src/client/views/InkingControl.tsx19
-rw-r--r--src/client/views/InkingStroke.tsx6
-rw-r--r--src/client/views/Main.scss23
-rw-r--r--src/client/views/Main.tsx150
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx187
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx74
-rw-r--r--src/client/views/collections/CollectionPDFView.tsx52
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx117
-rw-r--r--src/client/views/collections/CollectionSubView.tsx (renamed from src/client/views/collections/CollectionViewBase.tsx)132
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx39
-rw-r--r--src/client/views/collections/CollectionVideoView.tsx56
-rw-r--r--src/client/views/collections/CollectionView.tsx185
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx109
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx23
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss8
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx184
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx29
-rw-r--r--src/client/views/collections/collectionFreeForm/PreviewCursor.tsx7
-rw-r--r--src/client/views/nodes/Annotation.tsx128
-rw-r--r--src/client/views/nodes/AudioBox.tsx14
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx22
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx47
-rw-r--r--src/client/views/nodes/DocumentView.tsx153
-rw-r--r--src/client/views/nodes/FieldView.tsx82
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx359
-rw-r--r--src/client/views/nodes/ImageBox.tsx20
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx33
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx37
-rw-r--r--src/client/views/nodes/LinkBox.tsx17
-rw-r--r--src/client/views/nodes/LinkEditor.tsx6
-rw-r--r--src/client/views/nodes/LinkMenu.tsx12
-rw-r--r--src/client/views/nodes/PDFBox.tsx122
-rw-r--r--src/client/views/nodes/Sticky.tsx6
-rw-r--r--src/client/views/nodes/VideoBox.tsx28
-rw-r--r--src/client/views/nodes/WebBox.tsx12
42 files changed, 1459 insertions, 1273 deletions
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index cfa8ea7b7..615a928ad 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -2,11 +2,11 @@ import React = require("react");
import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem";
import { observable, action } from "mobx";
import { observer } from "mobx-react";
-import "./ContextMenu.scss"
+import "./ContextMenu.scss";
@observer
export class ContextMenu extends React.Component {
- static Instance: ContextMenu
+ static Instance: ContextMenu;
@observable private _items: Array<ContextMenuProps> = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault() }];
@observable private _pageX: number = 0;
@@ -22,15 +22,15 @@ export class ContextMenu extends React.Component {
constructor(props: Readonly<{}>) {
super(props);
- this.ref = React.createRef()
+ this.ref = React.createRef();
ContextMenu.Instance = this;
}
@action
clearItems() {
- this._items = []
- this._display = "none"
+ this._items = [];
+ this._display = "none";
}
@action
@@ -56,7 +56,7 @@ export class ContextMenu extends React.Component {
this._searchString = "";
- this._display = "flex"
+ this._display = "flex";
}
intersects = (x: number, y: number): boolean => {
@@ -86,7 +86,7 @@ export class ContextMenu extends React.Component {
{this._items.filter(prop => prop.description.toLowerCase().indexOf(this._searchString.toLowerCase()) !== -1).
map(prop => <ContextMenuItem {...prop} key={prop.description} />)}
</div>
- )
+ );
}
@action
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 4801c1555..70813f0dd 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -11,7 +11,7 @@ export interface SubmenuProps {
}
export interface ContextMenuItemProps {
- type: ContextMenuProps | SubmenuProps
+ type: ContextMenuProps | SubmenuProps;
}
export class ContextMenuItem extends React.Component<ContextMenuProps> {
@@ -20,6 +20,6 @@ export class ContextMenuItem extends React.Component<ContextMenuProps> {
<div className="contextMenu-item" onClick={this.props.event}>
<div className="contextMenu-description">{this.props.description}</div>
</div>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c7e4a269a..28af46358 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -21,8 +21,8 @@ export const Flyout = higflyout.default;
@observer
export class DocumentDecorations extends React.Component<{}, { value: string }> {
- static Instance: DocumentDecorations
- private _resizer = ""
+ static Instance: DocumentDecorations;
+ private _resizer = "";
private _isPointerDown = false;
private keyinput: React.RefObject<HTMLInputElement>;
private _documents: DocumentView[] = SelectionManager.SelectedDocuments();
@@ -40,8 +40,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
constructor(props: Readonly<{}>) {
- super(props)
- DocumentDecorations.Instance = this
+ super(props);
+ DocumentDecorations.Instance = this;
this.handleChange = this.handleChange.bind(this);
this.keyinput = React.createRef();
}
@@ -49,24 +49,24 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
@action
handleChange = (event: any) => {
this._title = event.target.value;
- };
+ }
@action
enterPressed = (e: any) => {
var key = e.keyCode || e.which;
// enter pressed
- if (key == 13) {
+ if (key === 13) {
var text = e.target.value;
- if (text[0] == '#') {
+ if (text[0] === '#') {
let command = text.slice(1, text.length);
- this._fieldKey = new Key(command)
- // if (command == "Title" || command == "title") {
+ this._fieldKey = new Key(command);
+ // if (command === "Title" || command === "title") {
// this._fieldKey = KeyStore.Title;
// }
- // else if (command == "Width" || command == "width") {
+ // else if (command === "Width" || command === "width") {
// this._fieldKey = KeyStore.Width;
// }
- this._title = "changed"
+ this._title = "changed";
// TODO: Change field with switch statement
}
else {
@@ -89,7 +89,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
return {
x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
- }
+ };
}, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE });
}
@@ -104,7 +104,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
document.addEventListener("pointermove", this.onBackgroundMove);
document.removeEventListener("pointerup", this.onBackgroundUp);
document.addEventListener("pointerup", this.onBackgroundUp);
- this._lastDrag = [e.clientX, e.clientY]
+ this._lastDrag = [e.clientX, e.clientY];
e.stopPropagation();
e.preventDefault();
}
@@ -117,23 +117,17 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
dragData.aliasOnDrop = false;
dragData.xOffset = e.x - left;
dragData.yOffset = e.y - top;
- dragData.removeDocument = (dropCollectionView: CollectionView) =>
- dragData.draggedDocuments.map(d => {
- if (dragDocView.props.RemoveDocument && dragDocView.props.ContainingCollectionView !== dropCollectionView) {
- dragDocView.props.RemoveDocument(d);
- }
- });
+ let move = SelectionManager.SelectedDocuments()[0].props.moveDocument;
+ dragData.moveDocument = move;
this._dragging = true;
document.removeEventListener("pointermove", this.onBackgroundMove);
document.removeEventListener("pointerup", this.onBackgroundUp);
- DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont!.current!), dragData,
- e.x, e.y,
- {
- handlers: {
- dragComplete: action(() => this._dragging = false),
- },
- hideSource: true
- })
+ DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => docView.ContentRef.current!), dragData, e.x, e.y, {
+ handlers: {
+ dragComplete: action(() => this._dragging = false),
+ },
+ hideSource: true
+ });
e.stopPropagation();
}
@@ -162,7 +156,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
onCloseUp = (e: PointerEvent): void => {
e.stopPropagation();
if (e.button === 0) {
- SelectionManager.SelectedDocuments().map(dv => dv.props.RemoveDocument && dv.props.RemoveDocument(dv.props.Document));
+ SelectionManager.SelectedDocuments().map(dv => dv.props.removeDocument && dv.props.removeDocument(dv.props.Document));
SelectionManager.DeselectAll();
document.removeEventListener("pointermove", this.onCloseMove);
document.removeEventListener("pointerup", this.onCloseUp);
@@ -205,74 +199,73 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
onLinkerButtonDown = (e: React.PointerEvent): void => {
e.stopPropagation();
- document.removeEventListener("pointermove", this.onLinkerButtonMoved)
+ document.removeEventListener("pointermove", this.onLinkerButtonMoved);
document.addEventListener("pointermove", this.onLinkerButtonMoved);
- document.removeEventListener("pointerup", this.onLinkerButtonUp)
+ document.removeEventListener("pointerup", this.onLinkerButtonUp);
document.addEventListener("pointerup", this.onLinkerButtonUp);
}
onLinkerButtonUp = (e: PointerEvent): void => {
- document.removeEventListener("pointermove", this.onLinkerButtonMoved)
- document.removeEventListener("pointerup", this.onLinkerButtonUp)
+ document.removeEventListener("pointermove", this.onLinkerButtonMoved);
+ document.removeEventListener("pointerup", this.onLinkerButtonUp);
e.stopPropagation();
}
onLinkerButtonMoved = (e: PointerEvent): void => {
- if (this._linkerButton.current != null) {
- document.removeEventListener("pointermove", this.onLinkerButtonMoved)
- document.removeEventListener("pointerup", this.onLinkerButtonUp)
+ if (this._linkerButton.current !== null) {
+ document.removeEventListener("pointermove", this.onLinkerButtonMoved);
+ document.removeEventListener("pointerup", this.onLinkerButtonUp);
let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, {
handlers: {
dragComplete: action(() => { }),
},
hideSource: false
- })
+ });
}
e.stopPropagation();
}
onLinkButtonDown = (e: React.PointerEvent): void => {
e.stopPropagation();
- document.removeEventListener("pointermove", this.onLinkButtonMoved)
+ document.removeEventListener("pointermove", this.onLinkButtonMoved);
document.addEventListener("pointermove", this.onLinkButtonMoved);
- document.removeEventListener("pointerup", this.onLinkButtonUp)
+ document.removeEventListener("pointerup", this.onLinkButtonUp);
document.addEventListener("pointerup", this.onLinkButtonUp);
}
onLinkButtonUp = (e: PointerEvent): void => {
- document.removeEventListener("pointermove", this.onLinkButtonMoved)
- document.removeEventListener("pointerup", this.onLinkButtonUp)
+ document.removeEventListener("pointermove", this.onLinkButtonMoved);
+ document.removeEventListener("pointerup", this.onLinkButtonUp);
e.stopPropagation();
}
onLinkButtonMoved = async (e: PointerEvent) => {
- if (this._linkButton.current != null) {
- document.removeEventListener("pointermove", this.onLinkButtonMoved)
+ if (this._linkButton.current !== null) {
+ document.removeEventListener("pointermove", this.onLinkButtonMoved);
document.removeEventListener("pointerup", this.onLinkButtonUp);
let sourceDoc = SelectionManager.SelectedDocuments()[0].props.Document;
- let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
- let draggedDocs = (srcTarg && srcTarg != FieldWaiting) ?
+ let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
+ let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
(linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
- let draggedFromDocs = (srcTarg && srcTarg != FieldWaiting) ?
+ let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
(linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
draggedDocs.push(...draggedFromDocs);
if (draggedDocs.length) {
let moddrag = [] as Document[];
- for (let i = 0; i < draggedDocs.length; i++) {
- let doc = await draggedDocs[i].GetTAsync(KeyStore.AnnotationOn, Document);
- if (doc)
- moddrag.push(doc);
+ for (const draggedDoc of draggedDocs) {
+ let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
+ if (doc) moddrag.push(doc);
}
- let dragData = new DragManager.DocumentDragData(moddrag);
+ let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
DragManager.StartDocumentDrag([this._linkButton.current], dragData, e.x, e.y, {
handlers: {
dragComplete: action(() => { }),
},
hideSource: false
- })
+ });
}
}
e.stopPropagation();
@@ -292,38 +285,38 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
case "":
break;
case "documentDecorations-topLeftResizer":
- dX = -1
- dY = -1
- dW = -(e.movementX)
- dH = -(e.movementY)
+ dX = -1;
+ dY = -1;
+ dW = -(e.movementX);
+ dH = -(e.movementY);
break;
case "documentDecorations-topRightResizer":
- dW = e.movementX
- dY = -1
- dH = -(e.movementY)
+ dW = e.movementX;
+ dY = -1;
+ dH = -(e.movementY);
break;
case "documentDecorations-topResizer":
- dY = -1
- dH = -(e.movementY)
+ dY = -1;
+ dH = -(e.movementY);
break;
case "documentDecorations-bottomLeftResizer":
- dX = -1
- dW = -(e.movementX)
- dH = e.movementY
+ dX = -1;
+ dW = -(e.movementX);
+ dH = e.movementY;
break;
case "documentDecorations-bottomRightResizer":
- dW = e.movementX
- dH = e.movementY
+ dW = e.movementX;
+ dH = e.movementY;
break;
case "documentDecorations-bottomResizer":
- dH = e.movementY
+ dH = e.movementY;
break;
case "documentDecorations-leftResizer":
- dX = -1
- dW = -(e.movementX)
+ dX = -1;
+ dW = -(e.movementX);
break;
case "documentDecorations-rightResizer":
- dW = e.movementX
+ dW = e.movementX;
break;
}
@@ -345,14 +338,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
var nativeWidth = doc.GetNumber(KeyStore.NativeWidth, 0);
var nativeHeight = doc.GetNumber(KeyStore.NativeHeight, 0);
if (nativeWidth > 0 && nativeHeight > 0) {
- if (Math.abs(dW) > Math.abs(dH))
+ if (Math.abs(dW) > Math.abs(dH)) {
actualdH = nativeHeight / nativeWidth * actualdW;
+ }
else actualdW = nativeWidth / nativeHeight * actualdH;
}
doc.SetNumber(KeyStore.Width, actualdW);
doc.SetNumber(KeyStore.Height, actualdH);
}
- })
+ });
}
onPointerUp = (e: PointerEvent): void => {
@@ -369,10 +363,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
if (this._title === "changed" && this._documents.length > 0) {
let field = this._documents[0].props.Document.Get(this._fieldKey);
if (field instanceof TextField) {
- return (field as TextField).GetValue();
+ return (field).GetValue();
}
else if (field instanceof NumberField) {
- return (field as NumberField).GetValue().toString();
+ return (field).GetValue().toString();
}
}
return this._title;
@@ -386,13 +380,16 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
// }
render() {
var bounds = this.Bounds;
+ if (bounds.x === Number.MAX_VALUE) {
+ return (null);
+ }
// console.log(this._documents.length)
// let test = this._documents[0].props.Document.Title;
if (this.Hidden) {
return (null);
}
if (isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
- console.log("DocumentDecorations: Bounds Error")
+ console.log("DocumentDecorations: Bounds Error");
return (null);
}
@@ -404,9 +401,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
let linkCount = linkToSize + linkFromSize;
linkButton = (<Flyout
anchorPoint={anchorPoints.RIGHT_TOP}
- content={
- <LinkMenu docView={selFirst} changeFlyout={this.changeFlyoutContent} />
- }>
+ content={<LinkMenu docView={selFirst}
+ changeFlyout={this.changeFlyoutContent} />}>
<div className={"linkButton-" + (selFirst.props.Document.GetData(KeyStore.LinkedToDocs, ListField, []).length ? "nonempty" : "empty")} onPointerDown={this.onLinkButtonDown} >{linkCount}</div>
</Flyout>);
}
@@ -418,7 +414,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
top: bounds.y - this._resizeBorderWidth / 2,
pointerEvents: this._dragging ? "none" : "all",
zIndex: SelectionManager.SelectedDocuments().length > 1 ? 1000 : 0,
- }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation() }} >
+ }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); }} >
</div>
<div id="documentDecorations-container" style={{
width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
@@ -444,6 +440,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
<div className="linkButton-linker" ref={this._linkerButton} onPointerDown={this.onLinkerButtonDown}>∞</div>
</div >
</div>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 29bf6add7..2f17c6c51 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -1,7 +1,7 @@
-import React = require('react')
+import React = require('react');
import { observer } from 'mobx-react';
import { observable, action, trace } from 'mobx';
-import "./EditableView.scss"
+import "./EditableView.scss";
export interface EditableProps {
/**
@@ -22,7 +22,7 @@ export interface EditableProps {
* The contents to render when not editing
*/
contents: any;
- height: number
+ height: number;
display?: string;
}
@@ -38,7 +38,7 @@ export class EditableView extends React.Component<EditableProps> {
@action
onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
- if (e.key == "Enter") {
+ if (e.key === "Enter") {
if (!e.ctrlKey) {
if (this.props.SetValue(e.currentTarget.value)) {
this.editing = false;
@@ -47,7 +47,7 @@ export class EditableView extends React.Component<EditableProps> {
this.props.OnFillDown(e.currentTarget.value);
this.editing = false;
}
- } else if (e.key == "Escape") {
+ } else if (e.key === "Escape") {
this.editing = false;
}
}
@@ -55,14 +55,14 @@ export class EditableView extends React.Component<EditableProps> {
render() {
if (this.editing) {
return <input defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus onBlur={action(() => this.editing = false)}
- style={{ display: this.props.display }}></input>
+ style={{ display: this.props.display }}></input>;
} else {
return (
<div className="editableView-container-editing" style={{ display: this.props.display, height: "auto", maxHeight: `${this.props.height}` }}
onClick={action(() => this.editing = true)} >
{this.props.contents}
</div>
- )
+ );
}
}
} \ No newline at end of file
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
index c5a2a50cb..42ae38c73 100644
--- a/src/client/views/InkingCanvas.scss
+++ b/src/client/views/InkingCanvas.scss
@@ -1,5 +1,8 @@
@import "global_variables";
+.inkingCanvas {
+ opacity:0.99;
+}
.inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect {
position: absolute;
top: 0;
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 45ca52d00..47ee8eb85 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -10,6 +10,7 @@ import "./InkingCanvas.scss";
import { InkingControl } from "./InkingControl";
import { InkingStroke } from "./InkingStroke";
import React = require("react");
+import { undoBatch, UndoManager } from "../util/UndoManager";
interface InkCanvasProps {
getScreenTransform: () => Transform;
@@ -22,6 +23,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
maxCanvasDim = 8192 / 2; // 1/2 of the maximum canvas dimension for Chrome
@observable inkMidX: number = 0;
@observable inkMidY: number = 0;
+ private previousState?: StrokeMap;
private _currentStrokeId: string = "";
public static IntersectStrokeRect(stroke: StrokeData, selRect: { left: number, top: number, width: number, height: number }): boolean {
return stroke.pathData.reduce((inside: boolean, val) => inside ||
@@ -56,24 +58,29 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
@action
onPointerDown = (e: React.PointerEvent): void => {
- if (e.button != 0 || e.altKey || e.ctrlKey || InkingControl.Instance.selectedTool === InkTool.None) {
+ if (e.button !== 0 || e.altKey || e.ctrlKey || InkingControl.Instance.selectedTool === InkTool.None) {
return;
}
+
document.addEventListener("pointermove", this.onPointerMove, true);
document.addEventListener("pointerup", this.onPointerUp, true);
e.stopPropagation();
e.preventDefault();
- if (InkingControl.Instance.selectedTool != InkTool.Eraser) {
+ this.previousState = this.inkData;
+
+ if (InkingControl.Instance.selectedTool !== InkTool.Eraser) {
// start the new line, saves a uuid to represent the field of the stroke
this._currentStrokeId = Utils.GenerateGuid();
- this.inkData.set(this._currentStrokeId, {
+ const data = this.inkData;
+ data.set(this._currentStrokeId, {
pathData: [this.relativeCoordinatesForEvent(e.clientX, e.clientY)],
color: InkingControl.Instance.selectedColor,
width: InkingControl.Instance.selectedWidth,
tool: InkingControl.Instance.selectedTool,
page: this.props.Document.GetNumber(KeyStore.CurPage, -1)
});
+ this.inkData = data;
}
}
@@ -88,13 +95,23 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
}
e.stopPropagation();
e.preventDefault();
+
+ const batch = UndoManager.StartBatch("One ink stroke");
+ const oldState = this.previousState || new Map;
+ this.previousState = undefined;
+ const newState = this.inkData;
+ UndoManager.AddEvent({
+ undo: () => this.inkData = oldState,
+ redo: () => this.inkData = newState,
+ });
+ batch.end();
}
@action
onPointerMove = (e: PointerEvent): void => {
- e.stopPropagation()
+ e.stopPropagation();
e.preventDefault();
- if (InkingControl.Instance.selectedTool != InkTool.Eraser) {
+ if (InkingControl.Instance.selectedTool !== InkTool.Eraser) {
let data = this.inkData; // add points to new line as it is being drawn
let strokeData = data.get(this._currentStrokeId);
if (strokeData) {
@@ -110,6 +127,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
return { x, y };
}
+ @undoBatch
@action
removeLine = (id: string): void => {
let data = this.inkData;
@@ -119,34 +137,35 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
@computed
get drawnPaths() {
- let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1)
+ let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => {
- if (strokeData.page == -1 || strokeData.page == curPage)
+ if (strokeData.page === -1 || strokeData.page === curPage) {
paths.push(<InkingStroke key={id} id={id} line={strokeData.pathData}
offsetX={this.maxCanvasDim - this.inkMidX}
offsetY={this.maxCanvasDim - this.inkMidY}
color={strokeData.color} width={strokeData.width}
- tool={strokeData.tool} deleteCallback={this.removeLine} />)
+ tool={strokeData.tool} deleteCallback={this.removeLine} />);
+ }
return paths;
}, [] as JSX.Element[]);
return [<svg className={`inkingCanvas-paths-markers`} key="Markers"
style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }} >
- {paths.filter(path => path.props.tool == InkTool.Highlighter)}
+ {paths.filter(path => path.props.tool === InkTool.Highlighter)}
</svg>,
<svg className={`inkingCanvas-paths-ink`} key="Pens"
style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }}>
- {paths.filter(path => path.props.tool != InkTool.Highlighter)}
+ {paths.filter(path => path.props.tool !== InkTool.Highlighter)}
</svg>];
}
render() {
- let svgCanvasStyle = InkingControl.Instance.selectedTool != InkTool.None ? "canSelect" : "noSelect";
+ let svgCanvasStyle = InkingControl.Instance.selectedTool !== InkTool.None ? "canSelect" : "noSelect";
return (
<div className="inkingCanvas" >
<div className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} />
{this.props.children()}
{this.drawnPaths}
</div >
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index c1519dff8..9a68f0671 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -1,10 +1,10 @@
import { observable, action, computed } from "mobx";
-import { CirclePicker, ColorResult } from 'react-color'
+import { CirclePicker, ColorResult } from 'react-color';
import React = require("react");
import { InkTool } from "../../fields/InkField";
import { observer } from "mobx-react";
-import "./InkingControl.scss"
+import "./InkingControl.scss";
import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-svg-icons';
@@ -21,11 +21,11 @@ export class InkingControl extends React.Component {
@observable private _selectedColor: string = "rgb(244, 67, 54)";
@observable private _selectedWidth: string = "25";
@observable private _open: boolean = false;
- @observable private _colorPickerDisplay: boolean = false;
+ @observable private _colorPickerDisplay = false;
constructor(props: Readonly<{}>) {
super(props);
- InkingControl.Instance = this
+ InkingControl.Instance = this;
}
@action
@@ -36,9 +36,9 @@ export class InkingControl extends React.Component {
@action
switchColor = (color: ColorResult): void => {
this._selectedColor = color.hex;
- if (SelectionManager.SelectedDocuments().length == 1) {
+ if (SelectionManager.SelectedDocuments().length === 1) {
var sdoc = SelectionManager.SelectedDocuments()[0];
- if (sdoc.props.ContainingCollectionView && sdoc.props.ContainingCollectionView) {
+ if (sdoc.props.ContainingCollectionView) {
sdoc.props.Document.SetDataOnPrototype(KeyStore.BackgroundColor, color.hex, TextField);
}
}
@@ -66,9 +66,9 @@ export class InkingControl extends React.Component {
selected = (tool: InkTool) => {
if (this._selectedTool === tool) {
- return { color: "#61aaa3" }
+ return { color: "#61aaa3" };
}
- return {}
+ return {};
}
@action
@@ -76,6 +76,7 @@ export class InkingControl extends React.Component {
this._open = !this._open;
}
+
@action
toggleColorPicker = () => {
this._colorPickerDisplay = !this._colorPickerDisplay;
@@ -110,6 +111,6 @@ export class InkingControl extends React.Component {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => this.switchWidth(e.target.value)} />
</li>
</ul >
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 615f8af7e..0f05da22c 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -41,7 +41,7 @@ export class InkingStroke extends React.Component<StrokeProps> {
fill: "none",
stroke: this._strokeColor,
strokeWidth: this._strokeWidth + "px",
- }
+ };
}
}
@@ -49,10 +49,10 @@ export class InkingStroke extends React.Component<StrokeProps> {
let pathStyle = this.createStyle();
let pathData = this.parseData(this.props.line);
- let pointerEvents: any = InkingControl.Instance.selectedTool == InkTool.Eraser ? "all" : "none";
+ let pointerEvents: any = InkingControl.Instance.selectedTool === InkTool.Eraser ? "all" : "none";
return (
<path d={pathData} style={{ ...pathStyle, pointerEvents: pointerEvents }} strokeLinejoin="round" strokeLinecap="round"
onPointerOver={this.deleteStroke} onPointerDown={this.deleteStroke} />
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 594803aab..fe7f007b0 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -4,7 +4,7 @@ html,
body {
width: 100%;
height: 100%;
- overflow: hidden;
+ overflow: auto;
font-family: $sans-serif;
margin: 0;
position:absolute;
@@ -157,12 +157,33 @@ button:hover {
cursor: pointer;
}
}
+#root {
+ overflow: visible;
+}
#main-div {
width:100%;
height:100%;
position:absolute;
top: 0;
left:0;
+ overflow: scroll;
+}
+.mainDiv-textInput {
+ background:pink;
+ width: 200px;
+ height: 200px;
+ position:absolute;
+ overflow: visible;
+ top: 0;
+ left: 0;
+ .formattedTextBox-cont {
+ background:pink;
+ width: 100%;
+ height: 100%;
+ position:absolute;
+ top: 0;
+ left: 0;
+ }
}
#mainContent-div {
width:100%;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 9251860a0..35d5e8a35 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -1,7 +1,7 @@
import { IconName, library } from '@fortawesome/fontawesome-svg-core';
import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, configure, observable, runInAction } from 'mobx';
+import { action, computed, configure, observable, runInAction, trace } from 'mobx';
import { observer } from 'mobx-react';
import "normalize.css";
import * as React from 'react';
@@ -15,9 +15,10 @@ import { ListField } from '../../fields/ListField';
import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu';
import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
import { MessageStore } from '../../server/Message';
+import { Utils, returnTrue, emptyFunction } from '../../Utils';
+import * as rp from 'request-promise';
import { RouteStore } from '../../server/RouteStore';
import { ServerUtils } from '../../server/ServerUtil';
-import { Utils } from '../../Utils';
import { Documents } from '../documents/Documents';
import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
@@ -36,6 +37,7 @@ import { DocumentDecorations } from './DocumentDecorations';
import { InkingControl } from './InkingControl';
import "./Main.scss";
import { DocumentView } from './nodes/DocumentView';
+import { FormattedTextBox } from './nodes/FormattedTextBox';
@observer
export class Main extends React.Component {
@@ -47,7 +49,7 @@ export class Main extends React.Component {
@computed private get mainContainer(): Document | undefined {
let doc = this.userDocument.GetT(KeyStore.ActiveWorkspace, Document);
- return doc == FieldWaiting ? undefined : doc;
+ return doc === FieldWaiting ? undefined : doc;
}
private set mainContainer(doc: Document | undefined) {
@@ -69,10 +71,10 @@ export class Main extends React.Component {
configure({ enforceActions: "observed" });
if (window.location.pathname !== RouteStore.home) {
let pathname = window.location.pathname.split("/");
- if (pathname.length > 1 && pathname[pathname.length - 2] == 'doc') {
+ if (pathname.length > 1 && pathname[pathname.length - 2] === 'doc') {
CurrentUserUtils.MainDocId = pathname[pathname.length - 1];
}
- };
+ }
CurrentUserUtils.loadCurrentUser();
@@ -117,8 +119,8 @@ export class Main extends React.Component {
initEventListeners = () => {
// window.addEventListener("pointermove", (e) => this.reportLocation(e))
- window.addEventListener("drop", (e) => e.preventDefault(), false) // drop event handler
- window.addEventListener("dragover", (e) => e.preventDefault(), false) // drag event handler
+ window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler
+ window.addEventListener("dragover", (e) => e.preventDefault(), false); // drag event handler
// click interactions for the context menu
document.addEventListener("pointerdown", action(function (e: PointerEvent) {
if (!ContextMenu.Instance.intersects(e.pageX, e.pageY)) {
@@ -137,15 +139,15 @@ export class Main extends React.Component {
} else {
this.createNewWorkspace();
}
- })
+ });
} else {
Server.GetField(CurrentUserUtils.MainDocId).then(field => {
if (field instanceof Document) {
- this.openWorkspace(field)
+ this.openWorkspace(field);
} else {
this.createNewWorkspace(CurrentUserUtils.MainDocId);
}
- })
+ });
}
}
@@ -161,7 +163,7 @@ export class Main extends React.Component {
// bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
setTimeout(() => {
this.openWorkspace(mainDoc);
- let pendingDocument = Documents.SchemaDocument([], { title: "New Mobile Uploads" })
+ let pendingDocument = Documents.SchemaDocument([], { title: "New Mobile Uploads" });
mainDoc.Set(KeyStore.OptionalRightCollection, pendingDocument);
}, 0);
}
@@ -180,7 +182,7 @@ export class Main extends React.Component {
if (f && f.Data.length > 0) {
CollectionDockingView.Instance.AddRightSplit(col);
}
- })
+ });
}
}, 100);
});
@@ -189,46 +191,70 @@ export class Main extends React.Component {
@observable
workspacesShown: boolean = false;
- areWorkspacesShown = () => {
- return this.workspacesShown;
- }
+ areWorkspacesShown = () => this.workspacesShown;
@action
toggleWorkspaces = () => {
this.workspacesShown = !this.workspacesShown;
}
- screenToLocalTransform = () => Transform.Identity
pwidthFunc = () => this.pwidth;
pheightFunc = () => this.pheight;
- focusDocument = (doc: Document) => { }
+ focusDocument = (doc: Document) => { };
noScaling = () => 1;
+ @observable _textDoc?: Document = undefined;
+ _textRect: any;
+ @action
+ SetTextDoc(textDoc?: Document, div?: HTMLDivElement) {
+ this._textDoc = undefined;
+ this._textDoc = textDoc;
+ if (div) {
+ this._textRect = div.getBoundingClientRect();
+ }
+ }
+
+ @computed
+ get activeTextBox() {
+ if (this._textDoc) {
+ let x: number = this._textRect.x;
+ let y: number = this._textRect.y;
+ let w: number = this._textRect.width;
+ let h: number = this._textRect.height;
+ return <div className="mainDiv-textInput" style={{ transform: `translate(${x}px, ${y}px)`, width: `${w}px`, height: `${h}px` }} >
+ <FormattedTextBox fieldKey={KeyStore.Archives} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={Transform.Identity} focus={(doc) => { }} />
+ </ div>;
+ }
+ else return (null);
+ }
+
@computed
get mainContent() {
return !this.mainContainer ? (null) :
<DocumentView Document={this.mainContainer}
- AddDocument={undefined}
- RemoveDocument={undefined}
- ScreenToLocalTransform={this.screenToLocalTransform}
+ addDocument={undefined}
+ removeDocument={undefined}
+ ScreenToLocalTransform={Transform.Identity}
ContentScaling={this.noScaling}
PanelWidth={this.pwidthFunc}
PanelHeight={this.pheightFunc}
isTopMost={true}
- SelectOnLoad={false}
+ selectOnLoad={false}
focus={this.focusDocument}
- ContainingCollectionView={undefined} />
+ parentActive={returnTrue}
+ onActiveChanged={emptyFunction}
+ ContainingCollectionView={undefined} />;
}
/* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */
@computed
get nodesMenu() {
let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
- let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf"
+ let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf";
let weburl = "https://cs.brown.edu/courses/cs166/";
let audiourl = "http://techslides.com/demos/samples/sample.mp3";
let videourl = "http://techslides.com/demos/sample-videos/small.mp4";
- let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" }))
+ let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" }));
let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
let addSchemaNode = action(() => Documents.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" }));
let addTreeNode = action(() => Documents.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", copyDraggedItems: true }));
@@ -236,7 +262,7 @@ export class Main extends React.Component {
let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" }));
let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" }));
let addWebNode = action(() => Documents.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" }));
- let addAudioNode = action(() => Documents.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" }))
+ let addAudioNode = action(() => Documents.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" }));
let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Document][] = [
[React.createRef<HTMLDivElement>(), "font", "Add Textbox", addTextNode],
@@ -248,7 +274,7 @@ export class Main extends React.Component {
[React.createRef<HTMLDivElement>(), "object-group", "Add Collection", addColNode],
[React.createRef<HTMLDivElement>(), "tree", "Add Tree", addTreeNode],
[React.createRef<HTMLDivElement>(), "table", "Add Schema", addSchemaNode],
- ]
+ ];
return < div id="add-nodes-menu" >
<input type="checkbox" id="add-menu-toggle" />
@@ -264,7 +290,7 @@ export class Main extends React.Component {
</div></li>)}
</ul>
</div>
- </div >
+ </div >;
}
/* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */
@@ -273,7 +299,7 @@ export class Main extends React.Component {
let workspacesRef = React.createRef<HTMLDivElement>();
let logoutRef = React.createRef<HTMLDivElement>();
- let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}))
+ let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}));
return [
<button className="clear-db-button" key="clear-db" onClick={clearDatabase}>Clear Database</button>,
<div id="toolbar" key="toolbar">
@@ -285,7 +311,7 @@ export class Main extends React.Component {
<button onClick={this.toggleWorkspaces}>Workspaces</button></div>,
<div className="main-buttonDiv" key="logout" style={{ top: '34px', right: '1px', position: 'absolute' }} ref={logoutRef}>
<button onClick={() => request.get(ServerUtils.prepend(RouteStore.logout), () => { })}>Log Out</button></div>
- ]
+ ];
}
@@ -294,36 +320,39 @@ export class Main extends React.Component {
let workspaces = this.userDocument.GetT<ListField<Document>>(KeyStore.Workspaces, ListField);
if (workspaces && workspaces !== FieldWaiting) {
workspaceMenu = <WorkspacesMenu active={this.mainContainer} open={this.openWorkspace} new={this.createNewWorkspace} allWorkspaces={workspaces.Data}
- isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} />
+ isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} />;
}
return (
- <div id="main-div">
- <DocumentDecorations />
- <Measure onResize={(r: any) => runInAction(() => {
- this.pwidth = r.entry.width;
- this.pheight = r.entry.height;
- })}>
- {({ measureRef }) =>
- <div ref={measureRef} id="mainContent-div">
- {this.mainContent}
- </div>
- }
- </Measure>
- <ContextMenu />
- {this.nodesMenu}
- {this.miscButtons}
- {workspaceMenu}
- <InkingControl />
- </div>
+ <>
+ <div id="main-div">
+ <DocumentDecorations />
+ <Measure onResize={(r: any) => runInAction(() => {
+ this.pwidth = r.entry.width;
+ this.pheight = r.entry.height;
+ })}>
+ {({ measureRef }) =>
+ <div ref={measureRef} id="mainContent-div">
+ {this.mainContent}
+ </div>
+ }
+ </Measure>
+ <ContextMenu />
+ {this.nodesMenu}
+ {this.miscButtons}
+ {workspaceMenu}
+ <InkingControl />
+ </div>
+ {this.activeTextBox}
+ </>
);
}
// --------------- Northstar hooks ------------- /
- @action SetNorthstarCatalog(ctlog: Catalog) {
- CurrentUserUtils.NorthstarDBCatalog = ctlog;
+ @action AddToNorthstarCatalog(ctlog: Catalog) {
+ CurrentUserUtils.NorthstarDBCatalog = CurrentUserUtils.NorthstarDBCatalog ? CurrentUserUtils.NorthstarDBCatalog : ctlog;
if (ctlog && ctlog.schemas) {
- this._northstarSchemas = ctlog.schemas.map(schema => {
+ this._northstarSchemas.push(...ctlog.schemas.map(schema => {
let schemaDoc = Documents.TreeDocument([], { width: 50, height: 100, title: schema.displayName! });
let schemaDocuments = schemaDoc.GetList(KeyStore.Data, [] as Document[]);
CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
@@ -332,7 +361,7 @@ export class Main extends React.Component {
schemaDocuments.push(field);
} else {
var atmod = new ColumnAttributeModel(attr);
- let histoOp = new HistogramOperation(schema!.displayName!,
+ let histoOp = new HistogramOperation(schema.displayName!,
new AttributeTransformationModel(atmod, AggregateFunction.None),
new AttributeTransformationModel(atmod, AggregateFunction.Count),
new AttributeTransformationModel(atmod, AggregateFunction.Count));
@@ -341,7 +370,7 @@ export class Main extends React.Component {
}));
});
return schemaDoc;
- })
+ }));
}
}
async initializeNorthstar(): Promise<void> {
@@ -354,12 +383,17 @@ export class Main extends React.Component {
const env = await response.json();
Settings.Instance.Update(env);
let cat = Gateway.Instance.ClearCatalog();
- cat.then(async () => this.SetNorthstarCatalog(await Gateway.Instance.GetCatalog()));
+ cat.then(async () => {
+ this.AddToNorthstarCatalog(await Gateway.Instance.GetCatalog());
+ if (!CurrentUserUtils.GetNorthstarSchema("Book1"))
+ this.AddToNorthstarCatalog(await Gateway.Instance.GetSchema("http://www.cs.brown.edu/~bcz/Book1.csv"));
+ });
+
}
}
-Documents.initProtos().then(() => {
- return CurrentUserUtils.loadCurrentUser()
-}).then(() => {
+(async () => {
+ await Documents.initProtos();
+ await CurrentUserUtils.loadCurrentUser();
ReactDOM.render(<Main />, document.getElementById('root'));
-});
+})();
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
new file mode 100644
index 000000000..4380c8194
--- /dev/null
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -0,0 +1,187 @@
+import { action } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { Document } from '../../../fields/Document';
+import { Field, FieldValue, FieldWaiting } from '../../../fields/Field';
+import { KeyStore } from '../../../fields/KeyStore';
+import { ListField } from '../../../fields/ListField';
+import { NumberField } from '../../../fields/NumberField';
+import { ContextMenu } from '../ContextMenu';
+import { FieldViewProps } from '../nodes/FieldView';
+
+export enum CollectionViewType {
+ Invalid,
+ Freeform,
+ Schema,
+ Docking,
+ Tree,
+}
+
+export interface CollectionRenderProps {
+ addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
+ removeDocument: (document: Document) => boolean;
+ moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
+ active: () => boolean;
+ onActiveChanged: (isActive: boolean) => void;
+}
+
+export interface CollectionViewProps extends FieldViewProps {
+ onContextMenu?: (e: React.MouseEvent) => void;
+ children: (type: CollectionViewType, props: CollectionRenderProps) => JSX.Element | JSX.Element[] | null;
+ className?: string;
+ contentRef?: React.Ref<HTMLDivElement>;
+}
+
+export const COLLECTION_BORDER_WIDTH = 1;
+
+@observer
+export class CollectionBaseView extends React.Component<CollectionViewProps> {
+ get collectionViewType(): CollectionViewType {
+ let Document = this.props.Document;
+ let viewField = Document.GetT(KeyStore.ViewType, NumberField);
+ if (viewField === FieldWaiting) {
+ return CollectionViewType.Invalid;
+ } else if (viewField) {
+ return viewField.Data;
+ } else {
+ return CollectionViewType.Freeform;
+ }
+ }
+
+ active = (): boolean => {
+ var isSelected = this.props.isSelected();
+ var topMost = this.props.isTopMost;
+ return isSelected || this._isChildActive || topMost;
+ }
+
+ //TODO should this be observable?
+ private _isChildActive = false;
+ onActiveChanged = (isActive: boolean) => {
+ this._isChildActive = isActive;
+ this.props.onActiveChanged(isActive);
+ }
+
+ createsCycle(documentToAdd: Document, containerDocument: Document): boolean {
+ let data = documentToAdd.GetList<Document>(KeyStore.Data, []);
+ for (const doc of data) {
+ if (this.createsCycle(doc, containerDocument)) {
+ return true;
+ }
+ }
+ let annots = documentToAdd.GetList<Document>(KeyStore.Annotations, []);
+ for (const annot of annots) {
+ if (this.createsCycle(annot, containerDocument)) {
+ return true;
+ }
+ }
+ for (let containerProto: FieldValue<Document> = containerDocument; containerProto && containerProto !== FieldWaiting; containerProto = containerProto.GetPrototype()) {
+ if (containerProto.Id === documentToAdd.Id) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @action.bound
+ addDocument(doc: Document, allowDuplicates: boolean = false): boolean {
+ let props = this.props;
+ var curPage = props.Document.GetNumber(KeyStore.CurPage, -1);
+ doc.SetOnPrototype(KeyStore.Page, new NumberField(curPage));
+ if (curPage >= 0) {
+ doc.SetOnPrototype(KeyStore.AnnotationOn, props.Document);
+ }
+ if (props.Document.Get(props.fieldKey) instanceof Field) {
+ //TODO This won't create the field if it doesn't already exist
+ const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>());
+ if (!this.createsCycle(doc, props.Document)) {
+ if (!value.some(v => v.Id === doc.Id) || allowDuplicates) {
+ value.push(doc);
+ }
+ }
+ else {
+ return false;
+ }
+ } else {
+ let proto = props.Document.GetPrototype();
+ if (!proto || proto === FieldWaiting || !this.createsCycle(proto, doc)) {
+ const field = new ListField([doc]);
+ // const script = CompileScript(`
+ // if(added) {
+ // console.log("added " + field.Title);
+ // } else {
+ // console.log("removed " + field.Title);
+ // }
+ // `, {
+ // addReturn: false,
+ // params: {
+ // field: Document.name,
+ // added: "boolean"
+ // }
+ // });
+ // if (script.compiled) {
+ // field.addScript(new ScriptField(script));
+ // }
+ props.Document.SetOnPrototype(props.fieldKey, field);
+ }
+ else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @action.bound
+ removeDocument(doc: Document): boolean {
+ const props = this.props;
+ //TODO This won't create the field if it doesn't already exist
+ const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>());
+ let index = -1;
+ for (let i = 0; i < value.length; i++) {
+ if (value[i].Id === doc.Id) {
+ index = i;
+ break;
+ }
+ }
+ doc.GetTAsync(KeyStore.AnnotationOn, Document).then((annotationOn) => {
+ if (annotationOn === props.Document) {
+ doc.Set(KeyStore.AnnotationOn, undefined, true);
+ }
+ });
+
+ if (index !== -1) {
+ value.splice(index, 1);
+
+ // SelectionManager.DeselectAll()
+ ContextMenu.Instance.clearItems();
+ return true;
+ }
+ return false;
+ }
+
+ @action.bound
+ moveDocument(doc: Document, targetCollection: Document, addDocument: (doc: Document) => boolean): boolean {
+ if (this.props.Document === targetCollection) {
+ return true;
+ }
+ if (this.removeDocument(doc)) {
+ return addDocument(doc);
+ }
+ return false;
+ }
+
+ render() {
+ const props: CollectionRenderProps = {
+ addDocument: this.addDocument,
+ removeDocument: this.removeDocument,
+ moveDocument: this.moveDocument,
+ active: this.active,
+ onActiveChanged: this.onActiveChanged,
+ };
+ return (
+ <div className={this.props.className || "collectionView-cont"} onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
+ {this.props.children(this.collectionViewType, props)}
+ </div>
+ );
+ }
+
+} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 921ee4591..ea6d3a247 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -8,14 +8,14 @@ import { Document } from "../../../fields/Document";
import { KeyStore } from "../../../fields/KeyStore";
import Measure from "react-measure";
import { FieldId, Opt, Field } from "../../../fields/Field";
-import { Utils } from "../../../Utils";
+import { Utils, returnTrue, emptyFunction } from "../../../Utils";
import { Server } from "../../Server";
import { undoBatch } from "../../util/UndoManager";
import { DocumentView } from "../nodes/DocumentView";
import "./CollectionDockingView.scss";
-import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
+import { COLLECTION_BORDER_WIDTH } from "./CollectionBaseView";
import React = require("react");
-import { SubCollectionViewProps } from "./CollectionViewBase";
+import { SubCollectionViewProps } from "./CollectionSubView";
import { ServerUtils } from "../../../server/ServerUtil";
import { DragManager } from "../../util/DragManager";
import { TextField } from "../../../fields/TextField";
@@ -32,7 +32,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
documentId: document.Id,
//collectionDockingView: CollectionDockingView.Instance
}
- }
+ };
}
private _goldenLayout: any = null;
@@ -58,7 +58,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
let newItemStackConfig = {
type: 'stack',
content: [CollectionDockingView.makeDocumentConfig(document)]
- }
+ };
var docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
this._goldenLayout.root.contentItems[0].addChild(docconfig);
docconfig.callDownwards('_$init');
@@ -86,7 +86,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
let newItemStackConfig = {
type: 'stack',
content: [CollectionDockingView.makeDocumentConfig(document)]
- }
+ };
var newContentItem = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
@@ -101,12 +101,12 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
newRow.addChild(newContentItem, undefined, true);
newRow.addChild(collayout, 0, true);
- collayout.config["width"] = 50;
- newContentItem.config["width"] = 50;
+ collayout.config.width = 50;
+ newContentItem.config.width = 50;
}
if (minimize) {
- newContentItem.config["width"] = 10;
- newContentItem.config["height"] = 10;
+ newContentItem.config.width = 10;
+ newContentItem.config.height = 10;
}
newContentItem.callDownwards('_$init');
this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
@@ -124,8 +124,9 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
this._goldenLayout = new GoldenLayout(JSON.parse(config));
}
else {
- if (config == JSON.stringify(this._goldenLayout.toConfig()))
+ if (config === JSON.stringify(this._goldenLayout.toConfig())) {
return;
+ }
try {
this._goldenLayout.unbind('itemDropped', this.itemDropped);
this._goldenLayout.unbind('tabCreated', this.tabCreated);
@@ -154,7 +155,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
reaction(
() => this.props.Document.GetText(KeyStore.Data, ""),
() => {
- if (!this._goldenLayout || this._ignoreStateChange != JSON.stringify(this._goldenLayout.toConfig())) {
+ if (!this._goldenLayout || this._ignoreStateChange !== JSON.stringify(this._goldenLayout.toConfig())) {
setTimeout(() => this.setupGoldenLayout(), 1);
}
this._ignoreStateChange = "";
@@ -193,23 +194,24 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
@action
onPointerDown = (e: React.PointerEvent): void => {
var className = (e.target as any).className;
- if ((className == "lm_title" || className == "lm_tab lm_active") && (e.ctrlKey || e.altKey)) {
+ if ((className === "lm_title" || className === "lm_tab lm_active") && (e.ctrlKey || e.altKey)) {
e.stopPropagation();
e.preventDefault();
let docid = (e.target as any).DashDocId;
let tab = (e.target as any).parentElement as HTMLElement;
Server.GetField(docid, action((f: Opt<Field>) => {
- if (f instanceof Document)
- DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f as Document]), e.pageX, e.pageY,
+ if (f instanceof Document) {
+ DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), e.pageX, e.pageY,
{
handlers: {
dragComplete: action(() => { }),
},
hideSource: false
- })
+ });
+ }
}));
}
- if (className == "lm_drag_handle" || className == "lm_close" || className == "lm_maximise" || className == "lm_minimise" || className == "lm_close_tab") {
+ if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") {
this._flush = true;
}
if (this.props.active()) {
@@ -220,22 +222,23 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
@undoBatch
stateChanged = () => {
var json = JSON.stringify(this._goldenLayout.toConfig());
- this.props.Document.SetText(KeyStore.Data, json)
+ this.props.Document.SetText(KeyStore.Data, json);
}
itemDropped = () => {
this.stateChanged();
}
+
tabCreated = (tab: any) => {
- if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type != "stack") {
- if (tab.titleElement[0].textContent.indexOf("-waiting") != -1) {
+ if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
+ if (tab.titleElement[0].textContent.indexOf("-waiting") !== -1) {
Server.GetField(tab.contentItem.config.props.documentId, action((f: Opt<Field>) => {
- if (f != undefined && f instanceof Document) {
+ if (f !== undefined && f instanceof Document) {
f.GetTAsync(KeyStore.Title, TextField, (tfield) => {
- if (tfield != undefined) {
+ if (tfield !== undefined) {
tab.titleElement[0].textContent = f.Title;
}
- })
+ });
}
}));
tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
@@ -280,7 +283,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
}
interface DockedFrameProps {
- documentId: FieldId,
+ documentId: FieldId;
//collectionDockingView: CollectionDockingView
}
@observer
@@ -296,35 +299,38 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
Server.GetField(this.props.documentId, action((f: Opt<Field>) => this._document = f as Document));
}
- private _nativeWidth = () => { return this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth); }
- private _nativeHeight = () => { return this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight); }
- private _contentScaling = () => { return this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth); }
+ private _nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth);
+ private _nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight);
+ private _contentScaling = () => this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth);
ScreenToLocalTransform = () => {
let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
- return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._contentScaling())
+ return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._contentScaling());
}
render() {
- if (!this._document)
+ if (!this._document) {
return (null);
+ }
var content =
<div className="collectionDockingView-content" ref={this._mainCont}>
<DocumentView key={this._document.Id} Document={this._document}
- AddDocument={undefined}
- RemoveDocument={undefined}
+ addDocument={undefined}
+ removeDocument={undefined}
ContentScaling={this._contentScaling}
PanelWidth={this._nativeWidth}
PanelHeight={this._nativeHeight}
ScreenToLocalTransform={this.ScreenToLocalTransform}
isTopMost={true}
- SelectOnLoad={false}
+ selectOnLoad={false}
+ parentActive={returnTrue}
+ onActiveChanged={emptyFunction}
focus={(doc: Document) => { }}
ContainingCollectionView={undefined} />
- </div>
+ </div>;
return <Measure onResize={action((r: any) => { this._panelWidth = r.entry.width; this._panelHeight = r.entry.height; })}>
{({ measureRef }) => <div ref={measureRef}> {content} </div>}
- </Measure>
+ </Measure>;
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 4d2daf149..97bac745c 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -1,22 +1,19 @@
import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { Document } from "../../../fields/Document";
import { KeyStore } from "../../../fields/KeyStore";
import { ContextMenu } from "../ContextMenu";
-import { CollectionView, CollectionViewType } from "./CollectionView";
-import { CollectionViewProps } from "./CollectionViewBase";
-import "./CollectionPDFView.scss"
+import "./CollectionPDFView.scss";
import React = require("react");
-import { FieldId } from "../../../fields/Field";
+import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
+import { FieldView, FieldViewProps } from "../nodes/FieldView";
+import { CollectionRenderProps, CollectionBaseView, CollectionViewType } from "./CollectionBaseView";
@observer
-export class CollectionPDFView extends React.Component<CollectionViewProps> {
+export class CollectionPDFView extends React.Component<FieldViewProps> {
public static LayoutString(fieldKey: string = "DataKey") {
- return `<${CollectionPDFView.name} Document={Document}
- ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} panelWidth={PanelWidth} panelHeight={PanelHeight} isSelected={isSelected} select={select} bindings={bindings}
- isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`;
+ return FieldView.LayoutString(CollectionPDFView, fieldKey);
}
private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, -1); }
@@ -25,35 +22,36 @@ export class CollectionPDFView extends React.Component<CollectionViewProps> {
@action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : -1;
private get uIButtons() {
- let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().transformDirection(1, 1)[0]);
+ let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale);
return (
<div className="collectionPdfView-buttonTray" key="tray" style={{ transform: `scale(${scaling}, ${scaling})` }}>
<button className="collectionPdfView-backward" onClick={this.onPageBack}>{"<"}</button>
<button className="collectionPdfView-forward" onClick={this.onPageForward}>{">"}</button>
- </div>);
+ </div>
+ );
}
- // "inherited" CollectionView API starts here...
- @observable
- public SelectedDocs: FieldId[] = []
- public active: () => boolean = () => CollectionView.Active(this);
-
- addDocument = (doc: Document, allowDuplicates: boolean): boolean => { return CollectionView.AddDocument(this.props, doc, allowDuplicates); }
- removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); }
-
- specificContextMenu = (e: React.MouseEvent): void => {
- if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+ onContextMenu = (e: React.MouseEvent): void => {
+ if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } });
}
}
- get collectionViewType(): CollectionViewType { return CollectionViewType.Freeform; }
- get subView(): any { return CollectionView.SubView(this); }
+ private subView = (_type: CollectionViewType, renderProps: CollectionRenderProps) => {
+ let props = { ...this.props, ...renderProps };
+ return (
+ <>
+ <CollectionFreeFormView {...props} />
+ {this.props.isSelected() ? this.uIButtons : (null)}
+ </>
+ );
+ }
render() {
- return (<div className="collectionPdfView-cont" onContextMenu={this.specificContextMenu}>
- {this.subView}
- {this.props.isSelected() ? this.uIButtons : (null)}
- </div>)
+ return (
+ <CollectionBaseView {...this.props} className="collectionPdfView-cont" onContextMenu={this.onContextMenu}>
+ {this.subView}
+ </CollectionBaseView>
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index b10aaba98..587f60b3d 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -22,9 +22,11 @@ import { EditableView } from "../EditableView";
import { DocumentView } from "../nodes/DocumentView";
import { FieldView, FieldViewProps } from "../nodes/FieldView";
import "./CollectionSchemaView.scss";
-import { CollectionView, COLLECTION_BORDER_WIDTH } from "./CollectionView";
-import { CollectionViewBase } from "./CollectionViewBase";
+import { CollectionView } from "./CollectionView";
+import { CollectionSubView } from "./CollectionSubView";
import { TextField } from "../../../fields/TextField";
+import { COLLECTION_BORDER_WIDTH } from "./CollectionBaseView";
+import { emptyFunction, returnFalse } from "../../../Utils";
// bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -39,7 +41,7 @@ class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggl
if (field instanceof Key) {
this.key = field;
}
- }))
+ }));
}
render() {
@@ -47,14 +49,14 @@ class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggl
return (<div key={this.key.Id}>
<input type="checkbox" checked={this.props.checked} onChange={() => this.key && this.props.toggle(this.key)} />
{this.key.Name}
- </div>)
+ </div>);
}
return (null);
}
}
@observer
-export class CollectionSchemaView extends CollectionViewBase {
+export class CollectionSchemaView extends CollectionSubView {
private _mainCont = React.createRef<HTMLDivElement>();
private _startSplitPercent = 0;
private DIVIDER_WIDTH = 4;
@@ -73,19 +75,22 @@ export class CollectionSchemaView extends CollectionViewBase {
renderCell = (rowProps: CellInfo) => {
let props: FieldViewProps = {
- doc: rowProps.value[0],
+ Document: rowProps.value[0],
fieldKey: rowProps.value[1],
isSelected: () => false,
select: () => { },
isTopMost: false,
- bindings: {},
selectOnLoad: false,
- }
+ ScreenToLocalTransform: Transform.Identity,
+ focus: emptyFunction,
+ active: returnFalse,
+ onActiveChanged: emptyFunction,
+ };
let contents = (
<FieldView {...props} />
- )
+ );
let reference = React.createRef<HTMLDivElement>();
- let onItemDown = setupDrag(reference, () => props.doc, (containingCollection: CollectionView) => this.props.removeDocument(props.doc));
+ let onItemDown = setupDrag(reference, () => props.Document, this.props.moveDocument);
let applyToDoc = (doc: Document, run: (args?: { [name: string]: any }) => any) => {
const res = run({ this: doc });
if (!res.success) return false;
@@ -101,29 +106,29 @@ export class CollectionSchemaView extends CollectionViewBase {
}
}
return false;
- }
+ };
return (
- <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "56px" }} key={props.doc.Id} ref={reference}>
+ <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "56px" }} key={props.Document.Id} ref={reference}>
<EditableView
display={"inline"}
contents={contents}
height={56}
GetValue={() => {
- let field = props.doc.Get(props.fieldKey);
+ let field = props.Document.Get(props.fieldKey);
if (field && field instanceof Field) {
return field.ToScriptString();
}
return field || "";
}}
SetValue={(value: string) => {
- let script = CompileScript(value, { addReturn: true, params: { this: "Document" } });
+ let script = CompileScript(value, { addReturn: true, params: { this: Document.name } });
if (!script.compiled) {
return false;
}
- return applyToDoc(props.doc, script.run);
+ return applyToDoc(props.Document, script.run);
}}
OnFillDown={(value: string) => {
- let script = CompileScript(value, { addReturn: true, params: { this: "Document" } });
+ let script = CompileScript(value, { addReturn: true, params: { this: Document.name } });
if (!script.compiled) {
return;
}
@@ -133,11 +138,11 @@ export class CollectionSchemaView extends CollectionViewBase {
if (val) {
val.Data.forEach(doc => applyToDoc(doc, run));
}
- })
+ });
}}>
</EditableView>
</div>
- )
+ );
}
private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
@@ -151,12 +156,12 @@ export class CollectionSchemaView extends CollectionViewBase {
that._selectedIndex = rowInfo.index;
if (handleOriginal) {
- handleOriginal()
+ handleOriginal();
}
}),
style: {
- background: rowInfo.index == this._selectedIndex ? "lightGray" : "white",
- //color: rowInfo.index == this._selectedIndex ? "white" : "black"
+ background: rowInfo.index === this._selectedIndex ? "lightGray" : "white",
+ //color: rowInfo.index === this._selectedIndex ? "white" : "black"
}
};
}
@@ -177,22 +182,22 @@ export class CollectionSchemaView extends CollectionViewBase {
this.columns.splice(index, 1);
}
- })
+ });
}
//toggles preview side-panel of schema
@action
toggleExpander = (event: React.ChangeEvent<HTMLInputElement>) => {
this._startSplitPercent = this.splitPercentage;
- if (this._startSplitPercent == this.splitPercentage) {
- this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0);
+ if (this._startSplitPercent === this.splitPercentage) {
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage === 0 ? 33 : 0);
}
}
@computed
get findAllDocumentKeys(): { [id: string]: boolean } {
const docs = this.props.Document.GetList<Document>(this.props.fieldKey, []);
- let keys: { [id: string]: boolean } = {}
+ let keys: { [id: string]: boolean } = {};
if (this._optionsActivated > -1) {
// bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields.
// then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be
@@ -201,7 +206,7 @@ export class CollectionSchemaView extends CollectionViewBase {
// is displayed (unlikely) it won't show up until something else changes.
untracked(() => docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))));
}
- this.columns.forEach(key => keys[key.Id] = true)
+ this.columns.forEach(key => keys[key.Id] = true);
return keys;
}
@@ -214,8 +219,8 @@ export class CollectionSchemaView extends CollectionViewBase {
onDividerUp = (e: PointerEvent): void => {
document.removeEventListener("pointermove", this.onDividerMove);
document.removeEventListener('pointerup', this.onDividerUp);
- if (this._startSplitPercent == this.splitPercentage) {
- this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0);
+ if (this._startSplitPercent === this.splitPercentage) {
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage === 0 ? 33 : 0);
}
}
onDividerDown = (e: React.PointerEvent) => {
@@ -243,14 +248,10 @@ export class CollectionSchemaView extends CollectionViewBase {
getContentScaling = (): number => this._contentScaling;
getPanelWidth = (): number => this._panelWidth;
getPanelHeight = (): number => this._panelHeight;
- getTransform = (): Transform => {
- return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
- }
- getPreviewTransform = (): Transform => {
- return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
- }
+ getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
+ getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
- focusDocument = (doc: Document) => { }
+ focusDocument = (doc: Document) => { };
onPointerDown = (e: React.PointerEvent): void => {
if (this.props.isSelected()) {
@@ -272,8 +273,9 @@ export class CollectionSchemaView extends CollectionViewBase {
this.newKeyName = e.currentTarget.value;
}
onWheel = (e: React.WheelEvent): void => {
- if (this.props.active())
+ if (this.props.active()) {
e.stopPropagation();
+ }
}
@observable _optionsActivated: number = 0;
@@ -299,29 +301,31 @@ export class CollectionSchemaView extends CollectionViewBase {
let doc: any = selected ? selected.Get(new Key(this.previewScript)) : undefined;
// let doc = CompileScript(this.previewScript, { this: selected }, true)();
- let content = this._selectedIndex == -1 || !selected ? (null) : (
+ let content = this._selectedIndex === -1 || !selected ? (null) : (
<Measure onResize={this.setScaling}>
{({ measureRef }) =>
<div className="collectionSchemaView-content" ref={measureRef}>
- {doc instanceof Document ? <DocumentView Document={doc}
- AddDocument={this.props.addDocument} RemoveDocument={this.props.removeDocument}
- isTopMost={false}
- SelectOnLoad={false}
- ScreenToLocalTransform={this.getPreviewTransform}
- ContentScaling={this.getContentScaling}
- PanelWidth={this.getPanelWidth}
- PanelHeight={this.getPanelHeight}
- ContainingCollectionView={this.props.CollectionView}
- focus={this.focusDocument}
- /> : null}
+ {doc instanceof Document ?
+ <DocumentView Document={doc}
+ addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+ isTopMost={false}
+ selectOnLoad={false}
+ ScreenToLocalTransform={this.getPreviewTransform}
+ ContentScaling={this.getContentScaling}
+ PanelWidth={this.getPanelWidth}
+ PanelHeight={this.getPanelHeight}
+ ContainingCollectionView={undefined}
+ focus={this.focusDocument}
+ parentActive={this.props.active}
+ onActiveChanged={this.props.onActiveChanged} /> : null}
<input value={this.previewScript} onChange={this.onPreviewScriptChange}
style={{ position: 'absolute', bottom: '0px' }} />
</div>
}
</Measure>
- )
- let dividerDragger = this.splitPercentage == 0 ? (null) :
- <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />
+ );
+ let dividerDragger = this.splitPercentage === 0 ? (null) :
+ <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
//options button and menu
let optionsMenu = !this.props.active() ? (null) : (<Flyout
@@ -330,12 +334,11 @@ export class CollectionSchemaView extends CollectionViewBase {
<div id="schema-options-header"><h5><b>Options</b></h5></div>
<div id="options-flyout-div">
<h6 className="schema-options-subHeader">Preview Window</h6>
- <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.splitPercentage != 0} onChange={this.toggleExpander} /> Show Preview </div>
+ <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.splitPercentage !== 0} onChange={this.toggleExpander} /> Show Preview </div>
<h6 className="schema-options-subHeader" >Displayed Columns</h6>
<ul id="schema-col-checklist" >
- {Array.from(Object.keys(allKeys)).map(item => {
- return (<KeyToggle checked={allKeys[item]} key={item} keyId={item} toggle={this.toggleKey} />)
- })}
+ {Array.from(Object.keys(allKeys)).map(item =>
+ (<KeyToggle checked={allKeys[item]} key={item} keyId={item} toggle={this.toggleKey} />))}
</ul>
<input value={this.newKeyName} onChange={this.newKeyChange} />
<button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
@@ -377,6 +380,6 @@ export class CollectionSchemaView extends CollectionViewBase {
{optionsMenu}
</div>
</div >
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionSubView.tsx
index 7cf49e215..5cdea0568 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -4,45 +4,30 @@ import { ListField } from "../../../fields/ListField";
import React = require("react");
import { KeyStore } from "../../../fields/KeyStore";
import { FieldWaiting, Opt } from "../../../fields/Field";
-import { undoBatch } from "../../util/UndoManager";
+import { undoBatch, UndoManager } from "../../util/UndoManager";
import { DragManager } from "../../util/DragManager";
import { Documents, DocumentOptions } from "../../documents/Documents";
-import { Key } from "../../../fields/Key";
-import { Transform } from "../../util/Transform";
-import { CollectionView } from "./CollectionView";
import { RouteStore } from "../../../server/RouteStore";
import { TupleField } from "../../../fields/TupleField";
import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
import { NumberField } from "../../../fields/NumberField";
-import request = require("request");
import { ServerUtils } from "../../../server/ServerUtil";
import { Server } from "../../Server";
-import { CollectionDockingView } from "./CollectionDockingView";
-import { runReactions } from "mobx/lib/internal";
+import { FieldViewProps } from "../nodes/FieldView";
+import * as rp from 'request-promise';
-export interface CollectionViewProps {
- fieldKey: Key;
- Document: Document;
- ScreenToLocalTransform: () => Transform;
- isSelected: () => boolean;
- isTopMost: boolean;
- select: (ctrlPressed: boolean) => void;
- bindings: any;
- panelWidth: () => number;
- panelHeight: () => number;
- focus: (doc: Document) => void;
+export interface CollectionViewProps extends FieldViewProps {
+ addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
+ removeDocument: (document: Document) => boolean;
+ moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
}
export interface SubCollectionViewProps extends CollectionViewProps {
- active: () => boolean;
- addDocument: (doc: Document, allowDuplicates: boolean) => boolean;
- removeDocument: (doc: Document) => boolean;
- CollectionView: CollectionView;
}
export type CursorEntry = TupleField<[string, string], [number, number]>;
-export class CollectionViewBase extends React.Component<SubCollectionViewProps> {
+export class CollectionSubView extends React.Component<SubCollectionViewProps> {
private dropDisposer?: DragManager.DragDropDisposer;
protected createDropTarget = (ele: HTMLDivElement) => {
if (this.dropDisposer) {
@@ -73,8 +58,8 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
let entry = new TupleField<[string, string], [number, number]>([textInfo, position]);
cursors.push(entry);
}
- }))
- })
+ }));
+ });
}
}
@@ -87,31 +72,18 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
de.data.draggedDocuments.map((draggedDocument: Document, i: number) =>
draggedDocument.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocuments[i].SetNumber(key, f.Data) : null)));
}
- let added = de.data.droppedDocuments.reduce((added, d) => this.props.addDocument(d, false), true);
- if (added && de.data.removeDocument && !de.data.aliasOnDrop && !de.data.copyOnDrop) {
- de.data.removeDocument(this.props.CollectionView);
+ let added = false;
+ if (de.data.aliasOnDrop || de.data.copyOnDrop) {
+ added = de.data.droppedDocuments.reduce((added: boolean, d) => added || this.props.addDocument(d), false);
+ } else if (de.data.moveDocument) {
+ const move = de.data.moveDocument;
+ added = de.data.droppedDocuments.reduce((added: boolean, d) => added || move(d, this.props.Document, this.props.addDocument), false);
+ } else {
+ added = de.data.droppedDocuments.reduce((added: boolean, d) => added || this.props.addDocument(d), false);
}
e.stopPropagation();
return added;
}
- if (de.data instanceof DragManager.LinkDragData) {
- let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document;
- if (sourceDoc) runInAction(() => {
- let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
- if (srcTarg && srcTarg != FieldWaiting) {
- let linkDocs = srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]);
- linkDocs.map(linkDoc => {
- let targDoc = linkDoc.GetT(KeyStore.LinkedToDocs, Document);
- if (targDoc && targDoc != FieldWaiting) {
- let dropdoc = targDoc.MakeDelegate();
- de.data.droppedDocuments.push(dropdoc);
- this.props.addDocument(dropdoc, false);
- }
- })
- }
- })
- return true;
- }
return false;
}
@@ -143,7 +115,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
alias.SetNumber(KeyStore.Height, options.height || options.width || 300);
this.props.addDocument(alias, false);
}
- })
+ });
return undefined;
}
ctor = Documents.WebDocument;
@@ -152,20 +124,19 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
return ctor ? ctor(path, options) : undefined;
}
+ @undoBatch
@action
protected onDrop(e: React.DragEvent, options: DocumentOptions): void {
- let that = this;
-
let html = e.dataTransfer.getData("text/html");
let text = e.dataTransfer.getData("text/plain");
if (text && text.startsWith("<div")) {
return;
}
- e.stopPropagation()
- e.preventDefault()
+ e.stopPropagation();
+ e.preventDefault();
- if (html && html.indexOf("<img") != 0 && !html.startsWith("<a")) {
+ if (html && html.indexOf("<img") !== 0 && !html.startsWith("<a")) {
console.log("not good");
let htmlDoc = Documents.HtmlDocument(html, { ...options, width: 300, height: 300 });
htmlDoc.SetText(KeyStore.DocumentText, text);
@@ -173,57 +144,70 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
return;
}
+ let batch = UndoManager.StartBatch("collection view drop");
+ let promises: Promise<void>[] = [];
+ // tslint:disable-next-line:prefer-for-of
for (let i = 0; i < e.dataTransfer.items.length; i++) {
const upload = window.location.origin + RouteStore.upload;
let item = e.dataTransfer.items[i];
- if (item.kind === "string" && item.type.indexOf("uri") != -1) {
- e.dataTransfer.items[i].getAsString(action((s: string) => {
- request.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s), (err, res, body) => {
+ if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
+ let str: string;
+ let prom = new Promise<string>(res =>
+ e.dataTransfer.items[i].getAsString(res)).then(action((s: string) => {
+ str = s;
+ return rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s));
+ })).then(res => {
let type = res.headers["content-type"];
if (type) {
- let doc = this.getDocumentFromType(type, s, { ...options, width: 300, nativeWidth: 300 })
+ let doc = this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 });
if (doc) {
this.props.addDocument(doc, false);
}
}
});
- // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false)
- }))
+ promises.push(prom);
+ // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false)
}
- let type = item.type
- if (item.kind == "file") {
+ let type = item.type;
+ if (item.kind === "file") {
let file = item.getAsFile();
- let formData = new FormData()
+ let formData = new FormData();
if (file) {
- formData.append('file', file)
+ formData.append('file', file);
}
- fetch(upload, {
+ let prom = fetch(upload, {
method: 'POST',
body: formData
- }).then((res: Response) => {
- return res.json()
- }).then(json => {
+ }).then(async (res: Response) => {
+ const json = await res.json();
json.map((file: any) => {
- let path = window.location.origin + file
+ let path = window.location.origin + file;
runInAction(() => {
- let doc = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300 })
+ let doc = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300 });
- let docs = that.props.Document.GetT(KeyStore.Data, ListField);
- if (docs != FieldWaiting) {
+ let docs = this.props.Document.GetT(KeyStore.Data, ListField);
+ if (docs !== FieldWaiting) {
if (!docs) {
docs = new ListField<Document>();
- that.props.Document.Set(KeyStore.Data, docs)
+ this.props.Document.Set(KeyStore.Data, docs);
}
if (doc) {
docs.Data.push(doc);
}
}
- })
- })
- })
+ });
+ });
+ });
+ promises.push(prom);
}
}
+
+ if (promises.length) {
+ Promise.all(promises).catch(() => { }).then(() => batch.end());
+ } else {
+ batch.end();
+ }
}
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 0b12f11fd..659cff9fe 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -7,17 +7,20 @@ import { Document } from "../../../fields/Document";
import { FieldWaiting } from "../../../fields/Field";
import { KeyStore } from "../../../fields/KeyStore";
import { ListField } from "../../../fields/ListField";
-import { setupDrag } from "../../util/DragManager";
+import { setupDrag, DragManager } from "../../util/DragManager";
import { EditableView } from "../EditableView";
import "./CollectionTreeView.scss";
-import { CollectionView, COLLECTION_BORDER_WIDTH } from "./CollectionView";
-import { CollectionViewBase } from "./CollectionViewBase";
-import React = require("react")
+import { CollectionView } from "./CollectionView";
+import { CollectionSubView } from "./CollectionSubView";
+import React = require("react");
+import { COLLECTION_BORDER_WIDTH } from './CollectionBaseView';
+import { props } from 'bluebird';
export interface TreeViewProps {
document: Document;
deleteDoc: (doc: Document) => void;
+ moveDocument: DragManager.MoveFunction;
copyOnDrag: boolean;
}
@@ -49,6 +52,16 @@ class TreeView extends React.Component<TreeViewProps> {
}
}
+ @action
+ move: DragManager.MoveFunction = (document, target, addDoc) => {
+ if (this.props.document === target) {
+ return true;
+ }
+ //TODO This should check if it was removed
+ this.remove(document);
+ return addDoc(document);
+ }
+
renderBullet(type: BulletType) {
let onClicked = action(() => this._collapsed = !this._collapsed);
let bullet: IconProp | undefined = undefined;
@@ -56,7 +69,7 @@ class TreeView extends React.Component<TreeViewProps> {
case BulletType.Collapsed: bullet = "caret-right"; break;
case BulletType.Collapsible: bullet = "caret-down"; break;
}
- return <div className="bullet" onClick={onClicked}>{bullet ? <FontAwesomeIcon icon={bullet} /> : ""} </div>
+ return <div className="bullet" onClick={onClicked}>{bullet ? <FontAwesomeIcon icon={bullet} /> : ""} </div>;
}
/**
@@ -64,7 +77,7 @@ class TreeView extends React.Component<TreeViewProps> {
*/
renderTitle() {
let reference = React.createRef<HTMLDivElement>();
- let onItemDown = setupDrag(reference, () => this.props.document, (containingCollection: CollectionView) => this.props.deleteDoc(this.props.document), this.props.copyOnDrag);
+ let onItemDown = setupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.copyOnDrag);
let editableView = (titleString: string) =>
(<EditableView
display={"inline"}
@@ -80,7 +93,7 @@ class TreeView extends React.Component<TreeViewProps> {
<div className="docContainer" ref={reference} onPointerDown={onItemDown}>
{editableView(this.props.document.Title)}
<div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>
- </div >)
+ </div >);
}
render() {
@@ -91,8 +104,8 @@ class TreeView extends React.Component<TreeViewProps> {
if (!this._collapsed) {
bulletType = BulletType.Collapsible;
childElements = <ul>
- {children.Data.map(value => <TreeView key={value.Id} document={value} deleteDoc={this.remove} copyOnDrag={this.props.copyOnDrag} />)}
- </ul>
+ {children.Data.map(value => <TreeView key={value.Id} document={value} deleteDoc={this.remove} moveDocument={this.move} copyOnDrag={this.props.copyOnDrag} />)}
+ </ul >;
}
else bulletType = BulletType.Collapsed;
}
@@ -102,12 +115,12 @@ class TreeView extends React.Component<TreeViewProps> {
{this.renderTitle()}
{childElements ? childElements : (null)}
</li>
- </div>
+ </div>;
}
}
@observer
-export class CollectionTreeView extends CollectionViewBase {
+export class CollectionTreeView extends CollectionSubView {
@action
remove = (document: Document) => {
@@ -122,8 +135,8 @@ export class CollectionTreeView extends CollectionViewBase {
let copyOnDrag = this.props.Document.GetBoolean(KeyStore.CopyDraggedItems, false);
let childrenElement = !children || children === FieldWaiting ? (null) :
(children.Data.map(value =>
- <TreeView document={value} key={value.Id} deleteDoc={this.remove} copyOnDrag={copyOnDrag} />)
- )
+ <TreeView document={value} key={value.Id} deleteDoc={this.remove} moveDocument={this.props.moveDocument} copyOnDrag={copyOnDrag} />)
+ );
return (
<div id="body" className="collectionTreeView-dropTarget" onWheel={(e: React.WheelEvent) => e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}>
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 470a853e3..b02983a2e 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -1,17 +1,16 @@
-import { action, computed, observable, trace } from "mobx";
+import { action, observable, trace } from "mobx";
import { observer } from "mobx-react";
-import { Document } from "../../../fields/Document";
import { KeyStore } from "../../../fields/KeyStore";
import { ContextMenu } from "../ContextMenu";
-import { CollectionView, CollectionViewType } from "./CollectionView";
-import { CollectionViewProps } from "./CollectionViewBase";
+import { CollectionViewType, CollectionBaseView, CollectionRenderProps } from "./CollectionBaseView";
import React = require("react");
-import { FieldId } from "../../../fields/Field";
-import "./CollectionVideoView.scss"
+import "./CollectionVideoView.scss";
+import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
+import { FieldView, FieldViewProps } from "../nodes/FieldView";
@observer
-export class CollectionVideoView extends React.Component<CollectionViewProps> {
+export class CollectionVideoView extends React.Component<FieldViewProps> {
private _intervalTimer: any = undefined;
private _player: HTMLVideoElement | undefined = undefined;
@@ -19,12 +18,10 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
@observable _isPlaying: boolean = false;
public static LayoutString(fieldKey: string = "DataKey") {
- return `<${CollectionVideoView.name} Document={Document}
- ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} panelWidth={PanelWidth} panelHeight={PanelHeight} isSelected={isSelected} select={select} bindings={bindings}
- isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`;
+ return FieldView.LayoutString(CollectionVideoView, fieldKey);
}
private get uIButtons() {
- let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().transformDirection(1, 1)[0]);
+ let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale);
return ([
<div className="collectionVideoView-time" key="time" onPointerDown={this.onResetDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
<span>{"" + Math.round(this._currentTimecode)}</span>
@@ -42,7 +39,7 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
@action
mainCont = (ele: HTMLDivElement | null) => {
if (ele) {
- this._player = ele!.getElementsByTagName("video")[0];
+ this._player = ele.getElementsByTagName("video")[0];
if (this.props.Document.GetNumber(KeyStore.CurPage, -1) >= 0) {
this._currentTimecode = this.props.Document.GetNumber(KeyStore.CurPage, -1);
}
@@ -60,7 +57,7 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
@action
updateTimecode = () => {
if (this._player) {
- if ((this._player as any).AHackBecauseSomethingResetsTheVideoToZero != -1) {
+ if ((this._player as any).AHackBecauseSomethingResetsTheVideoToZero !== -1) {
this._player.currentTime = (this._player as any).AHackBecauseSomethingResetsTheVideoToZero;
(this._player as any).AHackBecauseSomethingResetsTheVideoToZero = -1;
} else {
@@ -101,30 +98,27 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
}
- // "inherited" CollectionView API starts here...
-
- @observable
- public SelectedDocs: FieldId[] = []
- public active: () => boolean = () => CollectionView.Active(this);
-
- addDocument = (doc: Document, allowDuplicates: boolean): boolean => { return CollectionView.AddDocument(this.props, doc, allowDuplicates); }
- removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); }
-
- specificContextMenu = (e: React.MouseEvent): void => {
- if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+ onContextMenu = (e: React.MouseEvent): void => {
+ if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
ContextMenu.Instance.addItem({ description: "VideoOptions", event: () => { } });
}
}
- get collectionViewType(): CollectionViewType { return CollectionViewType.Freeform; }
- get subView(): any { return CollectionView.SubView(this); }
-
+ private subView = (_type: CollectionViewType, renderProps: CollectionRenderProps) => {
+ let props = { ...this.props, ...renderProps };
+ return (
+ <>
+ <CollectionFreeFormView {...props} />
+ {this.props.isSelected() ? this.uIButtons : (null)}
+ </>
+ );
+ }
render() {
trace();
- return (<div className="collectionVideoView-cont" ref={this.mainCont} onContextMenu={this.specificContextMenu}>
- {this.subView}
- {this.props.isSelected() ? this.uIButtons : (null)}
- </div>)
+ return (
+ <CollectionBaseView {...this.props} className="collectionVideoView-cont" contentRef={this.mainCont} onContextMenu={this.onContextMenu}>
+ {this.subView}
+ </CollectionBaseView>);
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 014aa1d8f..8abd0a02d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,159 +1,46 @@
-import { action, computed, observable } from "mobx";
-import { observer } from "mobx-react";
-import { Document } from "../../../fields/Document";
-import { ListField } from "../../../fields/ListField";
-import { SelectionManager } from "../../util/SelectionManager";
-import { ContextMenu } from "../ContextMenu";
-import React = require("react");
-import { KeyStore } from "../../../fields/KeyStore";
-import { NumberField } from "../../../fields/NumberField";
-import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
-import { CollectionDockingView } from "./CollectionDockingView";
-import { CollectionSchemaView } from "./CollectionSchemaView";
-import { CollectionViewProps } from "./CollectionViewBase";
-import { CollectionTreeView } from "./CollectionTreeView";
-import { Field, FieldId, FieldWaiting } from "../../../fields/Field";
-import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
-
-export enum CollectionViewType {
- Invalid,
- Freeform,
- Schema,
- Docking,
- Tree
-}
-
-export const COLLECTION_BORDER_WIDTH = 1;
+import * as React from 'react';
+import { FieldViewProps, FieldView } from '../nodes/FieldView';
+import { CollectionBaseView, CollectionViewType, CollectionRenderProps } from './CollectionBaseView';
+import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
+import { CollectionSchemaView } from './CollectionSchemaView';
+import { CollectionDockingView } from './CollectionDockingView';
+import { CollectionTreeView } from './CollectionTreeView';
+import { ContextMenu } from '../ContextMenu';
+import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
+import { KeyStore } from '../../../fields/KeyStore';
+import { observer } from 'mobx-react';
+import { undoBatch } from '../../util/UndoManager';
@observer
-export class CollectionView extends React.Component<CollectionViewProps> {
-
- public static LayoutString(fieldKey: string = "DataKey") {
- return `<${CollectionView.name} Document={Document}
- ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} panelWidth={PanelWidth} panelHeight={PanelHeight} isSelected={isSelected} select={select} bindings={bindings}
- isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`;
- }
-
- @observable
- public SelectedDocs: FieldId[] = [];
- public active: () => boolean = () => CollectionView.Active(this);
- addDocument = (doc: Document, allowDuplicates: boolean): boolean => { return CollectionView.AddDocument(this.props, doc, allowDuplicates); }
- removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); }
- get subView() { return CollectionView.SubView(this); }
-
- public static Active(self: CollectionView): boolean {
- var isSelected = self.props.isSelected();
- var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == self);
- var topMost = self.props.isTopMost;
- return isSelected || childSelected || topMost;
- }
-
- static createsCycle(documentToAdd: Document, containerDocument: Document): boolean {
- let data = documentToAdd.GetList<Document>(KeyStore.Data, []);
- for (let i = 0; i < data.length; i++) {
- if (CollectionView.createsCycle(data[i], containerDocument))
- return true;
- }
- let annots = documentToAdd.GetList<Document>(KeyStore.Annotations, []);
- for (let i = 0; i < annots.length; i++) {
- if (CollectionView.createsCycle(annots[i], containerDocument))
- return true;
- }
- for (let containerProto: any = containerDocument; containerProto && containerProto != FieldWaiting; containerProto = containerProto.GetPrototype()) {
- if (containerProto.Id == documentToAdd.Id)
- return true;
- }
- return false;
- }
-
- @action
- public static AddDocument(props: CollectionViewProps, doc: Document, allowDuplicates: boolean): boolean {
- var curPage = props.Document.GetNumber(KeyStore.CurPage, -1);
- doc.SetOnPrototype(KeyStore.Page, new NumberField(curPage));
- if (curPage >= 0) {
- doc.SetOnPrototype(KeyStore.AnnotationOn, props.Document);
- }
- if (props.Document.Get(props.fieldKey) instanceof Field) {
- //TODO This won't create the field if it doesn't already exist
- const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
- if (!CollectionView.createsCycle(doc, props.Document)) {
- if (!value.some(v => v.Id == doc.Id) || allowDuplicates)
- value.push(doc);
- }
- else
- return false;
- } else {
- let proto = props.Document.GetPrototype();
- if (!proto || proto == FieldWaiting || !CollectionView.createsCycle(proto, doc)) {
- props.Document.SetOnPrototype(props.fieldKey, new ListField([doc]));
- }
- else
- return false;
- }
- return true;
- }
-
- @action
- public static RemoveDocument(props: CollectionViewProps, doc: Document): boolean {
- //TODO This won't create the field if it doesn't already exist
- const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
- let index = -1;
- for (let i = 0; i < value.length; i++) {
- if (value[i].Id == doc.Id) {
- index = i;
- break;
- }
- }
- doc.GetTAsync(KeyStore.AnnotationOn, Document).then((annotationOn) => {
- if (annotationOn == props.Document) {
- doc.Set(KeyStore.AnnotationOn, undefined, true);
- }
- })
-
- if (index !== -1) {
- value.splice(index, 1)
-
- //SelectionManager.DeselectAll()
- ContextMenu.Instance.clearItems()
- return true;
- }
- return false
- }
-
- get collectionViewType(): CollectionViewType {
- let Document = this.props.Document;
- let viewField = Document.GetT(KeyStore.ViewType, NumberField);
- if (viewField === FieldWaiting) {
- return CollectionViewType.Invalid;
- } else if (viewField) {
- return viewField.Data;
- } else {
- return CollectionViewType.Freeform;
- }
- }
-
- specificContextMenu = (e: React.MouseEvent): void => {
- if (!e.isPropagationStopped() && this.props.Document.Id != CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
- 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: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) })
+export class CollectionView extends React.Component<FieldViewProps> {
+ public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(CollectionView, fieldStr); }
+
+ private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
+ let props = { ...this.props, ...renderProps };
+ switch (type) {
+ case CollectionViewType.Schema: return (<CollectionSchemaView {...props} />);
+ case CollectionViewType.Docking: return (<CollectionDockingView {...props} />);
+ case CollectionViewType.Tree: return (<CollectionTreeView {...props} />);
+ case CollectionViewType.Freeform:
+ default:
+ return (<CollectionFreeFormView {...props} />);
}
+ return (null);
}
- public static SubView(self: CollectionView) {
- let subProps = { ...self.props, addDocument: self.addDocument, removeDocument: self.removeDocument, active: self.active, CollectionView: self }
- switch (self.collectionViewType) {
- case CollectionViewType.Freeform: return (<CollectionFreeFormView {...subProps} />)
- case CollectionViewType.Schema: return (<CollectionSchemaView {...subProps} />)
- case CollectionViewType.Docking: return (<CollectionDockingView {...subProps} />)
- case CollectionViewType.Tree: return (<CollectionTreeView {...subProps} />)
+ onContextMenu = (e: React.MouseEvent): void => {
+ if (!e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+ ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)) });
+ ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema)) });
+ ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree)) });
}
- return (null);
}
render() {
- return (<div className="collectionView-cont" onContextMenu={this.specificContextMenu}>
- {this.subView}
- </div>)
+ return (
+ <CollectionBaseView {...this.props} onContextMenu={this.onContextMenu}>
+ {this.SubView}
+ </CollectionBaseView>
+ );
}
-}
+} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 3dfd74ec8..081b3eb6c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -32,6 +32,6 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
style={{ strokeWidth: `${l.length * 5}` }}
x1={`${x1}`} y1={`${y1}`}
x2={`${x2}`} y2={`${y2}`} />
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index d4809ac1c..cf058090d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,4 +1,4 @@
-import { computed, reaction, runInAction, trace } from "mobx";
+import { computed, reaction } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../../../fields/Document";
import { FieldWaiting } from "../../../../fields/Field";
@@ -7,71 +7,73 @@ import { ListField } from "../../../../fields/ListField";
import { Utils } from "../../../../Utils";
import { DocumentManager } from "../../../util/DocumentManager";
import { DocumentView } from "../../nodes/DocumentView";
-import { CollectionViewProps } from "../CollectionViewBase";
+import { CollectionViewProps } from "../CollectionSubView";
import "./CollectionFreeFormLinksView.scss";
import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView";
import React = require("react");
-import v5 = require("uuid/v5");
-import { find } from "async";
@observer
export class CollectionFreeFormLinksView extends React.Component<CollectionViewProps> {
+ HackToAvoidReactionFiringUnnecessarily?: Document = undefined;
componentDidMount() {
- reaction(() => {
- return DocumentManager.Instance.getAllDocumentViews(this.props.Document).map(dv => dv.props.Document.GetNumber(KeyStore.X, 0))
- }, () => {
- let views = DocumentManager.Instance.getAllDocumentViews(this.props.Document);
- for (let i = 0; i < views.length; i++) {
- for (let j = 0; j < views.length; j++) {
- let srcDoc = views[j].props.Document;
- let dstDoc = views[i].props.Document;
- let x1 = srcDoc.GetNumber(KeyStore.X, 0);
- let x1w = srcDoc.GetNumber(KeyStore.Width, -1);
- let x2 = dstDoc.GetNumber(KeyStore.X, 0);
- let x2w = dstDoc.GetNumber(KeyStore.Width, -1);
- if (x1w < 0 || x2w < 0 || i == j)
- continue;
- let dstTarg = dstDoc;
- let srcTarg = srcDoc;
- let findBrush = (field: ListField<Document>) => field.Data.findIndex(brush => {
- let bdocs = brush ? brush.GetList(KeyStore.BrushingDocs, [] as Document[]) : [];
- return (bdocs.length && ((bdocs[0] == dstTarg && bdocs[1] == srcTarg)) ? true : false)
- });
- let brushAction = (field: ListField<Document>) => {
- let found = findBrush(field);
- if (found != -1) {
- console.log("REMOVE BRUSH " + srcTarg.Title + " " + dstTarg.Title);
- field.Data.splice(found, 1);
+ this.HackToAvoidReactionFiringUnnecessarily = this.props.Document;
+ reaction(() =>
+ DocumentManager.Instance.getAllDocumentViews(this.HackToAvoidReactionFiringUnnecessarily!).
+ map(dv => dv.props.Document.GetNumber(KeyStore.X, 0)),
+ () => {
+ let views = DocumentManager.Instance.getAllDocumentViews(this.props.Document);
+ for (let i = 0; i < views.length; i++) {
+ for (let j = 0; j < views.length; j++) {
+ let srcDoc = views[j].props.Document;
+ let dstDoc = views[i].props.Document;
+ let x1 = srcDoc.GetNumber(KeyStore.X, 0);
+ let x1w = srcDoc.GetNumber(KeyStore.Width, -1);
+ let x2 = dstDoc.GetNumber(KeyStore.X, 0);
+ let x2w = dstDoc.GetNumber(KeyStore.Width, -1);
+ if (x1w < 0 || x2w < 0 || i === j) {
+ continue;
}
- };
- if (Math.abs(x1 + x1w - x2) < 20) {
- let linkDoc: Document = new Document();
- linkDoc.SetText(KeyStore.Title, "Histogram Brush");
- linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
- linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
-
- brushAction = brushAction = (field: ListField<Document>) => {
- if (findBrush(field) == -1) {
- console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title);
- (findBrush(field) == -1) && field.Data.push(linkDoc);
+ let dstTarg = dstDoc;
+ let srcTarg = srcDoc;
+ let findBrush = (field: ListField<Document>) => field.Data.findIndex(brush => {
+ let bdocs = brush ? brush.GetList(KeyStore.BrushingDocs, [] as Document[]) : [];
+ return (bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false);
+ });
+ let brushAction = (field: ListField<Document>) => {
+ let found = findBrush(field);
+ if (found !== -1) {
+ console.log("REMOVE BRUSH " + srcTarg.Title + " " + dstTarg.Title);
+ field.Data.splice(found, 1);
}
};
- }
- dstTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
- srcTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
+ if (Math.abs(x1 + x1w - x2) < 20) {
+ let linkDoc: Document = new Document();
+ linkDoc.SetText(KeyStore.Title, "Histogram Brush");
+ linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
+ linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
+
+ brushAction = brushAction = (field: ListField<Document>) => {
+ if (findBrush(field) === -1) {
+ console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title);
+ (findBrush(field) === -1) && field.Data.push(linkDoc);
+ }
+ };
+ }
+ dstTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
+ srcTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
+ }
}
- }
- })
+ });
}
documentAnchors(view: DocumentView) {
let equalViews = [view];
let containerDoc = view.props.Document.GetT(KeyStore.AnnotationOn, Document);
- if (containerDoc && containerDoc != FieldWaiting && containerDoc instanceof Document) {
- equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.GetPrototype() as Document)
+ if (containerDoc && containerDoc instanceof Document) {
+ equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.GetPrototype()!);
}
- return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document == this.props.Document);
+ return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document);
}
@computed
@@ -83,17 +85,18 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document })));
possiblePairs.map(possiblePair => {
if (!drawnPairs.reduce((found, drawnPair) => {
- let match = (possiblePair.a == drawnPair.a && possiblePair.b == drawnPair.b);
+ let match = (possiblePair.a === drawnPair.a && possiblePair.b === drawnPair.b);
if (match) {
- if (!drawnPair.l.reduce((found, link) => found || link.Id == connection.l.Id, false))
+ if (!drawnPair.l.reduce((found, link) => found || link.Id === connection.l.Id, false)) {
drawnPair.l.push(connection.l);
+ }
}
return match || found;
}, false)) {
- drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] as Document[] });
+ drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] });
}
- })
- return drawnPairs
+ });
+ return drawnPairs;
}, [] as { a: Document, b: Document, l: Document[] }[]);
return connections.map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index 19382e66f..fc832264d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -1,21 +1,8 @@
-import { action, computed, observable } from "mobx";
+import { computed } from "mobx";
import { observer } from "mobx-react";
-import { Document } from "../../../../fields/Document";
-import { FieldWaiting } from "../../../../fields/Field";
import { KeyStore } from "../../../../fields/KeyStore";
-import { TextField } from "../../../../fields/TextField";
-import { DragManager } from "../../../util/DragManager";
-import { Transform } from "../../../util/Transform";
-import { undoBatch } from "../../../util/UndoManager";
-import { InkingCanvas } from "../../InkingCanvas";
-import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
-import { DocumentContentsView } from "../../nodes/DocumentContentsView";
-import { DocumentViewProps } from "../../nodes/DocumentView";
-import { COLLECTION_BORDER_WIDTH } from "../CollectionView";
-import { CollectionViewBase, CollectionViewProps, CursorEntry } from "../CollectionViewBase";
-import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView";
+import { CollectionViewProps, CursorEntry } from "../CollectionSubView";
import "./CollectionFreeFormView.scss";
-import { MarqueeView } from "./MarqueeView";
import React = require("react");
import v5 = require("uuid/v5");
import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
@@ -70,7 +57,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
let id = entry.Data[0][0];
let email = entry.Data[0][1];
let point = entry.Data[1];
- this.drawCrosshairs("#" + v5(id, v5.URL).substring(0, 6).toUpperCase() + "22")
+ this.drawCrosshairs("#" + v5(id, v5.URL).substring(0, 6).toUpperCase() + "22");
return (
<div
key={id}
@@ -82,7 +69,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
}}
>
<canvas
- ref={(el) => { if (el) this.crosshairs = el }}
+ ref={(el) => { if (el) this.crosshairs = el; }}
width={20}
height={20}
style={{
@@ -106,7 +93,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
</div>
);
}
- })
+ });
}
render() {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 79d520069..81f2146e4 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -1,5 +1,11 @@
@import "../../global_variables";
-
+.collectionfreeformview-measure {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
.collectionfreeformview {
position: absolute;
top: 0;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f3a83f5a0..a77a28aa7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable, trace } from "mobx";
+import { action, computed, observable, trace, ObservableSet, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../../../fields/Document";
import { FieldWaiting } from "../../../../fields/Field";
@@ -11,8 +11,8 @@ import { InkingCanvas } from "../../InkingCanvas";
import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
import { DocumentContentsView } from "../../nodes/DocumentContentsView";
import { DocumentViewProps } from "../../nodes/DocumentView";
-import { COLLECTION_BORDER_WIDTH } from "../CollectionView";
-import { CollectionViewBase } from "../CollectionViewBase";
+import { COLLECTION_BORDER_WIDTH } from "../CollectionBaseView";
+import { CollectionSubView } from "../CollectionSubView";
import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView";
import "./CollectionFreeFormView.scss";
import { MarqueeView } from "./MarqueeView";
@@ -21,10 +21,14 @@ import v5 = require("uuid/v5");
import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
import { PreviewCursor } from "./PreviewCursor";
import { Timeline } from "../../nodes/Timeline"
+import { DocumentManager } from "../../../util/DocumentManager";
+import { SelectionManager } from "../../../util/SelectionManager";
import { NumberField } from "../../../../fields/NumberField";
+import { Main } from "../../Main";
+import Measure from "react-measure";
@observer
-export class CollectionFreeFormView extends CollectionViewBase {
+export class CollectionFreeFormView extends CollectionSubView {
public _canvasRef = React.createRef<HTMLDivElement>();
private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type)
@@ -41,15 +45,20 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
public selectDocuments = (docs: Document[]) => {
- this.props.CollectionView.SelectedDocs.length = 0;
- docs.map(d => this.props.CollectionView.SelectedDocs.push(d.Id));
+ SelectionManager.DeselectAll;
+ docs.map(doc => {
+ const dv = DocumentManager.Instance.getDocumentView(doc);
+ if (dv) {
+ SelectionManager.SelectDoc(dv, true);
+ }
+ });
}
public getActiveDocuments = () => {
var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).reduce((active, doc) => {
var page = doc.GetNumber(KeyStore.Page, -1);
- if (page == curPage || page == -1) {
+ if (page === curPage || page === -1) {
active.push(doc);
}
return active;
@@ -60,46 +69,50 @@ export class CollectionFreeFormView extends CollectionViewBase {
@observable public DownY: number = 0;
@observable private _lastX: number = 0;
@observable private _lastY: number = 0;
+ @observable private _pwidth: number = 0;
+ @observable private _pheight: number = 0;
- @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0) }
- @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0) }
+ @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0); }
+ @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0); }
@computed get scale(): number { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
@computed get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's?
@computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
@computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
@computed get zoomScaling() { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
- @computed get centeringShiftX() { return !this.props.Document.GetNumber(KeyStore.NativeWidth, 0) ? this.props.panelWidth() / 2 : 0; } // shift so pan position is at center of window for non-overlay collections
- @computed get centeringShiftY() { return !this.props.Document.GetNumber(KeyStore.NativeHeight, 0) ? this.props.panelHeight() / 2 : 0; }// shift so pan position is at center of window for non-overlay collections
+ @computed get centeringShiftX() { return !this.props.Document.GetNumber(KeyStore.NativeWidth, 0) ? this._pwidth / 2 : 0; } // shift so pan position is at center of window for non-overlay collections
+ @computed get centeringShiftY() { return !this.props.Document.GetNumber(KeyStore.NativeHeight, 0) ? this._pheight / 2 : 0; }// shift so pan position is at center of window for non-overlay collections
@undoBatch
@action
drop = (e: Event, de: DragManager.DropEvent) => {
if (super.drop(e, de)) {
- let droppedDocs = de.data.droppedDocuments as Document[];
- let xoff = de.data.xOffset as number || 0;
- let yoff = de.data.yOffset as number || 0;
- if (droppedDocs && droppedDocs.length) {
- let screenX = de.x - xoff;
- let screenY = de.y - yoff;
- const [x, y] = this.getTransform().transformPoint(screenX, screenY);
- let dragDoc = de.data.droppedDocuments[0];
- let dragX = dragDoc.GetNumber(KeyStore.X, 0);
- let dragY = dragDoc.GetNumber(KeyStore.Y, 0);
- droppedDocs.map(async d => {
- let docX = d.GetNumber(KeyStore.X, 0);
- let docY = d.GetNumber(KeyStore.Y, 0);
- d.SetNumber(KeyStore.X, x + (docX - dragX));
- d.SetNumber(KeyStore.Y, y + (docY - dragY));
- let docW = await d.GetTAsync(KeyStore.Width, NumberField);
- let docH = await d.GetTAsync(KeyStore.Height, NumberField);
- if (!docW) {
- d.SetNumber(KeyStore.Width, 300);
- }
- if (!docH) {
- d.SetNumber(KeyStore.Height, 300);
- }
- this.bringToFront(d);
- })
+ if (de.data instanceof DragManager.DocumentDragData) {
+ let droppedDocs = de.data.droppedDocuments;
+ let xoff = de.data.xOffset as number || 0;
+ let yoff = de.data.yOffset as number || 0;
+ if (droppedDocs.length) {
+ let screenX = de.x - xoff;
+ let screenY = de.y - yoff;
+ const [x, y] = this.getTransform().transformPoint(screenX, screenY);
+ let dragDoc = droppedDocs[0];
+ let dragX = dragDoc.GetNumber(KeyStore.X, 0);
+ let dragY = dragDoc.GetNumber(KeyStore.Y, 0);
+ droppedDocs.map(async d => {
+ let docX = d.GetNumber(KeyStore.X, 0);
+ let docY = d.GetNumber(KeyStore.Y, 0);
+ d.SetNumber(KeyStore.X, x + (docX - dragX));
+ d.SetNumber(KeyStore.Y, y + (docY - dragY));
+ let docW = await d.GetTAsync(KeyStore.Width, NumberField);
+ let docH = await d.GetTAsync(KeyStore.Height, NumberField);
+ if (!docW) {
+ d.SetNumber(KeyStore.Width, 300);
+ }
+ if (!docH) {
+ d.SetNumber(KeyStore.Height, 300);
+ }
+ this.bringToFront(d);
+ });
+ }
}
return true;
}
@@ -115,15 +128,16 @@ export class CollectionFreeFormView extends CollectionViewBase {
@action
onPointerDown = (e: React.PointerEvent): void => {
- if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling != 1)) || e.button == 0) && this.props.active()) {
+ if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling !== 1)) || e.button === 0) && this.props.active()) {
document.removeEventListener("pointermove", this.onPointerMove);
document.addEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
document.addEventListener("pointerup", this.onPointerUp);
this._lastX = this.DownX = e.pageX;
this._lastY = this.DownY = e.pageY;
- if (this.props.isSelected())
+ if (this.props.isSelected()) {
e.stopPropagation();
+ }
}
}
@@ -137,7 +151,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
@action
onPointerMove = (e: PointerEvent): void => {
if (!e.cancelBubble && this.props.active()) {
- if ((!this.isAnnotationOverlay || this.zoomScaling != 1) && !e.shiftKey) {
+ if ((!this.isAnnotationOverlay || this.zoomScaling !== 1) && !e.shiftKey) {
let x = this.props.Document.GetNumber(KeyStore.PanX, 0);
let y = this.props.Document.GetNumber(KeyStore.PanY, 0);
let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
@@ -166,17 +180,18 @@ export class CollectionFreeFormView extends CollectionViewBase {
e.stopPropagation();
e.preventDefault();
} else {
- // if (modes[e.deltaMode] == 'pixels') coefficient = 50;
- // else if (modes[e.deltaMode] == 'lines') coefficient = 1000; // This should correspond to line-height??
+ // if (modes[e.deltaMode] === 'pixels') coefficient = 50;
+ // else if (modes[e.deltaMode] === 'lines') coefficient = 1000; // This should correspond to line-height??
let transform = this.getTransform();
let deltaScale = (1 - (e.deltaY / coefficient));
- if (deltaScale * this.zoomScaling < 1 && this.isAnnotationOverlay)
+ if (deltaScale * this.zoomScaling < 1 && this.isAnnotationOverlay) {
deltaScale = 1 / this.zoomScaling;
+ }
let [x, y] = transform.transformPoint(e.clientX, e.clientY);
- let localTransform = this.getLocalTransform()
- localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y)
+ let localTransform = this.getLocalTransform();
+ localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y);
// console.log(localTransform)
this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale);
@@ -186,6 +201,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
@action
private SetPan(panX: number, panY: number) {
+ Main.Instance.SetTextDoc(undefined, undefined);
var x1 = this.getLocalTransform().inverse().Scale;
const newPanX = Math.min((1 - 1 / x1) * this.nativeWidth, Math.max(0, panX));
const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY));
@@ -216,7 +232,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0);
}).map((doc, index) => {
- doc.SetNumber(KeyStore.ZIndex, index + 1)
+ doc.SetNumber(KeyStore.ZIndex, index + 1);
});
}
@@ -243,17 +259,20 @@ export class CollectionFreeFormView extends CollectionViewBase {
getDocumentViewProps(document: Document): DocumentViewProps {
return {
Document: document,
- AddDocument: this.props.addDocument,
- RemoveDocument: this.props.removeDocument,
+ addDocument: this.props.addDocument,
+ removeDocument: this.props.removeDocument,
+ moveDocument: this.props.moveDocument,
ScreenToLocalTransform: this.getTransform,
isTopMost: false,
- SelectOnLoad: document.Id == this._selectOnLoaded,
+ selectOnLoad: document.Id === this._selectOnLoaded,
PanelWidth: document.Width,
PanelHeight: document.Height,
ContentScaling: this.noScaling,
- ContainingCollectionView: this.props.CollectionView,
- focus: this.focusDocument
- }
+ ContainingCollectionView: undefined,
+ focus: this.focusDocument,
+ parentActive: this.props.active,
+ onActiveChanged: this.props.active,
+ };
}
@computed
@@ -261,10 +280,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => {
var page = doc.GetNumber(KeyStore.Page, -1);
- if (page == curPage || page == -1)
+ if (page === curPage || page === -1) {
prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />);
+ }
return prev;
- }, [] as JSX.Element[])
+ }, [] as JSX.Element[]);
}
@computed
@@ -280,9 +300,9 @@ export class CollectionFreeFormView extends CollectionViewBase {
layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={() => false} select={() => { }} />);
}
- getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform())
- getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH)
- getLocalTransform = (): Transform => Transform.Identity.scale(1 / this.scale).translate(this.panX, this.panY);
+ getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
+ getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH);
+ getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.scale).translate(this.panX, this.panY);
noScaling = () => 1;
childViews = () => this.views;
@@ -293,31 +313,35 @@ export class CollectionFreeFormView extends CollectionViewBase {
const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0);
return (
- <div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`}
- onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))}
- onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel}
- style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}>
- <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
- addDocument={this.addDocument} removeDocument={this.props.removeDocument}
- getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
- <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox}
- getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} >
- <div className="collectionfreeformview" ref={this._canvasRef}
- style={{ transform: `translate(${dx}px, ${dy}px) scale(${this.zoomScaling}, ${this.zoomScaling}) translate(${panx}px, ${pany}px)` }}>
- {this.backgroundView}
- <CollectionFreeFormLinksView {...this.props}>
- <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
- {this.childViews}
- </InkingCanvas>
- </CollectionFreeFormLinksView>
- <CollectionFreeFormRemoteCursors {...this.props} />
+ <Measure onResize={(r: any) => runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height })}>
+ {({ measureRef }) => (
+ <div className={`collectionfreeformview-measure`} ref={measureRef}>
+ <div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`}
+ onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))}
+ onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel}
+ style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}>
+ <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
+ addDocument={this.addDocument} removeDocument={this.props.removeDocument}
+ getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
+ <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox}
+ getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} >
+ <div className="collectionfreeformview" ref={this._canvasRef}
+ style={{ transform: `translate(${dx}px, ${dy}px) scale(${this.zoomScaling}, ${this.zoomScaling}) translate(${panx}px, ${pany}px)` }}>
+ {this.backgroundView}
+ <CollectionFreeFormLinksView {...this.props}>
+ <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
+ {this.childViews}
+ </InkingCanvas>
+ </CollectionFreeFormLinksView>
+ <CollectionFreeFormRemoteCursors {...this.props} />
+ </div>
+ {this.overlayView}
+ </PreviewCursor>
+ <Timeline />
+ </MarqueeView>
</div>
- {this.overlayView}
- </PreviewCursor>
- <Timeline />
- </MarqueeView>
-
- </div>
+ </div>)}
+ </Measure>
);
}
} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index df150a045..1e6faafb3 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -37,7 +37,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
@action
cleanupInteractions = (all: boolean = false) => {
if (all) {
- document.removeEventListener("pointermove", this.onPointerMove, true)
+ document.removeEventListener("pointermove", this.onPointerMove, true);
document.removeEventListener("pointerup", this.onPointerUp, true);
} else {
this._used = true;
@@ -48,11 +48,11 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
@action
onPointerDown = (e: React.PointerEvent): void => {
- if (e.buttons == 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) {
+ if (e.buttons === 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) {
this._downX = this._lastX = e.pageX;
this._downY = this._lastY = e.pageY;
this._used = false;
- document.addEventListener("pointermove", this.onPointerMove, true)
+ document.addEventListener("pointermove", this.onPointerMove, true);
document.addEventListener("pointerup", this.onPointerUp, true);
document.addEventListener("keydown", this.marqueeCommand, true);
}
@@ -63,7 +63,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
this._lastX = e.pageX;
this._lastY = e.pageY;
if (!e.cancelBubble) {
- if (!this._used && e.buttons == 1 && !e.altKey && !e.metaKey &&
+ if (!this._used && e.buttons === 1 && !e.altKey && !e.metaKey &&
(Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) {
this._visible = true;
}
@@ -94,20 +94,20 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
let top = this._downY < this._lastY ? this._downY : this._lastY;
let topLeft = this.props.getTransform().transformPoint(left, top);
let size = this.props.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
- return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }
+ return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) };
}
@action
marqueeCommand = (e: KeyboardEvent) => {
- if (e.key == "Backspace" || e.key == "Delete") {
+ if (e.key === "Backspace" || e.key === "Delete") {
this.marqueeSelect().map(d => this.props.removeDocument(d));
let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
- if (ink && ink != FieldWaiting) {
+ if (ink && ink !== FieldWaiting) {
this.marqueeInkDelete(ink.Data);
}
this.cleanupInteractions();
}
- if (e.key == "c") {
+ if (e.key === "c") {
let bounds = this.Bounds;
let selected = this.marqueeSelect().map(d => {
this.props.removeDocument(d);
@@ -118,7 +118,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
return d;
});
let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
- let inkData = ink && ink != FieldWaiting ? ink.Data : undefined;
+ let inkData = ink && ink !== FieldWaiting ? ink.Data : undefined;
//setTimeout(() => {
let newCollection = Documents.FreeformDocument(selected, {
x: bounds.left,
@@ -147,7 +147,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
if (InkingCanvas.IntersectStrokeRect(value, this.Bounds)) {
idata.set(key,
{
- pathData: value.pathData.map(val => { return { x: val.x + centerShiftX, y: val.y + centerShiftY } }),
+ pathData: value.pathData.map(val => ({ x: val.x + centerShiftX, y: val.y + centerShiftY })),
color: value.color,
width: value.width,
tool: value.tool,
@@ -180,9 +180,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
var y = doc.GetNumber(KeyStore.Y, 0);
var w = doc.GetNumber(KeyStore.Width, 0);
var h = doc.GetNumber(KeyStore.Height, 0);
- if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect))
- selection.push(doc)
- })
+ if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) {
+ selection.push(doc);
+ }
+ });
return selection;
}
@@ -190,7 +191,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
get marqueeDiv() {
let p = this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY);
let v = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
- return <div className="marquee" style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, width: `${Math.abs(v[0])}`, height: `${Math.abs(v[1])}` }} />
+ return <div className="marquee" style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, width: `${Math.abs(v[0])}`, height: `${Math.abs(v[1])}` }} />;
}
render() {
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
index 93c98f7b0..8eabb020a 100644
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
+++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
@@ -33,7 +33,7 @@ export class PreviewCursor extends React.Component<PreviewCursorProps> {
@action
onPointerDown = (e: React.PointerEvent) => {
- if (e.button == 0 && this.props.container.props.active()) {
+ if (e.button === 0 && this.props.container.props.active()) {
document.removeEventListener("keypress", this.onKeyPress, false);
this._showOnUp = true;
this.DownX = e.pageX;
@@ -90,7 +90,7 @@ export class PreviewCursor extends React.Component<PreviewCursorProps> {
{this.props.children}
<PreviewCursorPrompt setVisible={this.setVisible} getPoint={this.getPoint} getVisible={this.getVisible} />
</div>
- )
+ );
}
}
@@ -109,8 +109,9 @@ export class PreviewCursorPrompt extends React.Component<PromptProps> {
render() {
let p = this.props.getPoint();
- if (this.props.getVisible() && this._promptRef.current)
+ if (this.props.getVisible() && this._promptRef.current) {
this._promptRef.current.focus();
+ }
return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._promptRef}
style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, opacity: this.props.getVisible() ? 1 : 0 }}>
I
diff --git a/src/client/views/nodes/Annotation.tsx b/src/client/views/nodes/Annotation.tsx
index a2c7be1a8..3e4ed6bf1 100644
--- a/src/client/views/nodes/Annotation.tsx
+++ b/src/client/views/nodes/Annotation.tsx
@@ -1,16 +1,16 @@
import "./ImageBox.scss";
-import React = require("react")
-import { observer } from "mobx-react"
+import React = require("react");
+import { observer } from "mobx-react";
import { observable, action } from 'mobx';
-import 'react-pdf/dist/Page/AnnotationLayer.css'
+import 'react-pdf/dist/Page/AnnotationLayer.css';
-interface IProps{
+interface IProps {
Span: HTMLSpanElement;
- X: number;
- Y: number;
- Highlights: any[];
- Annotations: any[];
- CurrAnno: any[];
+ X: number;
+ Y: number;
+ Highlights: any[];
+ Annotations: any[];
+ CurrAnno: any[];
}
@@ -23,95 +23,95 @@ interface IProps{
*/
@observer
export class Annotation extends React.Component<IProps> {
-
+
/**
* changes color of the span (highlighted section)
*/
- onColorChange = (e:React.PointerEvent) => {
- if (e.currentTarget.innerHTML == "r"){
- this.props.Span.style.backgroundColor = "rgba(255,0,0, 0.3)"
- } else if (e.currentTarget.innerHTML == "b"){
- this.props.Span.style.backgroundColor = "rgba(0,255, 255, 0.3)"
- } else if (e.currentTarget.innerHTML == "y"){
- this.props.Span.style.backgroundColor = "rgba(255,255,0, 0.3)"
- } else if (e.currentTarget.innerHTML == "g"){
- this.props.Span.style.backgroundColor = "rgba(76, 175, 80, 0.3)"
+ onColorChange = (e: React.PointerEvent) => {
+ if (e.currentTarget.innerHTML === "r") {
+ this.props.Span.style.backgroundColor = "rgba(255,0,0, 0.3)";
+ } else if (e.currentTarget.innerHTML === "b") {
+ this.props.Span.style.backgroundColor = "rgba(0,255, 255, 0.3)";
+ } else if (e.currentTarget.innerHTML === "y") {
+ this.props.Span.style.backgroundColor = "rgba(255,255,0, 0.3)";
+ } else if (e.currentTarget.innerHTML === "g") {
+ this.props.Span.style.backgroundColor = "rgba(76, 175, 80, 0.3)";
}
-
+
}
/**
* removes the highlighted span. Supposed to remove Annotation too, but I don't know how to unmount this
*/
@action
- onRemove = (e:any) => {
- let index:number = -1;
+ onRemove = (e: any) => {
+ let index: number = -1;
//finding the highlight in the highlight array
this.props.Highlights.forEach((e) => {
- for (let i = 0; i < e.spans.length; i++){
- if (e.spans[i] == this.props.Span){
- index = this.props.Highlights.indexOf(e);
- this.props.Highlights.splice(index, 1);
+ for (const span of e.spans) {
+ if (span === this.props.Span) {
+ index = this.props.Highlights.indexOf(e);
+ this.props.Highlights.splice(index, 1);
}
}
- })
+ });
//removing from CurrAnno and Annotation array
- this.props.Annotations.splice(index, 1);
- this.props.CurrAnno.pop()
-
+ this.props.Annotations.splice(index, 1);
+ this.props.CurrAnno.pop();
+
//removing span from div
- if(this.props.Span.parentElement){
- let nodesArray = this.props.Span.parentElement.childNodes;
+ if (this.props.Span.parentElement) {
+ let nodesArray = this.props.Span.parentElement.childNodes;
nodesArray.forEach((e) => {
- if (e == this.props.Span){
- if (this.props.Span.parentElement){
+ if (e === this.props.Span) {
+ if (this.props.Span.parentElement) {
this.props.Highlights.forEach((item) => {
- if (item == e){
- item.remove();
+ if (item === e) {
+ item.remove();
}
- })
- e.remove();
+ });
+ e.remove();
}
}
- })
+ });
}
-
-
+
+
}
render() {
return (
- <div
- style = {{
- position: "absolute",
- top: "20px",
- left: "0px",
- zIndex: 1,
- transform: `translate(${this.props.X}px, ${this.props.Y}px)`,
-
- }}>
- <div style = {{width:"200px", height:"50px", backgroundColor: "orange"}}>
+ <div
+ style={{
+ position: "absolute",
+ top: "20px",
+ left: "0px",
+ zIndex: 1,
+ transform: `translate(${this.props.X}px, ${this.props.Y}px)`,
+
+ }}>
+ <div style={{ width: "200px", height: "50px", backgroundColor: "orange" }}>
<button
- style = {{borderRadius: "25px", width:"25%", height:"100%"}}
- onClick = {this.onRemove}
+ style={{ borderRadius: "25px", width: "25%", height: "100%" }}
+ onClick={this.onRemove}
>x</button>
- <div style = {{width:"75%", height: "100%" , display:"inline-block"}}>
- <button onPointerDown = {this.onColorChange} style = {{backgroundColor:"red", borderRadius:"50%", color: "transparent"}}>r</button>
- <button onPointerDown = {this.onColorChange} style = {{backgroundColor:"blue", borderRadius:"50%", color: "transparent"}}>b</button>
- <button onPointerDown = {this.onColorChange} style = {{backgroundColor:"yellow", borderRadius:"50%", color:"transparent"}}>y</button>
- <button onPointerDown = {this.onColorChange} style = {{backgroundColor:"green", borderRadius:"50%", color:"transparent"}}>g</button>
+ <div style={{ width: "75%", height: "100%", display: "inline-block" }}>
+ <button onPointerDown={this.onColorChange} style={{ backgroundColor: "red", borderRadius: "50%", color: "transparent" }}>r</button>
+ <button onPointerDown={this.onColorChange} style={{ backgroundColor: "blue", borderRadius: "50%", color: "transparent" }}>b</button>
+ <button onPointerDown={this.onColorChange} style={{ backgroundColor: "yellow", borderRadius: "50%", color: "transparent" }}>y</button>
+ <button onPointerDown={this.onColorChange} style={{ backgroundColor: "green", borderRadius: "50%", color: "transparent" }}>g</button>
</div>
-
+
</div>
- <div style = {{width:"200px", height:"200"}}>
- <textarea style = {{width: "100%", height: "100%"}}
- defaultValue = "Enter Text Here..."
-
+ <div style={{ width: "200px", height: "200" }}>
+ <textarea style={{ width: "100%", height: "100%" }}
+ defaultValue="Enter Text Here..."
+
></textarea>
</div>
</div>
-
+
);
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 6daf15f5f..1493ff25b 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -1,18 +1,18 @@
-import React = require("react")
+import React = require("react");
import { FieldViewProps, FieldView } from './FieldView';
import { FieldWaiting } from '../../../fields/Field';
-import { observer } from "mobx-react"
+import { observer } from "mobx-react";
import { ContextMenu } from "../../views/ContextMenu";
import { observable, action } from 'mobx';
import { KeyStore } from '../../../fields/KeyStore';
import { AudioField } from "../../../fields/AudioField";
-import "./AudioBox.scss"
+import "./AudioBox.scss";
import { NumberField } from "../../../fields/NumberField";
@observer
export class AudioBox extends React.Component<FieldViewProps> {
- public static LayoutString() { return FieldView.LayoutString(AudioBox) }
+ public static LayoutString() { return FieldView.LayoutString(AudioBox); }
constructor(props: FieldViewProps) {
super(props);
@@ -28,8 +28,8 @@ export class AudioBox extends React.Component<FieldViewProps> {
render() {
- let field = this.props.doc.Get(this.props.fieldKey)
- let path = field == FieldWaiting ? "http://techslides.com/demos/samples/sample.mp3" :
+ let field = this.props.Document.Get(this.props.fieldKey);
+ let path = field === FieldWaiting ? "http://techslides.com/demos/samples/sample.mp3" :
field instanceof AudioField ? field.Data.href : "http://techslides.com/demos/samples/sample.mp3";
return (
@@ -39,6 +39,6 @@ export class AudioBox extends React.Component<FieldViewProps> {
Not supported.
</audio>
</div>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 1a0f0cbbd..77f41105f 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -35,31 +35,29 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
@computed get nativeHeight(): number { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
set width(w: number) {
- this.props.Document.SetData(KeyStore.Width, w, NumberField)
+ this.props.Document.SetData(KeyStore.Width, w, NumberField);
if (this.nativeWidth && this.nativeHeight) {
- this.props.Document.SetNumber(KeyStore.Height, this.nativeHeight / this.nativeWidth * w)
+ this.props.Document.SetNumber(KeyStore.Height, this.nativeHeight / this.nativeWidth * w);
}
}
set height(h: number) {
this.props.Document.SetData(KeyStore.Height, h, NumberField);
if (this.nativeWidth && this.nativeHeight) {
- this.props.Document.SetNumber(KeyStore.Width, this.nativeWidth / this.nativeHeight * h)
+ this.props.Document.SetNumber(KeyStore.Width, this.nativeWidth / this.nativeHeight * h);
}
}
set zIndex(h: number) {
- this.props.Document.SetData(KeyStore.ZIndex, h, NumberField)
+ this.props.Document.SetData(KeyStore.ZIndex, h, NumberField);
}
- contentScaling = () => {
- return this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
- }
+ contentScaling = () => 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)).scale(1 / this.contentScaling());
- }
+ getTransform = (): Transform =>
+ 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() {
@@ -68,7 +66,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
ScreenToLocalTransform={this.getTransform}
PanelWidth={this.panelWidth}
PanelHeight={this.panelHeight}
- />
+ />;
}
panelWidth = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelWidth();
panelHeight = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelHeight();
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 77551649c..5836da396 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -1,6 +1,6 @@
import { computed } from "mobx";
import { observer } from "mobx-react";
-import { FieldWaiting } from "../../../fields/Field";
+import { FieldWaiting, Field } from "../../../fields/Field";
import { Key } from "../../../fields/Key";
import { KeyStore } from "../../../fields/KeyStore";
import { ListField } from "../../../fields/ListField";
@@ -11,7 +11,7 @@ import { CollectionSchemaView } from "../collections/CollectionSchemaView";
import { CollectionVideoView } from "../collections/CollectionVideoView";
import { CollectionView } from "../collections/CollectionView";
import { AudioBox } from "./AudioBox";
-import { DocumentViewProps, JsxBindings } from "./DocumentView";
+import { DocumentViewProps } from "./DocumentView";
import "./DocumentView.scss";
import { FormattedTextBox } from "./FormattedTextBox";
import { ImageBox } from "./ImageBox";
@@ -21,8 +21,16 @@ import { VideoBox } from "./VideoBox";
import { WebBox } from "./WebBox";
import { HistogramBox } from "../../northstar/dash-nodes/HistogramBox";
import React = require("react");
+import { Document } from "../../../fields/Document";
+import { FieldViewProps } from "./FieldView";
+import { Without } from "../../../Utils";
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
+type BindingProps = Without<FieldViewProps, 'fieldKey'>;
+export interface JsxBindings {
+ props: BindingProps;
+ [keyName: string]: BindingProps | Field;
+}
@observer
export class DocumentContentsView extends React.Component<DocumentViewProps & {
@@ -36,13 +44,40 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
CreateBindings(): JsxBindings {
- let bindings: JsxBindings = { ...this.props, };
+ let
+ {
+ Document,
+ isSelected,
+ select,
+ isTopMost,
+ selectOnLoad,
+ ScreenToLocalTransform,
+ addDocument,
+ removeDocument,
+ onActiveChanged,
+ parentActive: active,
+ } = this.props;
+ let bindings: JsxBindings = {
+ props: {
+ Document,
+ isSelected,
+ select,
+ isTopMost,
+ selectOnLoad,
+ ScreenToLocalTransform,
+ active,
+ onActiveChanged,
+ addDocument,
+ removeDocument,
+ focus,
+ }
+ };
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
}
for (const key of this.layoutFields) {
let field = this.props.Document.Get(key);
- bindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field;
+ bindings[key.Name] = field && field !== FieldWaiting ? field.GetValue() : field;
}
return bindings;
}
@@ -57,7 +92,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
bindings={this.CreateBindings()}
jsx={this.layout}
showWarnings={true}
- onError={(test: any) => { console.log(test) }}
- />
+ onError={(test: any) => { console.log(test); }}
+ />;
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7514e782d..9670ca6b2 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -15,24 +15,28 @@ import { DragManager } from "../../util/DragManager";
import { SelectionManager } from "../../util/SelectionManager";
import { Transform } from "../../util/Transform";
import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { CollectionView, CollectionViewType } from "../collections/CollectionView";
+import { CollectionView } from "../collections/CollectionView";
import { ContextMenu } from "../ContextMenu";
import { DocumentContentsView } from "./DocumentContentsView";
import "./DocumentView.scss";
import React = require("react");
+
export interface DocumentViewProps {
ContainingCollectionView: Opt<CollectionView>;
Document: Document;
- AddDocument?: (doc: Document, allowDuplicates: boolean) => boolean;
- RemoveDocument?: (doc: Document) => boolean;
+ addDocument?: (doc: Document, allowDuplicates?: boolean) => boolean;
+ removeDocument?: (doc: Document) => boolean;
+ moveDocument?: (doc: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
ScreenToLocalTransform: () => Transform;
isTopMost: boolean;
ContentScaling: () => number;
PanelWidth: () => number;
PanelHeight: () => number;
focus: (doc: Document) => void;
- SelectOnLoad: boolean;
+ selectOnLoad: boolean;
+ parentActive: () => boolean;
+ onActiveChanged: (isActive: boolean) => void;
}
export interface JsxArgs extends DocumentViewProps {
Keys: { [name: string]: Key };
@@ -76,68 +80,29 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
return args;
}
-export interface JsxBindings {
- Document: Document;
- isSelected: () => boolean;
- select: (isCtrlPressed: boolean) => void;
- isTopMost: boolean;
- SelectOnLoad: boolean;
- [prop: string]: any;
-}
-
@observer
export class DocumentView extends React.Component<DocumentViewProps> {
private _mainCont = React.createRef<HTMLDivElement>();
+ public get ContentRef() {
+ return this._mainCont;
+ }
private _downX: number = 0;
private _downY: number = 0;
-
- private _reactionDisposer: Opt<IReactionDisposer>;
- @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();
+ @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); }
+ @computed get topMost(): boolean { return this.props.isTopMost; }
+ @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;
if (e.shiftKey && e.buttons === 2) {
if (this.props.isTopMost) {
this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
- } else
+ } else {
CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
+ }
e.stopPropagation();
} else {
if (this.active && !e.isDefaultPrevented()) {
@@ -148,7 +113,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
document.addEventListener("pointerup", this.onPointerUp);
}
}
- };
+ }
private dropDisposer?: DragManager.DragDropDisposer;
@@ -159,20 +124,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
});
}
runInAction(() => DocumentManager.Instance.DocumentViews.push(this));
- this._reactionDisposer = reaction(
- () =>
- this.props.ContainingCollectionView &&
- this.props.ContainingCollectionView.SelectedDocs.slice(),
- () => {
- if (
- this.props.ContainingCollectionView &&
- this.props.ContainingCollectionView.SelectedDocs.indexOf(
- this.props.Document.Id
- ) != -1
- )
- SelectionManager.SelectDoc(this, true);
- }
- );
}
componentDidUpdate() {
@@ -190,15 +141,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
if (this.dropDisposer) {
this.dropDisposer();
}
- runInAction(() =>
- DocumentManager.Instance.DocumentViews.splice(
- DocumentManager.Instance.DocumentViews.indexOf(this),
- 1
- )
- );
- if (this._reactionDisposer) {
- this._reactionDisposer();
- }
+ runInAction(() => DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1));
}
startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
@@ -211,14 +154,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
dragData.aliasOnDrop = dropAliasOfDraggedDoc;
dragData.xOffset = x - left;
dragData.yOffset = y - top;
- dragData.removeDocument = (dropCollectionView: CollectionView) => {
- if (
- this.props.RemoveDocument &&
- this.props.ContainingCollectionView !== dropCollectionView
- ) {
- this.props.RemoveDocument(this.props.Document);
- }
- };
+ dragData.moveDocument = this.props.moveDocument;
DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, {
handlers: {
dragComplete: action(() => { })
@@ -238,13 +174,13 @@ export class DocumentView extends React.Component<DocumentViewProps> {
) {
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
- if (!this.topMost || e.buttons == 2 || e.altKey) {
+ if (!this.topMost || e.buttons === 2 || e.altKey) {
this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey);
}
}
e.stopPropagation();
e.preventDefault();
- };
+ }
onPointerUp = (e: PointerEvent): void => {
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
@@ -255,25 +191,22 @@ export class DocumentView extends React.Component<DocumentViewProps> {
) {
SelectionManager.SelectDoc(this, e.ctrlKey);
}
- };
+ }
stopPropogation = (e: React.SyntheticEvent) => {
e.stopPropagation();
- };
+ }
deleteClicked = (): void => {
- if (this.props.RemoveDocument) {
- this.props.RemoveDocument(this.props.Document);
+ if (this.props.removeDocument) {
+ this.props.removeDocument(this.props.Document);
}
- };
+ }
fieldsClicked = (e: React.MouseEvent): void => {
- if (this.props.AddDocument) {
- this.props.AddDocument(
- Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }),
- false
- );
+ if (this.props.addDocument) {
+ this.props.addDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), false);
}
- };
+ }
fullScreenClicked = (e: React.MouseEvent): void => {
CollectionDockingView.Instance.OpenFullScreen(this.props.Document);
ContextMenu.Instance.clearItems();
@@ -282,7 +215,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
event: this.closeFullScreenClicked
});
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
- };
+ }
closeFullScreenClicked = (e: React.MouseEvent): void => {
CollectionDockingView.Instance.CloseFullScreen();
@@ -292,7 +225,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
event: this.fullScreenClicked
});
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
- };
+ }
@action
public minimize = (): void => {
@@ -302,7 +235,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
BooleanField
);
SelectionManager.DeselectAll();
- };
+ }
@action
drop = (e: Event, de: DragManager.DropEvent) => {
@@ -344,7 +277,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
);
e.stopPropagation();
}
- };
+ }
onDrop = (e: React.DragEvent) => {
if (e.isDefaultPrevented()) {
@@ -358,7 +291,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
e.stopPropagation();
e.preventDefault();
}
- };
+ }
@action
onContextMenu = (e: React.MouseEvent): void => {
@@ -420,14 +353,14 @@ export class DocumentView extends React.Component<DocumentViewProps> {
});
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
SelectionManager.SelectDoc(this, e.ctrlKey);
- };
+ }
isMinimized = () => {
let field = this.props.Document.GetT(KeyStore.Minimized, BooleanField);
if (field && field !== FieldWaiting) {
return field.Data;
}
- };
+ }
@action
expand = () => {
@@ -436,15 +369,13 @@ export class DocumentView extends React.Component<DocumentViewProps> {
false as boolean,
BooleanField
);
- };
+ }
- isSelected = () => {
- return SelectionManager.IsSelected(this);
- };
+ isSelected = () => SelectionManager.IsSelected(this);
select = (ctrlPressed: boolean) => {
SelectionManager.SelectDoc(this, ctrlPressed);
- };
+ }
render() {
if (!this.props.Document) {
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 4e83ec7b9..07c5b332c 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
import { observer } from "mobx-react";
import { computed } from "mobx";
import { Field, FieldWaiting, FieldValue } from "../../../fields/Field";
@@ -7,7 +7,7 @@ import { TextField } from "../../../fields/TextField";
import { NumberField } from "../../../fields/NumberField";
import { RichTextField } from "../../../fields/RichTextField";
import { ImageField } from "../../../fields/ImageField";
-import { VideoField } from "../../../fields/VideoField"
+import { VideoField } from "../../../fields/VideoField";
import { Key } from "../../../fields/Key";
import { FormattedTextBox } from "./FormattedTextBox";
import { ImageBox } from "./ImageBox";
@@ -19,6 +19,7 @@ import { ListField } from "../../../fields/ListField";
import { DocumentContentsView } from "./DocumentContentsView";
import { Transform } from "../../util/Transform";
import { KeyStore } from "../../../fields/KeyStore";
+import { returnFalse } from "../../../Utils";
//
@@ -28,80 +29,89 @@ import { KeyStore } from "../../../fields/KeyStore";
//
export interface FieldViewProps {
fieldKey: Key;
- doc: Document;
+ Document: Document;
isSelected: () => boolean;
- select: () => void;
+ select: (isCtrlPressed: boolean) => void;
isTopMost: boolean;
selectOnLoad: boolean;
- bindings: any;
+ addDocument?: (document: Document, allowDuplicates?: boolean) => boolean;
+ removeDocument?: (document: Document) => boolean;
+ moveDocument?: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
+ ScreenToLocalTransform: () => Transform;
+ active: () => boolean;
+ onActiveChanged: (isActive: boolean) => void;
+ focus: (doc: Document) => void;
}
@observer
export class FieldView extends React.Component<FieldViewProps> {
public static LayoutString(fieldType: { name: string }, fieldStr: string = "DataKey") {
- return `<${fieldType.name} doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={${fieldStr}} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost} />`;
+ return `<${fieldType.name} {...props} fieldKey={${fieldStr}} />`;
}
@computed
get field(): FieldValue<Field> {
- const { doc, fieldKey } = this.props;
+ const { Document: doc, fieldKey } = this.props;
return doc.Get(fieldKey);
}
render() {
const field = this.field;
if (!field) {
- return <p>{'<null>'}</p>
+ return <p>{'<null>'}</p>;
}
if (field instanceof TextField) {
- return <p>{field.Data}</p>
+ return <p>{field.Data}</p>;
}
else if (field instanceof RichTextField) {
- return <FormattedTextBox {...this.props} />
+ return <FormattedTextBox {...this.props} />;
}
else if (field instanceof ImageField) {
- return <ImageBox {...this.props} />
+ return <ImageBox {...this.props} />;
}
else if (field instanceof VideoField) {
- return <VideoBox {...this.props} />
+ return <VideoBox {...this.props} />;
}
else if (field instanceof AudioField) {
- return <AudioBox {...this.props} />
+ return <AudioBox {...this.props} />;
}
else if (field instanceof Document) {
- return (<DocumentContentsView Document={field}
- AddDocument={undefined}
- RemoveDocument={undefined}
- ScreenToLocalTransform={() => Transform.Identity}
- ContentScaling={() => 1}
- PanelWidth={() => 100}
- PanelHeight={() => 100}
- isTopMost={true}
- SelectOnLoad={false}
- focus={() => { }}
- isSelected={() => false}
- select={() => false}
- layoutKey={KeyStore.Layout}
- ContainingCollectionView={undefined} />)
+ return (
+ <DocumentContentsView Document={field}
+ addDocument={undefined}
+ removeDocument={undefined}
+ ScreenToLocalTransform={Transform.Identity}
+ ContentScaling={() => 1}
+ PanelWidth={() => 100}
+ PanelHeight={() => 100}
+ isTopMost={true} //TODO Why is this top most?
+ selectOnLoad={false}
+ focus={() => { }}
+ isSelected={() => false}
+ select={() => false}
+ layoutKey={KeyStore.Layout}
+ ContainingCollectionView={undefined}
+ parentActive={this.props.active}
+ onActiveChanged={this.props.onActiveChanged} />
+ );
}
else if (field instanceof ListField) {
return (<div>
- {(field as ListField<Field>).Data.map(f => {
- return f instanceof Document ? f.Title : f.GetValue().toString();
- }).join(", ")}
- </div>)
+ {(field as ListField<Field>).Data.map(f => f instanceof Document ? f.Title : f.GetValue().toString()).join(", ")}
+ </div>);
}
// bcz: this belongs here, but it doesn't render well so taking it out for now
// else if (field instanceof HtmlField) {
// return <WebBox {...this.props} />
// }
else if (field instanceof NumberField) {
- return <p>{field.Data}</p>
+ return <p>{field.Data}</p>;
}
- else if (field != FieldWaiting) {
- return <p>{JSON.stringify(field.GetValue())}</p>
+ else if (field !== FieldWaiting) {
+ return <p>{JSON.stringify(field.GetValue())}</p>;
}
- else
- return <p> {"Waiting for server..."} </p>
+ else {
+ return <p> {"Waiting for server..."} </p>;
+ }
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 0c0efc437..beca6cdc6 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -2,19 +2,19 @@ import { action, IReactionDisposer, reaction } from "mobx";
import { baseKeymap } from "prosemirror-commands";
import { history, redo, undo } from "prosemirror-history";
import { keymap } from "prosemirror-keymap";
-import { schema } from "../../util/RichTextSchema";
-import { EditorState, Transaction } from "prosemirror-state";
+import { EditorState, Plugin, Transaction } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
-import { Opt, FieldWaiting } from "../../../fields/Field";
-import "./FormattedTextBox.scss";
-import React = require("react");
+import { FieldWaiting, Opt } from "../../../fields/Field";
+import { KeyStore } from "../../../fields/KeyStore";
import { RichTextField } from "../../../fields/RichTextField";
-import { FieldViewProps, FieldView } from "./FieldView";
-import { Plugin } from "prosemirror-state";
-import { Decoration, DecorationSet } from "prosemirror-view";
+import { inpRules } from "../../util/RichTextRules";
+import { schema } from "../../util/RichTextSchema";
import { TooltipTextMenu } from "../../util/TooltipTextMenu";
import { ContextMenu } from "../../views/ContextMenu";
-import { inpRules } from "../../util/RichTextRules";
+import { Main } from "../Main";
+import { FieldView, FieldViewProps } from "./FieldView";
+import "./FormattedTextBox.scss";
+import React = require("react");
const { buildMenuItems } = require("prosemirror-example-setup");
const { menuBar } = require("prosemirror-menu");
@@ -35,156 +35,195 @@ const { menuBar } = require("prosemirror-menu");
// this will edit the document and assign the new value to that field.
//]
export class FormattedTextBox extends React.Component<FieldViewProps> {
- public static LayoutString(fieldStr: string = "DataKey") {
- return FieldView.LayoutString(FormattedTextBox, fieldStr);
- }
- private _ref: React.RefObject<HTMLDivElement>;
- private _editorView: Opt<EditorView>;
- private _reactionDisposer: Opt<IReactionDisposer>;
-
- constructor(props: FieldViewProps) {
- 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.SetDataOnPrototype(
- fieldKey,
- JSON.stringify(state.toJSON()),
- RichTextField
- );
- // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
- }
- };
-
- componentDidMount() {
- let state: EditorState;
- const config = {
- schema,
- inpRules, //these currently don't do anything, but could eventually be helpful
- plugins: [
- history(),
- keymap({ "Mod-z": undo, "Mod-y": redo }),
- keymap(baseKeymap),
- this.tooltipMenuPlugin()
- ]
- };
-
- let field = this.props.doc.GetT(this.props.fieldKey, RichTextField);
- if (field && field != FieldWaiting && field.Data) {
- 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.GetT(this.props.fieldKey, RichTextField);
- return field && field != FieldWaiting ? field.Data : undefined;
- },
- field => {
- if (field && this._editorView) {
- this._editorView.updateState(
- EditorState.fromJSON(config, JSON.parse(field))
- );
+ public static LayoutString(fieldStr: string = "DataKey") {
+ return FieldView.LayoutString(FormattedTextBox, fieldStr);
+ }
+ private _ref: React.RefObject<HTMLDivElement>;
+ private _editorView: Opt<EditorView>;
+ private _reactionDisposer: Opt<IReactionDisposer>;
+ private _inputReactionDisposer: Opt<IReactionDisposer>;
+
+ constructor(props: FieldViewProps) {
+ 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);
+ this.FieldDoc.SetDataOnPrototype(
+ this.FieldKey,
+ JSON.stringify(state.toJSON()),
+ RichTextField
+ );
+ // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+ }
+ }
+
+ get FieldDoc() { return this.props.fieldKey === KeyStore.Archives ? Main.Instance._textDoc! : this.props.Document; }
+ get FieldKey() { return this.props.fieldKey === KeyStore.Archives ? KeyStore.Data : this.props.fieldKey; }
+
+ componentDidMount() {
+ const config = {
+ schema,
+ inpRules, //these currently don't do anything, but could eventually be helpful
+ plugins: [
+ history(),
+ keymap({ "Mod-z": undo, "Mod-y": redo }),
+ keymap(baseKeymap),
+ this.tooltipMenuPlugin()
+ ]
+ };
+
+ if (this.props.fieldKey === KeyStore.Archives) {
+ this._inputReactionDisposer = reaction(() => Main.Instance._textDoc && Main.Instance._textDoc.Id,
+ () => {
+ if (this._editorView) {
+ this._editorView.destroy();
+ }
+
+ this.setupEditor(config);
+ }
+ );
+ }
+
+ this._reactionDisposer = reaction(
+ () => {
+ const field = this.FieldDoc.GetT(this.FieldKey, RichTextField);
+ return field && field !== FieldWaiting ? field.Data : undefined;
+ },
+ field => {
+ if (field && this._editorView) {
+ this._editorView.updateState(
+ EditorState.fromJSON(config, JSON.parse(field))
+ );
+ }
+ }
+ );
+ this.setupEditor(config);
+ }
+
+ private setupEditor(config: any) {
+
+ let state: EditorState;
+ let field = this.FieldDoc.GetT(this.FieldKey, RichTextField);
+ if (field && field !== FieldWaiting && field.Data) {
+ 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
+ });
}
- }
- );
- if (this.props.selectOnLoad) {
- this.props.select();
- this._editorView!.focus();
- }
- }
-
- 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.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
- // doc.SetData(fieldKey, e.target.value, RichTextField);
- }
- onPointerDown = (e: React.PointerEvent): void => {
- if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
- e.stopPropagation();
- }
- };
-
- //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE
- textCapability = (e: React.MouseEvent): void => {};
-
- specificContextMenu = (e: React.MouseEvent): void => {
- ContextMenu.Instance.addItem({
- description: "Text Capability",
- event: this.textCapability
- });
-
- // ContextMenu.Instance.addItem({
- // description: "Submenu",
- // items: [
- // {
- // description: "item 1", event:
- // },
- // {
- // description: "item 2", event:
- // }
- // ]
- // })
- // e.stopPropagation()
- };
-
- onPointerWheel = (e: React.WheelEvent): void => {
- e.stopPropagation();
- };
-
- tooltipMenuPlugin() {
- return new Plugin({
- view(_editorView) {
- return new TooltipTextMenu(_editorView);
- }
- });
- }
- onKeyPress(e: React.KeyboardEvent) {
- e.stopPropagation();
- // stop propagation doesn't seem to stop propagation of native keyboard events.
- // so we set a flag on the native event that marks that the event's been handled.
- // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
- }
- render() {
- return (
- <div
- className="formattedTextBox-cont"
- onKeyDown={this.onKeyPress}
- onKeyPress={this.onKeyPress}
- onPointerDown={this.onPointerDown}
- onContextMenu={this.specificContextMenu}
- // tfs: do we need this event handler
- onWheel={this.onPointerWheel}
- ref={this._ref}
- />
- );
- }
+
+ if (this.props.selectOnLoad) {
+ this.props.select(false);
+ this._editorView!.focus();
+ }
+ }
+
+ componentWillUnmount() {
+ if (this._editorView) {
+ this._editorView.destroy();
+ }
+ if (this._reactionDisposer) {
+ this._reactionDisposer();
+ }
+ if (this._inputReactionDisposer) {
+ this._inputReactionDisposer();
+ }
+ }
+
+ shouldComponentUpdate() {
+ return false;
+ }
+
+ @action
+ onChange(e: React.ChangeEvent<HTMLInputElement>) {
+ const { fieldKey, Document } = this.props;
+ Document.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
+ // doc.SetData(fieldKey, e.target.value, RichTextField);
+ }
+ onPointerDown = (e: React.PointerEvent): void => {
+ if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
+ e.stopPropagation();
+ }
+ }
+ onPointerUp = (e: React.PointerEvent): void => {
+ if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
+ e.stopPropagation();
+ }
+ if (this.props.fieldKey !== KeyStore.Archives) {
+ e.preventDefault();
+ Main.Instance.SetTextDoc(this.props.Document, this._ref.current!);
+ }
+ }
+
+ onFocused = (e: React.FocusEvent): void => {
+ if (this.props.fieldKey !== KeyStore.Archives) {
+ Main.Instance.SetTextDoc(this.props.Document, this._ref.current!);
+ }
+ }
+
+ //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE
+ textCapability = (e: React.MouseEvent): void => { };
+
+ specificContextMenu = (e: React.MouseEvent): void => {
+ ContextMenu.Instance.addItem({
+ description: "Text Capability",
+ event: this.textCapability
+ });
+
+ // ContextMenu.Instance.addItem({
+ // description: "Submenu",
+ // items: [
+ // {
+ // description: "item 1", event:
+ // },
+ // {
+ // description: "item 2", event:
+ // }
+ // ]
+ // })
+ // e.stopPropagation()
+ }
+
+ onPointerWheel = (e: React.WheelEvent): void => {
+ e.stopPropagation();
+ }
+
+ tooltipMenuPlugin() {
+ return new Plugin({
+ view(_editorView) {
+ return new TooltipTextMenu(_editorView);
+ }
+ });
+ }
+ onKeyPress(e: React.KeyboardEvent) {
+ e.stopPropagation();
+ // stop propagation doesn't seem to stop propagation of native keyboard events.
+ // so we set a flag on the native event that marks that the event's been handled.
+ // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
+ }
+ render() {
+ return (
+ <div
+ className="formattedTextBox-cont"
+ onKeyDown={this.onKeyPress}
+ onKeyPress={this.onKeyPress}
+ onPointerUp={this.onPointerUp}
+ onPointerDown={this.onPointerDown}
+ onContextMenu={this.specificContextMenu}
+ // tfs: do we need this event handler
+ onWheel={this.onPointerWheel}
+ ref={this._ref}
+ />
+ );
+ }
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 60d1f7214..6b0a3a799 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -9,13 +9,13 @@ import { KeyStore } from '../../../fields/KeyStore';
import { ContextMenu } from "../../views/ContextMenu";
import { FieldView, FieldViewProps } from './FieldView';
import "./ImageBox.scss";
-import React = require("react")
+import React = require("react");
import { Utils } from '../../../Utils';
@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 _imgRef: React.RefObject<HTMLImageElement>;
private _downX: number = 0;
@@ -39,7 +39,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
onLoad = (target: any) => {
var h = this._imgRef.current!.naturalHeight;
var w = this._imgRef.current!.naturalWidth;
- this.props.doc.SetNumber(KeyStore.NativeHeight, this.props.doc.GetNumber(KeyStore.NativeWidth, 0) * h / w)
+ this.props.Document.SetNumber(KeyStore.NativeHeight, this.props.Document.GetNumber(KeyStore.NativeWidth, 0) * h / w);
}
componentDidMount() {
@@ -86,31 +86,31 @@ export class ImageBox extends React.Component<FieldViewProps> {
onMoveNextRequest={action(() =>
this._photoIndex = (this._photoIndex + 1) % images.length
)}
- />)
+ />);
}
}
specificContextMenu = (e: React.MouseEvent): void => {
- let field = this.props.doc.GetT(this.props.fieldKey, ImageField);
+ let field = this.props.Document.GetT(this.props.fieldKey, ImageField);
if (field && field !== FieldWaiting) {
let url = field.Data.href;
ContextMenu.Instance.addItem({
description: "Copy path", event: () => {
- Utils.CopyText(url)
+ Utils.CopyText(url);
}
});
}
}
render() {
- let field = this.props.doc.Get(this.props.fieldKey);
- let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
+ let field = this.props.Document.Get(this.props.fieldKey);
+ let path = field === FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
field instanceof ImageField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif";
- let nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 1);
+ let nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 1);
return (
<div className="imageBox-cont" onPointerDown={this.onPointerDown} ref={this._ref} onContextMenu={this.specificContextMenu}>
<img src={path} width={nativeWidth} alt="Image not found" ref={this._imgRef} onLoad={this.onLoad} />
{this.lightbox(path)}
- </div>)
+ </div>);
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 9bd6c1052..bcac113f0 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -7,7 +7,7 @@ import { KeyStore } from '../../../fields/KeyStore';
import { FieldView, FieldViewProps } from './FieldView';
import "./KeyValueBox.scss";
import { KeyValuePair } from "./KeyValuePair";
-import React = require("react")
+import React = require("react");
import { CompileScript, ToField } from "../../util/Scripting";
import { Key } from '../../../fields/Key';
import { observable, action } from "mobx";
@@ -15,7 +15,7 @@ import { observable, action } from "mobx";
@observer
export class KeyValueBox extends React.Component<FieldViewProps> {
- public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr) }
+ public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr); }
@observable private _keyInput: string = "";
@observable private _valueInput: string = "";
@@ -32,11 +32,11 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
@action
onEnterKey = (e: React.KeyboardEvent): void => {
- if (e.key == 'Enter') {
+ if (e.key === 'Enter') {
if (this._keyInput && this._valueInput) {
- let doc = this.props.doc.GetT(KeyStore.Data, Document);
- if (!doc || doc == FieldWaiting) {
- return
+ let doc = this.props.Document.GetT(KeyStore.Data, Document);
+ if (!doc || doc === FieldWaiting) {
+ return;
}
let realDoc = doc;
@@ -55,8 +55,8 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
realDoc.Set(new Key(this._keyInput), dataField);
}
}
- this._keyInput = ""
- this._valueInput = ""
+ this._keyInput = "";
+ this._valueInput = "";
}
}
}
@@ -71,9 +71,9 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
}
createTable = () => {
- let doc = this.props.doc.GetT(KeyStore.Data, Document);
- if (!doc || doc == FieldWaiting) {
- return <tr><td>Loading...</td></tr>
+ let doc = this.props.Document.GetT(KeyStore.Data, Document);
+ if (!doc || doc === FieldWaiting) {
+ return <tr><td>Loading...</td></tr>;
}
let realDoc = doc;
@@ -84,13 +84,13 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
if (!(key in ids)) {
ids[key] = key;
}
- })
+ });
}
let rows: JSX.Element[] = [];
let i = 0;
for (let key in ids) {
- rows.push(<KeyValuePair doc={realDoc} rowStyle={"keyValueBox-" + (i++ % 2 ? "oddRow" : "evenRow")} fieldId={key} key={key} />)
+ rows.push(<KeyValuePair doc={realDoc} rowStyle={"keyValueBox-" + (i++ % 2 ? "oddRow" : "evenRow")} fieldId={key} key={key} />);
}
return rows;
}
@@ -105,14 +105,13 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
this._valueInput = e.currentTarget.value;
}
- newKeyValue = () => {
- return (
+ newKeyValue = () =>
+ (
<tr>
<td><input type="text" value={this._keyInput} placeholder="Key" onChange={this.keyChanged} /></td>
<td><input type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyPress={this.onEnterKey} /></td>
</tr>
)
- }
render() {
return (<div className="keyValueBox-cont" onWheel={this.onPointerWheel}>
@@ -126,6 +125,6 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
{this.newKeyValue()}
</tbody>
</table>
- </div>)
+ </div>);
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 5647f45bf..a1050dc6e 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -1,16 +1,18 @@
import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
import "./KeyValueBox.scss";
import "./KeyValuePair.scss";
-import React = require("react")
+import React = require("react");
import { FieldViewProps, FieldView } from './FieldView';
import { Opt, Field } from '../../../fields/Field';
-import { observer } from "mobx-react"
+import { observer } from "mobx-react";
import { observable, action } from 'mobx';
import { Document } from '../../../fields/Document';
import { Key } from '../../../fields/Key';
-import { Server } from "../../Server"
+import { Server } from "../../Server";
import { EditableView } from "../EditableView";
import { CompileScript, ToField } from "../../util/Scripting";
+import { Transform } from '../../util/Transform';
+import { returnFalse, emptyFunction } from '../../../Utils';
// Represents one row in a key value plane
@@ -23,7 +25,7 @@ export interface KeyValuePairProps {
export class KeyValuePair extends React.Component<KeyValuePairProps> {
@observable
- private key: Opt<Key>
+ private key: Opt<Key>;
constructor(props: KeyValuePairProps) {
super(props);
@@ -39,18 +41,21 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
render() {
if (!this.key) {
- return <tr><td>error</td><td></td></tr>
+ return <tr><td>error</td><td></td></tr>;
}
let props: FieldViewProps = {
- doc: this.props.doc,
+ Document: this.props.doc,
fieldKey: this.key,
- isSelected: () => false,
- select: () => { },
+ isSelected: returnFalse,
+ select: emptyFunction,
isTopMost: false,
- bindings: {},
selectOnLoad: false,
- }
+ active: returnFalse,
+ onActiveChanged: emptyFunction,
+ ScreenToLocalTransform: Transform.Identity,
+ focus: emptyFunction,
+ };
let contents = (
<FieldView {...props} />
);
@@ -61,15 +66,15 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
<div className="container">
<div>{this.key.Name}</div>
<button className="delete" onClick={() => {
- let field = props.doc.Get(props.fieldKey);
+ let field = props.Document.Get(props.fieldKey);
if (field && field instanceof Field) {
- props.doc.Set(props.fieldKey, undefined);
+ props.Document.Set(props.fieldKey, undefined);
}
}}>X</button>
</div>
</td>
<td><EditableView contents={contents} height={36} GetValue={() => {
- let field = props.doc.Get(props.fieldKey);
+ let field = props.Document.Get(props.fieldKey);
if (field && field instanceof Field) {
return field.ToScriptString();
}
@@ -84,18 +89,18 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
if (!res.success) return false;
const field = res.result;
if (field instanceof Field) {
- props.doc.Set(props.fieldKey, field);
+ props.Document.Set(props.fieldKey, field);
return true;
} else {
let dataField = ToField(field);
if (dataField) {
- props.doc.Set(props.fieldKey, dataField);
+ props.Document.Set(props.fieldKey, dataField);
return true;
}
}
return false;
}}></EditableView></td>
</tr>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index e81f8fec7..b016a3d48 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -2,8 +2,8 @@ import { observable, computed, action } from "mobx";
import React = require("react");
import { SelectionManager } from "../../util/SelectionManager";
import { observer } from "mobx-react";
-import './LinkBox.scss'
-import { KeyStore } from '../../../fields/KeyStore'
+import './LinkBox.scss';
+import { KeyStore } from '../../../fields/KeyStore';
import { props } from "bluebird";
import { DocumentView } from "./DocumentView";
import { Document } from "../../../fields/Document";
@@ -30,7 +30,7 @@ interface Props {
linkName: String;
pairedDoc: Document;
type: String;
- showEditor: () => void
+ showEditor: () => void;
}
@observer
@@ -49,15 +49,16 @@ export class LinkBox extends React.Component<Props> {
} else if (contextDoc instanceof Document) {
this.props.pairedDoc.GetTAsync(KeyStore.Page, NumberField).then((pfield: any) => {
contextDoc.GetTAsync(KeyStore.CurPage, NumberField).then((cfield: any) => {
- if (pfield != cfield)
+ if (pfield !== cfield) {
contextDoc.SetNumber(KeyStore.CurPage, pfield.Data);
+ }
let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
if (contextView) {
contextView.props.focus(contextDoc);
} else {
CollectionDockingView.Instance.AddRightSplit(contextDoc);
}
- })
+ });
});
}
});
@@ -80,7 +81,7 @@ export class LinkBox extends React.Component<Props> {
if (field) {
field.Data.splice(field.Data.indexOf(this.props.linkDoc));
}
- })
+ });
}
});
this.props.linkDoc.GetTAsync(KeyStore.LinkedToDocs, Document, field => {
@@ -89,7 +90,7 @@ export class LinkBox extends React.Component<Props> {
if (field) {
field.Data.splice(field.Data.indexOf(this.props.linkDoc));
}
- })
+ });
}
});
}
@@ -117,6 +118,6 @@ export class LinkBox extends React.Component<Props> {
<FontAwesomeIcon className="fa-icon-delete" icon="times" size="sm" /></div>
</div>
</div>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx
index 3f7b4bf2d..bde50fed8 100644
--- a/src/client/views/nodes/LinkEditor.tsx
+++ b/src/client/views/nodes/LinkEditor.tsx
@@ -2,8 +2,8 @@ import { observable, computed, action } from "mobx";
import React = require("react");
import { SelectionManager } from "../../util/SelectionManager";
import { observer } from "mobx-react";
-import './LinkEditor.scss'
-import { KeyStore } from '../../../fields/KeyStore'
+import './LinkEditor.scss';
+import { KeyStore } from '../../../fields/KeyStore';
import { props } from "bluebird";
import { DocumentView } from "./DocumentView";
import { Document } from "../../../fields/Document";
@@ -43,7 +43,7 @@ export class LinkEditor extends React.Component<Props> {
<div className="save-button" onPointerDown={this.onSaveButtonPressed}>SAVE</div>
</div>
- )
+ );
}
@action
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index 5eeb40772..ac09da305 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -13,7 +13,7 @@ import React = require("react");
interface Props {
docView: DocumentView;
- changeFlyout: () => void
+ changeFlyout: () => void;
}
@observer
@@ -24,10 +24,10 @@ export class LinkMenu extends React.Component<Props> {
renderLinkItems(links: Document[], key: Key, type: string) {
return links.map(link => {
let doc = link.GetT(key, Document);
- if (doc && doc != FieldWaiting) {
- return <LinkBox key={doc.Id} linkDoc={link} linkName={link.Title} pairedDoc={doc} showEditor={action(() => this._editingLink = link)} type={type} />
+ if (doc && doc !== FieldWaiting) {
+ return <LinkBox key={doc.Id} linkDoc={link} linkName={link.Title} pairedDoc={doc} showEditor={action(() => this._editingLink = link)} type={type} />;
}
- })
+ });
}
render() {
@@ -43,11 +43,11 @@ export class LinkMenu extends React.Component<Props> {
{this.renderLinkItems(linkFrom, KeyStore.LinkedFromDocs, "Source: ")}
</div>
</div>
- )
+ );
} else {
return (
<LinkEditor linkDoc={this._editingLink} showLinks={action(() => this._editingLink = undefined)}></LinkEditor>
- )
+ );
}
}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 7039b0c41..81ceb37f6 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -17,7 +17,7 @@ import { FieldView, FieldViewProps } from './FieldView';
import "./ImageBox.scss";
import "./PDFBox.scss";
import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here
-import React = require("react")
+import React = require("react");
import { SelectionManager } from "../../util/SelectionManager";
/** ALSO LOOK AT: Annotation.tsx, Sticky.tsx
@@ -55,7 +55,7 @@ import { SelectionManager } from "../../util/SelectionManager";
export class PDFBox extends React.Component<FieldViewProps> {
public static LayoutString() { return FieldView.LayoutString(PDFBox); }
- private _mainDiv = React.createRef<HTMLDivElement>()
+ private _mainDiv = React.createRef<HTMLDivElement>();
private _pdf = React.createRef<HTMLCanvasElement>();
@observable private _renderAsSvg = true;
@@ -72,7 +72,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
private _currTool: any; //keeps track of current tool button reference
private _drawToolOn: boolean = false; //boolean that keeps track of the drawing tool
- private _drawTool = React.createRef<HTMLButtonElement>()//drawing tool button reference
+ private _drawTool = React.createRef<HTMLButtonElement>();//drawing tool button reference
private _colorTool = React.createRef<HTMLButtonElement>(); //color button reference
private _currColor: string = "black"; //current color that user selected (for ink/pen)
@@ -85,18 +85,18 @@ export class PDFBox extends React.Component<FieldViewProps> {
@observable private _perPageInfo: Object[] = []; //stores pageInfo
@observable private _pageInfo: any = { area: [], divs: [], anno: [] }; //divs is array of objects linked to anno
- @observable private _currAnno: any = []
+ @observable private _currAnno: any = [];
@observable private _interactive: boolean = false;
@observable private _loaded: boolean = false;
- @computed private get curPage() { return this.props.doc.GetNumber(KeyStore.CurPage, 1); }
- @computed private get thumbnailPage() { return this.props.doc.GetNumber(KeyStore.ThumbnailPage, -1); }
+ @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, 1); }
+ @computed private get thumbnailPage() { return this.props.Document.GetNumber(KeyStore.ThumbnailPage, -1); }
componentDidMount() {
this._reactionDisposer = reaction(
() => [SelectionManager.SelectedDocuments().slice()],
() => {
- if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage != this.thumbnailPage && !this.props.isSelected()) {
+ if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage !== this.thumbnailPage && !this.props.isSelected()) {
this.saveThumbnail();
this._interactive = true;
}
@@ -167,25 +167,25 @@ export class PDFBox extends React.Component<FieldViewProps> {
let obj: Object = { parentDivs: [], spans: [] };
//@ts-ignore
- if (range.commonAncestorContainer.className == 'react-pdf__Page__textContent') { //multiline highlighting case
- obj = this.highlightNodes(range.commonAncestorContainer.childNodes)
+ if (range.commonAncestorContainer.className === 'react-pdf__Page__textContent') { //multiline highlighting case
+ obj = this.highlightNodes(range.commonAncestorContainer.childNodes);
} else { //single line highlighting case
- let parentDiv = range.commonAncestorContainer.parentElement
+ let parentDiv = range.commonAncestorContainer.parentElement;
if (parentDiv) {
- if (parentDiv.className == 'react-pdf__Page__textContent') { //when highlight is overwritten
- obj = this.highlightNodes(parentDiv.childNodes)
+ if (parentDiv.className === 'react-pdf__Page__textContent') { //when highlight is overwritten
+ obj = this.highlightNodes(parentDiv.childNodes);
} else {
parentDiv.childNodes.forEach((child) => {
- if (child.nodeName == 'SPAN') {
+ if (child.nodeName === 'SPAN') {
//@ts-ignore
- obj.parentDivs.push(parentDiv)
+ obj.parentDivs.push(parentDiv);
//@ts-ignore
- child.id = "highlighted"
+ child.id = "highlighted";
//@ts-ignore
- obj.spans.push(child)
+ obj.spans.push(child);
child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
}
- })
+ });
}
}
}
@@ -196,21 +196,21 @@ export class PDFBox extends React.Component<FieldViewProps> {
}
highlightNodes = (nodes: NodeListOf<ChildNode>) => {
- let temp = { parentDivs: [], spans: [] }
+ let temp = { parentDivs: [], spans: [] };
nodes.forEach((div) => {
div.childNodes.forEach((child) => {
- if (child.nodeName == 'SPAN') {
+ if (child.nodeName === 'SPAN') {
//@ts-ignore
- temp.parentDivs.push(div)
+ temp.parentDivs.push(div);
//@ts-ignore
- child.id = "highlighted"
+ child.id = "highlighted";
//@ts-ignore
- temp.spans.push(child)
+ temp.spans.push(child);
child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
}
- })
+ });
- })
+ });
return temp;
}
@@ -223,29 +223,29 @@ export class PDFBox extends React.Component<FieldViewProps> {
let index: any;
this._pageInfo.divs.forEach((obj: any) => {
obj.spans.forEach((element: any) => {
- if (element == span) {
+ if (element === span) {
if (!index) {
index = this._pageInfo.divs.indexOf(obj);
}
}
- })
- })
+ });
+ });
if (this._pageInfo.anno.length >= index + 1) {
- if (this._currAnno.length == 0) {
+ if (this._currAnno.length === 0) {
this._currAnno.push(this._pageInfo.anno[index]);
}
} else {
- if (this._currAnno.length == 0) { //if there are no current annotation
+ if (this._currAnno.length === 0) { //if there are no current annotation
let div = span.offsetParent;
//@ts-ignore
- let divX = div.style.left
+ let divX = div.style.left;
//@ts-ignore
- let divY = div.style.top
+ let divY = div.style.top;
//slicing "px" from the end
divX = divX.slice(0, divX.length - 2); //gets X of the DIV element (parent of Span)
divY = divY.slice(0, divY.length - 2); //gets Y of the DIV element (parent of Span)
- let annotation = <Annotation key={Utils.GenerateGuid()} Span={span} X={divX} Y={divY - 300} Highlights={this._pageInfo.divs} Annotations={this._pageInfo.anno} CurrAnno={this._currAnno} />
+ let annotation = <Annotation key={Utils.GenerateGuid()} Span={span} X={divX} Y={divY - 300} Highlights={this._pageInfo.divs} Annotations={this._pageInfo.anno} CurrAnno={this._currAnno} />;
this._pageInfo.anno.push(annotation);
this._currAnno.push(annotation);
}
@@ -263,7 +263,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
this.makeEditableAndHighlight(color);
}
} catch (ex) {
- this.makeEditableAndHighlight(color)
+ this.makeEditableAndHighlight(color);
}
}
}
@@ -305,7 +305,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
}
if (this._mainDiv.current) {
- let sticky = <Sticky key={Utils.GenerateGuid()} Height={height} Width={width} X={this.initX} Y={this.initY} />
+ let sticky = <Sticky key={Utils.GenerateGuid()} Height={height} Width={width} X={this.initX} Y={this.initY} />;
this._pageInfo.area.push(sticky);
}
this._toolOn = false;
@@ -317,7 +317,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
* starts drawing the line when user presses down.
*/
onDraw = () => {
- if (this._currTool != null) {
+ if (this._currTool !== null) {
this._currTool.style.backgroundColor = "grey";
}
@@ -342,13 +342,13 @@ export class PDFBox extends React.Component<FieldViewProps> {
* for changing color (for ink/pen)
*/
onColorChange = (e: React.PointerEvent) => {
- if (e.currentTarget.innerHTML == "Red") {
+ if (e.currentTarget.innerHTML === "Red") {
this._currColor = "red";
- } else if (e.currentTarget.innerHTML == "Blue") {
+ } else if (e.currentTarget.innerHTML === "Blue") {
this._currColor = "blue";
- } else if (e.currentTarget.innerHTML == "Green") {
+ } else if (e.currentTarget.innerHTML === "Green") {
this._currColor = "green";
- } else if (e.currentTarget.innerHTML == "Black") {
+ } else if (e.currentTarget.innerHTML === "Black") {
this._currColor = "black";
}
@@ -360,7 +360,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
*/
onHighlight = () => {
this._drawToolOn = false;
- if (this._currTool != null) {
+ if (this._currTool !== null) {
this._currTool.style.backgroundColor = "grey";
}
if (this._highlightTool.current) {
@@ -381,12 +381,12 @@ export class PDFBox extends React.Component<FieldViewProps> {
this._renderAsSvg = false;
setTimeout(() => {
var me = this;
- let nwidth = me.props.doc.GetNumber(KeyStore.NativeWidth, 0);
- let nheight = me.props.doc.GetNumber(KeyStore.NativeHeight, 0);
+ let nwidth = me.props.Document.GetNumber(KeyStore.NativeWidth, 0);
+ let nheight = me.props.Document.GetNumber(KeyStore.NativeHeight, 0);
htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 })
.then(action((dataUrl: string) => {
- me.props.doc.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField);
- me.props.doc.SetNumber(KeyStore.ThumbnailPage, me.props.doc.GetNumber(KeyStore.CurPage, -1));
+ me.props.Document.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField);
+ me.props.Document.SetNumber(KeyStore.ThumbnailPage, me.props.Document.GetNumber(KeyStore.CurPage, -1));
me._renderAsSvg = true;
}))
.catch(function (error: any) {
@@ -399,24 +399,24 @@ export class PDFBox extends React.Component<FieldViewProps> {
onLoaded = (page: any) => {
if (this._mainDiv.current) {
this._mainDiv.current.childNodes.forEach((element) => {
- if (element.nodeName == "DIV") {
+ if (element.nodeName === "DIV") {
element.childNodes[0].childNodes.forEach((e) => {
if (e instanceof HTMLCanvasElement) {
this._pdfCanvas = e;
- this._pdfContext = e.getContext("2d")
+ this._pdfContext = e.getContext("2d");
}
- })
+ });
}
- })
+ });
}
// bcz: the number of pages should really be set when the document is imported.
- this.props.doc.SetNumber(KeyStore.NumPages, page._transport.numPages);
- if (this._perPageInfo.length == 0) { //Makes sure it only runs once
- this._perPageInfo = [...Array(page._transport.numPages)]
+ this.props.Document.SetNumber(KeyStore.NumPages, page._transport.numPages);
+ if (this._perPageInfo.length === 0) { //Makes sure it only runs once
+ this._perPageInfo = [...Array(page._transport.numPages)];
}
this._loaded = true;
}
@@ -426,11 +426,11 @@ export class PDFBox extends React.Component<FieldViewProps> {
// bcz: the nativeHeight should really be set when the document is imported.
// also, the native dimensions could be different for different pages of the PDF
// so this design is flawed.
- var nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 0);
- if (!this.props.doc.GetNumber(KeyStore.NativeHeight, 0)) {
+ var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
+ if (!this.props.Document.GetNumber(KeyStore.NativeHeight, 0)) {
var nativeHeight = nativeWidth * r.entry.height / r.entry.width;
- this.props.doc.SetNumber(KeyStore.Height, nativeHeight / nativeWidth * this.props.doc.GetNumber(KeyStore.Width, 0));
- this.props.doc.SetNumber(KeyStore.NativeHeight, nativeHeight);
+ this.props.Document.SetNumber(KeyStore.Height, nativeHeight / nativeWidth * this.props.Document.GetNumber(KeyStore.Width, 0));
+ this.props.Document.SetNumber(KeyStore.NativeHeight, nativeHeight);
}
}
@@ -438,8 +438,8 @@ export class PDFBox extends React.Component<FieldViewProps> {
get pdfContent() {
let page = this.curPage;
const renderHeight = 2400;
- let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField);
- let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight;
+ let pdfUrl = this.props.Document.GetT(this.props.fieldKey, PDFField);
+ let xf = this.props.Document.GetNumber(KeyStore.NativeHeight, 0) / renderHeight;
return <div className="pdfBox-contentContainer" key="container" style={{ transform: `scale(${xf}, ${xf})` }}>
<Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`} renderMode={this._renderAsSvg ? "svg" : ""}>
<Measure onResize={this.setScaling}>
@@ -456,8 +456,8 @@ export class PDFBox extends React.Component<FieldViewProps> {
@computed
get pdfRenderer() {
let proxy = this._loaded ? (null) : this.imageProxyRenderer;
- let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField);
- if ((!this._interactive && proxy) || !pdfUrl || pdfUrl == FieldWaiting) {
+ let pdfUrl = this.props.Document.GetT(this.props.fieldKey, PDFField);
+ if ((!this._interactive && proxy) || !pdfUrl || pdfUrl === FieldWaiting) {
return proxy;
}
return [
@@ -470,9 +470,9 @@ export class PDFBox extends React.Component<FieldViewProps> {
@computed
get imageProxyRenderer() {
- let thumbField = this.props.doc.Get(KeyStore.Thumbnail);
+ let thumbField = this.props.Document.Get(KeyStore.Thumbnail);
if (thumbField) {
- let path = thumbField == FieldWaiting || this.thumbnailPage != this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
+ let path = thumbField === FieldWaiting || this.thumbnailPage !== this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
thumbField instanceof ImageField ? thumbField.Data.href : "http://cs.brown.edu/people/bcz/prairie.jpg";
return <img src={path} width="100%" />;
}
diff --git a/src/client/views/nodes/Sticky.tsx b/src/client/views/nodes/Sticky.tsx
index 4a4d69e90..11719831b 100644
--- a/src/client/views/nodes/Sticky.tsx
+++ b/src/client/views/nodes/Sticky.tsx
@@ -39,7 +39,7 @@ export class Sticky extends React.Component<IProps> {
document.addEventListener("pointermove", this.drawMove);
document.addEventListener("pointerup", this.drawUp);
}
- };
+ }
//when user drags
drawMove = (e: PointerEvent): void => {
@@ -49,7 +49,7 @@ export class Sticky extends React.Component<IProps> {
//connects the point
this.ctx.lineTo(x, y);
this.ctx.stroke();
- };
+ }
/**
* when user lifts the mouse, the drawing ends
@@ -58,7 +58,7 @@ export class Sticky extends React.Component<IProps> {
this.ctx.closePath();
console.log(this.ctx);
document.removeEventListener("pointermove", this.drawMove);
- };
+ }
render() {
return (
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 7c0db83a8..314af64c9 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
import { observer } from "mobx-react";
import { FieldWaiting, Opt } from '../../../fields/Field';
import { VideoField } from '../../../fields/VideoField';
@@ -13,14 +13,14 @@ import { number } from "prop-types";
export class VideoBox extends React.Component<FieldViewProps> {
private _reactionDisposer: Opt<IReactionDisposer>;
- private _videoRef = React.createRef<HTMLVideoElement>()
- public static LayoutString() { return FieldView.LayoutString(VideoBox) }
+ private _videoRef = React.createRef<HTMLVideoElement>();
+ public static LayoutString() { return FieldView.LayoutString(VideoBox); }
constructor(props: FieldViewProps) {
super(props);
}
- @computed private get curPage() { return this.props.doc.GetNumber(KeyStore.CurPage, -1); }
+ @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, -1); }
_loaded: boolean = false;
@@ -31,12 +31,12 @@ export class VideoBox extends React.Component<FieldViewProps> {
// bcz: the nativeHeight should really be set when the document is imported.
// also, the native dimensions could be different for different pages of the PDF
// so this design is flawed.
- var nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 0);
- var nativeHeight = this.props.doc.GetNumber(KeyStore.NativeHeight, 0);
+ var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
+ var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
var newNativeHeight = nativeWidth * r.entry.height / r.entry.width;
- if (!nativeHeight && newNativeHeight != nativeHeight && !isNaN(newNativeHeight)) {
- this.props.doc.SetNumber(KeyStore.Height, newNativeHeight / nativeWidth * this.props.doc.GetNumber(KeyStore.Width, 0));
- this.props.doc.SetNumber(KeyStore.NativeHeight, newNativeHeight);
+ if (!nativeHeight && newNativeHeight !== nativeHeight && !isNaN(newNativeHeight)) {
+ this.props.Document.SetNumber(KeyStore.Height, newNativeHeight / nativeWidth * this.props.Document.GetNumber(KeyStore.Width, 0));
+ this.props.Document.SetNumber(KeyStore.NativeHeight, newNativeHeight);
}
} else {
this._loaded = true;
@@ -50,15 +50,15 @@ export class VideoBox extends React.Component<FieldViewProps> {
@action
setVideoRef = (vref: HTMLVideoElement | null) => {
if (this.curPage >= 0 && vref) {
- vref!.currentTime = this.curPage;
- (vref! as any).AHackBecauseSomethingResetsTheVideoToZero = this.curPage;
+ vref.currentTime = this.curPage;
+ (vref as any).AHackBecauseSomethingResetsTheVideoToZero = this.curPage;
}
}
render() {
- let field = this.props.doc.GetT(this.props.fieldKey, VideoField);
+ let field = this.props.Document.GetT(this.props.fieldKey, VideoField);
if (!field || field === FieldWaiting) {
- return <div>Loading</div>
+ return <div>Loading</div>;
}
let path = field.Data.href;
trace();
@@ -73,6 +73,6 @@ export class VideoBox extends React.Component<FieldViewProps> {
</div>
}
</Measure>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 2ca8d49ce..90ce72c41 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1,9 +1,9 @@
import "./WebBox.scss";
-import React = require("react")
+import React = require("react");
import { WebField } from '../../../fields/WebField';
import { FieldViewProps, FieldView } from './FieldView';
import { FieldWaiting } from '../../../fields/Field';
-import { observer } from "mobx-react"
+import { observer } from "mobx-react";
import { computed } from 'mobx';
import { KeyStore } from '../../../fields/KeyStore';
@@ -16,11 +16,11 @@ export class WebBox extends React.Component<FieldViewProps> {
super(props);
}
- @computed get html(): string { return this.props.doc.GetHtml(KeyStore.Data, ""); }
+ @computed get html(): string { return this.props.Document.GetHtml(KeyStore.Data, ""); }
render() {
- let field = this.props.doc.Get(this.props.fieldKey);
- let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
+ let field = this.props.Document.Get(this.props.fieldKey);
+ let path = field === FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
field instanceof WebField ? field.Data.href : "https://crossorigin.me/" + "https://cs.brown.edu";
let content = this.html ?
@@ -33,6 +33,6 @@ export class WebBox extends React.Component<FieldViewProps> {
return (
<div className="webBox-cont" >
{content}
- </div>)
+ </div>);
}
} \ No newline at end of file