aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/DocumentDecorations.tsx47
-rw-r--r--src/client/views/EditableView.tsx4
-rw-r--r--src/client/views/InkingCanvas.tsx14
-rw-r--r--src/client/views/InkingControl.tsx4
-rw-r--r--src/client/views/InkingStroke.tsx4
-rw-r--r--src/client/views/Main.tsx32
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx166
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx42
-rw-r--r--src/client/views/collections/CollectionPDFView.tsx45
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx74
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx25
-rw-r--r--src/client/views/collections/CollectionVideoView.tsx46
-rw-r--r--src/client/views/collections/CollectionView.tsx178
-rw-r--r--src/client/views/collections/CollectionViewBase.tsx57
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx22
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx17
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx98
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx14
-rw-r--r--src/client/views/collections/collectionFreeForm/PreviewCursor.tsx2
-rw-r--r--src/client/views/nodes/Annotation.tsx108
-rw-r--r--src/client/views/nodes/AudioBox.tsx4
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx12
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx43
-rw-r--r--src/client/views/nodes/DocumentView.tsx120
-rw-r--r--src/client/views/nodes/FieldView.tsx55
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx16
-rw-r--r--src/client/views/nodes/ImageBox.tsx10
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx15
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx23
-rw-r--r--src/client/views/nodes/LinkBox.tsx2
-rw-r--r--src/client/views/nodes/LinkMenu.tsx2
-rw-r--r--src/client/views/nodes/PDFBox.tsx66
-rw-r--r--src/client/views/nodes/VideoBox.tsx18
-rw-r--r--src/client/views/nodes/WebBox.tsx6
34 files changed, 709 insertions, 682 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c7e4a269a..deed0fa7c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -55,15 +55,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
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") {
+ // 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"
@@ -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);
@@ -217,7 +211,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
}
onLinkerButtonMoved = (e: PointerEvent): void => {
- if (this._linkerButton.current != null) {
+ if (this._linkerButton.current !== null) {
document.removeEventListener("pointermove", this.onLinkerButtonMoved)
document.removeEventListener("pointerup", this.onLinkerButtonUp)
let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
@@ -246,25 +240,24 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
}
onLinkButtonMoved = async (e: PointerEvent) => {
- if (this._linkButton.current != null) {
+ 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 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);
DragManager.StartDocumentDrag([this._linkButton.current], dragData, e.x, e.y, {
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 29bf6add7..982aacdea 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -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;
}
}
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 45ca52d00..4b3ea48c5 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -56,7 +56,7 @@ 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);
@@ -64,7 +64,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
e.stopPropagation();
e.preventDefault();
- if (InkingControl.Instance.selectedTool != InkTool.Eraser) {
+ 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, {
@@ -94,7 +94,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
onPointerMove = (e: PointerEvent): void => {
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) {
@@ -121,7 +121,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
get drawnPaths() {
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}
@@ -131,16 +131,16 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
}, [] 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} />
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index c1519dff8..13f0a0acc 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -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);
}
}
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 615f8af7e..12b15a3f0 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -30,7 +30,7 @@ export class InkingStroke extends React.Component<StrokeProps> {
}
parseData = (line: Array<{ x: number, y: number }>): string => {
- return !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ");
+ return !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ")
}
createStyle() {
@@ -49,7 +49,7 @@ 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} />
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index c9467e130..9868f6c74 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -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';
@@ -48,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) {
@@ -70,7 +71,7 @@ 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];
}
};
@@ -190,15 +191,12 @@ 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) => { }
@@ -222,7 +220,7 @@ export class Main extends React.Component {
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} doc={this._textDoc} isSelected={() => true} select={() => { }} isTopMost={true} selectOnLoad={true} bindings={undefined} />
+ <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);
@@ -232,15 +230,17 @@ export class Main extends React.Component {
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}
+ parentActive={returnTrue}
+ onActiveChanged={emptyFunction}
ContainingCollectionView={undefined} />
}
@@ -385,8 +385,8 @@ export class Main extends React.Component {
}
}
-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..7a5ab6e3c
--- /dev/null
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -0,0 +1,166 @@
+import * as React from 'react';
+import { FieldViewProps } from '../nodes/FieldView';
+import { KeyStore } from '../../../fields/KeyStore';
+import { NumberField } from '../../../fields/NumberField';
+import { FieldWaiting, Field, FieldValue } from '../../../fields/Field';
+import { ContextMenu } from '../ContextMenu';
+import { SelectionManager } from '../../util/SelectionManager';
+import { Document } from '../../../fields/Document';
+import { ListField } from '../../../fields/ListField';
+import { action } from 'mobx';
+import { Transform } from '../../util/Transform';
+import { observer } from 'mobx-react';
+
+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)) {
+ props.Document.SetOnPrototype(props.fieldKey, new ListField([doc]));
+ }
+ 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..6640c843e 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -8,12 +8,12 @@ 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 { ServerUtils } from "../../../server/ServerUtil";
@@ -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,7 +124,7 @@ 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);
@@ -154,7 +154,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,7 +193,7 @@ 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;
@@ -209,7 +209,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
})
}));
}
- 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()) {
@@ -227,12 +227,12 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
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;
}
})
@@ -296,9 +296,9 @@ 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!);
@@ -311,14 +311,16 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
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>
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 4d2daf149..1f2e71f6e 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -1,22 +1,20 @@
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 React = require("react");
-import { FieldId } from "../../../fields/Field";
+import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
+import { FieldView } from "../nodes/FieldView";
+import { CollectionRenderProps, CollectionBaseView, CollectionViewType } from "./CollectionBaseView";
@observer
export class CollectionPDFView extends React.Component<CollectionViewProps> {
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); }
@@ -30,30 +28,31 @@ export class CollectionPDFView extends React.Component<CollectionViewProps> {
<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 = { ...renderProps, ...this.props };
+ 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..4604945d1 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -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 { CollectionView } from "./CollectionView";
import { CollectionViewBase } from "./CollectionViewBase";
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
@@ -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;
@@ -103,13 +108,13 @@ 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();
}
@@ -120,7 +125,7 @@ export class CollectionSchemaView extends CollectionViewBase {
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" } });
@@ -155,8 +160,8 @@ export class CollectionSchemaView extends CollectionViewBase {
}
}),
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"
}
};
}
@@ -184,8 +189,8 @@ export class CollectionSchemaView extends CollectionViewBase {
@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);
}
}
@@ -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,12 +248,8 @@ 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) => { }
@@ -299,28 +300,30 @@ 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) :
+ let dividerDragger = this.splitPercentage === 0 ? (null) :
<div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />
//options button and menu
@@ -330,12 +333,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>
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 0b12f11fd..dce35868e 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 { CollectionView } from "./CollectionView";
import { CollectionViewBase } from "./CollectionViewBase";
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;
@@ -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"}
@@ -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;
}
@@ -122,7 +135,7 @@ 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 (
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 470a853e3..afadfeefb 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -3,11 +3,14 @@ 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 { CollectionView } from "./CollectionView";
+import { CollectionViewType, CollectionBaseView, CollectionRenderProps } from "./CollectionBaseView";
import { CollectionViewProps } from "./CollectionViewBase";
import React = require("react");
import { FieldId } from "../../../fields/Field";
import "./CollectionVideoView.scss"
+import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
+import { FieldView } from "../nodes/FieldView";
@observer
@@ -19,9 +22,7 @@ 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]);
@@ -42,7 +43,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 +61,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 +102,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 = { ...renderProps, ...this.props };
+ 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..1b0cfd57b 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,159 +1,45 @@
-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';
@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;
+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);
}
- 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
+ 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: () => 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) })
}
}
- 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} />)
- }
- 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/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 7cf49e215..84d378e1c 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -17,27 +17,15 @@ 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";
-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]>;
@@ -87,9 +75,14 @@ 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) {
+ 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;
@@ -98,11 +91,11 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document;
if (sourceDoc) runInAction(() => {
let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
- if (srcTarg && srcTarg != FieldWaiting) {
+ 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) {
+ if (targDoc && targDoc !== FieldWaiting) {
let dropdoc = targDoc.MakeDelegate();
de.data.droppedDocuments.push(dropdoc);
this.props.addDocument(dropdoc, false);
@@ -154,8 +147,6 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
@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");
@@ -165,7 +156,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
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,10 +164,11 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
return;
}
+ // 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) {
+ 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) => {
let type = res.headers["content-type"];
@@ -191,7 +183,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
}))
}
let type = item.type
- if (item.kind == "file") {
+ if (item.kind === "file") {
let file = item.getAsFile();
let formData = new FormData()
@@ -202,19 +194,18 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
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
runInAction(() => {
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);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 1189dd4e8..abc6cecff 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -31,17 +31,17 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
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)
+ 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)
+ return (bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false)
});
let brushAction = (field: ListField<Document>) => {
let found = findBrush(field);
- if (found != -1) {
+ if (found !== -1) {
console.log("REMOVE BRUSH " + srcTarg.Title + " " + dstTarg.Title);
field.Data.splice(found, 1);
}
@@ -53,9 +53,9 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
brushAction = brushAction = (field: ListField<Document>) => {
- if (findBrush(field) == -1) {
+ if (findBrush(field) === -1) {
console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title);
- (findBrush(field) == -1) && field.Data.push(linkDoc);
+ (findBrush(field) === -1) && field.Data.push(linkDoc);
}
};
}
@@ -69,10 +69,10 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
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
@@ -84,14 +84,14 @@ 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
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index 19382e66f..f664f4e65 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 "../CollectionViewBase";
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";
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2a86d0ee1..d542b8bc2 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -11,7 +11,7 @@ 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 { COLLECTION_BORDER_WIDTH } from "../CollectionBaseView";
import { CollectionViewBase } from "../CollectionViewBase";
import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView";
import "./CollectionFreeFormView.scss";
@@ -20,6 +20,8 @@ import React = require("react");
import v5 = require("uuid/v5");
import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
import { PreviewCursor } from "./PreviewCursor";
+import { DocumentManager } from "../../../util/DocumentManager";
+import { SelectionManager } from "../../../util/SelectionManager";
import { NumberField } from "../../../../fields/NumberField";
import { Main } from "../../Main";
@@ -41,15 +43,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;
@@ -61,6 +68,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
@observable private _lastX: number = 0;
@observable private _lastY: number = 0;
+ private outerElement?: HTMLDivElement;
+
@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); }
@@ -68,38 +77,40 @@ export class CollectionFreeFormView extends CollectionViewBase {
@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.outerElement ? this.outerElement.clientWidth / 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.outerElement ? this.outerElement.clientHeight / 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,7 +126,7 @@ 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);
@@ -137,7 +148,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,8 +177,8 @@ 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));
@@ -244,16 +255,19 @@ 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,
}
}
@@ -262,7 +276,7 @@ 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[])
@@ -283,7 +297,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
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);
+ getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.scale).translate(this.panX, this.panY);
noScaling = () => 1;
childViews = () => this.views;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index df150a045..704db1d4a 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -48,7 +48,7 @@ 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;
@@ -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;
}
@@ -99,15 +99,15 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
@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,
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
index 93c98f7b0..599461f85 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;
diff --git a/src/client/views/nodes/Annotation.tsx b/src/client/views/nodes/Annotation.tsx
index a2c7be1a8..e4f17940c 100644
--- a/src/client/views/nodes/Annotation.tsx
+++ b/src/client/views/nodes/Annotation.tsx
@@ -4,13 +4,13 @@ import { observer } from "mobx-react"
import { observable, action } from 'mobx';
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"){
+ 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"){
+ } else if (e.currentTarget.innerHTML === "b") {
this.props.Span.style.backgroundColor = "rgba(0,255, 255, 0.3)"
- } else if (e.currentTarget.innerHTML == "y"){
+ } else if (e.currentTarget.innerHTML === "y") {
this.props.Span.style.backgroundColor = "rgba(255,255,0, 0.3)"
- } else if (e.currentTarget.innerHTML == "g"){
+ } 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.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..1bd934c25 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -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 (
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 1a0f0cbbd..dcf82ccd4 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -52,14 +52,12 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
this.props.Document.SetData(KeyStore.ZIndex, h, NumberField)
}
- contentScaling = () => {
- return this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
- }
+ 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() {
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 77551649c..34cc326aa 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;
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7514e782d..ab9cd2d53 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,60 +80,20 @@ 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;
@@ -159,20 +123,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 +140,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 +153,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,7 +173,7 @@ 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);
}
}
@@ -261,17 +196,14 @@ export class DocumentView extends React.Component<DocumentViewProps> {
};
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 => {
@@ -438,9 +370,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
);
};
- isSelected = () => {
- return SelectionManager.IsSelected(this);
- };
+ isSelected = () => SelectionManager.IsSelected(this)
select = (ctrlPressed: boolean) => {
SelectionManager.SelectDoc(this, ctrlPressed);
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 4e83ec7b9..d9422ae9b 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -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,23 +29,29 @@ 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() {
@@ -68,26 +75,28 @@ export class FieldView extends React.Component<FieldViewProps> {
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(", ")}
+ {(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
@@ -97,7 +106,7 @@ export class FieldView extends React.Component<FieldViewProps> {
else if (field instanceof NumberField) {
return <p>{field.Data}</p>
}
- else if (field != FieldWaiting) {
+ else if (field !== FieldWaiting) {
return <p>{JSON.stringify(field.GetValue())}</p>
}
else
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index e59179874..ebac61c78 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -63,7 +63,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
}
};
- get FieldDoc() { return this.props.fieldKey === KeyStore.Archives ? Main.Instance._textDoc! : this.props.doc; }
+ 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() {
@@ -92,7 +92,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
this._reactionDisposer = reaction(
() => {
const field = this.FieldDoc.GetT(this.FieldKey, RichTextField);
- return field && field != FieldWaiting ? field.Data : undefined;
+ return field && field !== FieldWaiting ? field.Data : undefined;
},
field => {
if (field && this._editorView) {
@@ -109,7 +109,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
let state: EditorState;
let field = this.FieldDoc.GetT(this.FieldKey, RichTextField);
- if (field && field != FieldWaiting && field.Data) {
+ if (field && field !== FieldWaiting && field.Data) {
state = EditorState.fromJSON(config, JSON.parse(field.Data));
} else {
state = EditorState.create(config);
@@ -122,7 +122,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
}
if (this.props.selectOnLoad) {
- this.props.select();
+ this.props.select(false);
this._editorView!.focus();
}
}
@@ -145,8 +145,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
@action
onChange(e: React.ChangeEvent<HTMLInputElement>) {
- const { fieldKey, doc } = this.props;
- doc.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
+ 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 => {
@@ -162,13 +162,13 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
}
if (this.props.fieldKey !== KeyStore.Archives) {
e.preventDefault();
- Main.Instance.SetTextDoc(this.props.doc, this._ref.current!);
+ 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.doc, this._ref.current!);
+ Main.Instance.SetTextDoc(this.props.Document, this._ref.current!);
}
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 60d1f7214..c5f29f7b0 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -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() {
@@ -91,7 +91,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
}
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({
@@ -103,10 +103,10 @@ export class ImageBox extends React.Component<FieldViewProps> {
}
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} />
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 9bd6c1052..8a7f32e6d 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -32,10 +32,10 @@ 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) {
+ let doc = this.props.Document.GetT(KeyStore.Data, Document);
+ if (!doc || doc === FieldWaiting) {
return
}
let realDoc = doc;
@@ -71,8 +71,8 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
}
createTable = () => {
- let doc = this.props.doc.GetT(KeyStore.Data, Document);
- if (!doc || doc == FieldWaiting) {
+ let doc = this.props.Document.GetT(KeyStore.Data, Document);
+ if (!doc || doc === FieldWaiting) {
return <tr><td>Loading...</td></tr>
}
let realDoc = doc;
@@ -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}>
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 5647f45bf..c6a0a7296 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -11,6 +11,8 @@ import { Key } from '../../../fields/Key';
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
@@ -43,13 +45,16 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
}
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,12 +89,12 @@ 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;
}
}
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index e81f8fec7..4791d6029 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -49,7 +49,7 @@ 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) {
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index 5eeb40772..6c2d24630 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -24,7 +24,7 @@ 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) {
+ if (doc && doc !== FieldWaiting) {
return <LinkBox key={doc.Id} linkDoc={link} linkName={link.Title} pairedDoc={doc} showEditor={action(() => this._editingLink = link)} type={type} />
}
})
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 7039b0c41..774d9be3e 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -89,14 +89,14 @@ export class PDFBox extends React.Component<FieldViewProps> {
@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,16 +167,16 @@ 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
+ 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
if (parentDiv) {
- if (parentDiv.className == 'react-pdf__Page__textContent') { //when highlight is overwritten
+ 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)
//@ts-ignore
@@ -199,7 +199,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
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)
//@ts-ignore
@@ -223,7 +223,7 @@ 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);
}
@@ -232,11 +232,11 @@ export class PDFBox extends React.Component<FieldViewProps> {
})
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
@@ -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,7 +399,7 @@ 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) {
@@ -414,8 +414,8 @@ export class PDFBox extends React.Component<FieldViewProps> {
}
// 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.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/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 7c0db83a8..a08b320e8 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -20,7 +20,7 @@ export class VideoBox extends React.Component<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,13 +50,13 @@ 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>
}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 2ca8d49ce..c1d389001 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -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 ?