aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts12
-rw-r--r--src/client/Server.ts52
-rw-r--r--src/client/SocketStub.ts2
-rw-r--r--src/client/documents/Documents.ts3
-rw-r--r--src/client/northstar/dash-nodes/HistogramBox.tsx14
-rw-r--r--src/client/northstar/manager/Gateway.ts24
-rw-r--r--src/client/util/DocumentManager.ts14
-rw-r--r--src/client/util/DragManager.ts62
-rw-r--r--src/client/util/Scripting.ts14
-rw-r--r--src/client/util/SelectionManager.ts19
-rw-r--r--src/client/util/Transform.ts42
-rw-r--r--src/client/util/TypedEvent.ts4
-rw-r--r--src/client/util/UndoManager.ts4
-rw-r--r--src/client/util/type_decls.d2
-rw-r--r--src/client/views/DocumentDecorations.tsx10
-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.tsx25
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx166
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx12
-rw-r--r--src/client/views/collections/CollectionPDFView.tsx43
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx74
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx22
-rw-r--r--src/client/views/collections/CollectionVideoView.tsx42
-rw-r--r--src/client/views/collections/CollectionView.tsx176
-rw-r--r--src/client/views/collections/CollectionViewBase.tsx53
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx18
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx17
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx94
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx2
-rw-r--r--src/client/views/nodes/AudioBox.tsx2
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx12
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx41
-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.tsx266
-rw-r--r--src/client/views/nodes/ImageBox.tsx10
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx9
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx23
-rw-r--r--src/client/views/nodes/PDFBox.tsx66
-rw-r--r--src/client/views/nodes/VideoBox.tsx16
-rw-r--r--src/client/views/nodes/WebBox.tsx4
-rw-r--r--src/debug/Viewer.tsx6
-rw-r--r--src/fields/Document.ts37
-rw-r--r--src/fields/Field.ts4
-rw-r--r--src/fields/WebField.ts2
-rw-r--r--src/mobile/ImageUpload.tsx55
-rw-r--r--src/server/authentication/controllers/WorkspacesMenu.tsx2
-rw-r--r--src/server/authentication/controllers/user_controller.ts12
-rw-r--r--src/server/index.ts10
-rw-r--r--src/server/public/files/upload_a6a70d84ebb65febf7900e29f52cc86d.pdfbin1043556 -> 0 bytes
53 files changed, 897 insertions, 903 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index a5d9bd0ca..8bd7f2f5c 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -18,7 +18,7 @@ export class Utils {
return { scale: 1, translateX: 1, translateY: 1 }
}
const rect = ele.getBoundingClientRect();
- const scale = ele.offsetWidth == 0 && rect.width == 0 ? 1 : rect.width / ele.offsetWidth;
+ const scale = ele.offsetWidth === 0 && rect.width === 0 ? 1 : rect.width / ele.offsetWidth;
const translateX = rect.left;
const translateY = rect.top;
@@ -86,4 +86,14 @@ export class Utils {
}
}
+export function returnTrue() {
+ return true;
+}
+
+export function returnFalse() {
+ return false;
+}
+
+export function emptyFunction() { }
+
export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; \ No newline at end of file
diff --git a/src/client/Server.ts b/src/client/Server.ts
index 37e3c2c0d..45c7144ca 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -21,11 +21,11 @@ export class Server {
let fn = (cb: (field: Opt<Field>) => void) => {
let cached = this.ClientFieldsCached.get(fieldid);
- if (!cached) {
+ if (cached === undefined) {
this.ClientFieldsCached.set(fieldid, FieldWaiting);
SocketStub.SEND_FIELD_REQUEST(fieldid, action((field: Field | undefined) => {
let cached = this.ClientFieldsCached.get(fieldid);
- if (cached != FieldWaiting)
+ if (cached !== FieldWaiting)
cb(cached);
else {
if (field) {
@@ -36,23 +36,22 @@ export class Server {
cb(field)
}
}));
- } else if (cached != FieldWaiting) {
+ } else if (cached !== FieldWaiting) {
setTimeout(() => cb(cached as Field), 0);
} else {
- reaction(() => {
- return this.ClientFieldsCached.get(fieldid);
- }, (field, reaction) => {
- if (field !== "<Waiting>") {
- reaction.dispose()
- cb(field)
- }
- })
+ reaction(() => this.ClientFieldsCached.get(fieldid),
+ (field, reaction) => {
+ if (field !== FieldWaiting) {
+ reaction.dispose()
+ cb(field)
+ }
+ })
}
}
if (callback) {
fn(callback);
} else {
- return new Promise(res => fn(res));
+ return new Promise(fn);
}
}
@@ -92,24 +91,23 @@ export class Server {
}
}
}
- reaction(() => {
- return waitingFieldIds.map(id => this.ClientFieldsCached.get(id));
- }, (cachedFields, reaction) => {
- if (!cachedFields.some(field => !field || field === FieldWaiting)) {
- reaction.dispose();
- for (let field of cachedFields) {
- let realField = field as Field;
- existingFields[realField.Id] = realField;
+ reaction(() => waitingFieldIds.map(id => this.ClientFieldsCached.get(id)),
+ (cachedFields, reaction) => {
+ if (!cachedFields.some(field => !field)) {
+ reaction.dispose();
+ for (let field of cachedFields) {
+ let realField = field as Field;
+ existingFields[realField.Id] = realField;
+ }
+ cb({ ...fields, ...existingFields })
}
- cb({ ...fields, ...existingFields })
- }
- }, { fireImmediately: true })
+ }, { fireImmediately: true })
}));
};
if (callback) {
fn(callback);
} else {
- return new Promise(res => fn(res));
+ return new Promise(fn);
}
}
@@ -153,19 +151,19 @@ export class Server {
@action
private static cacheField(clientField: Field) {
var cached = this.ClientFieldsCached.get(clientField.Id);
- if (!cached || cached == FieldWaiting) {
+ if (!cached) {
this.ClientFieldsCached.set(clientField.Id, clientField);
} else {
// probably should overwrite the values within any field that was already here...
}
- return this.ClientFieldsCached.get(clientField.Id) as Field;
+ return this.ClientFieldsCached.get(clientField.Id);
}
@action
static updateField(field: { _id: string, data: any, type: Types }) {
if (Server.ClientFieldsCached.has(field._id)) {
var f = Server.ClientFieldsCached.get(field._id);
- if (f && f != FieldWaiting) {
+ if (f) {
// console.log("Applying : " + field._id);
f.UpdateFromServer(field.data);
f.init(() => { });
diff --git a/src/client/SocketStub.ts b/src/client/SocketStub.ts
index 5045037c5..c3cd8bee6 100644
--- a/src/client/SocketStub.ts
+++ b/src/client/SocketStub.ts
@@ -55,7 +55,7 @@ export class SocketStub {
if (callback) {
fn(callback);
} else {
- return new Promise(res => fn(res))
+ return new Promise(fn)
}
}
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1f0744782..1b1485c12 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -17,7 +17,8 @@ import { HistogramOperation } from "../northstar/operations/HistogramOperation";
import { Server } from "../Server";
import { CollectionPDFView } from "../views/collections/CollectionPDFView";
import { CollectionVideoView } from "../views/collections/CollectionVideoView";
-import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
+import { CollectionView } from "../views/collections/CollectionView";
+import { CollectionViewType } from "../views/collections/CollectionBaseView";
import { AudioBox } from "../views/nodes/AudioBox";
import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
import { ImageBox } from "../views/nodes/ImageBox";
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index 49ebe5ebc..5938bf9b1 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -117,14 +117,14 @@ export class HistogramBox extends React.Component<FieldViewProps> {
activateHistogramOperation(catalog?: Catalog) {
if (catalog) {
- this.props.doc.GetTAsync(this.props.fieldKey, HistogramField).then((histoOp: Opt<HistogramField>) => runInAction(() => {
+ this.props.Document.GetTAsync(this.props.fieldKey, HistogramField).then((histoOp: Opt<HistogramField>) => runInAction(() => {
this.HistoOp = histoOp ? histoOp.Data : HistogramOperation.Empty;
if (this.HistoOp != HistogramOperation.Empty) {
- reaction(() => this.props.doc.GetList(KeyStore.LinkedFromDocs, []), (docs: Document[]) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true });
- reaction(() => this.props.doc.GetList(KeyStore.BrushingDocs, []).length,
+ reaction(() => this.props.Document.GetList(KeyStore.LinkedFromDocs, []), (docs: Document[]) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true });
+ reaction(() => this.props.Document.GetList(KeyStore.BrushingDocs, []).length,
() => {
- let brushingDocs = this.props.doc.GetList(KeyStore.BrushingDocs, [] as Document[]);
- let proto = this.props.doc.GetPrototype() as Document;
+ let brushingDocs = this.props.Document.GetList(KeyStore.BrushingDocs, [] as Document[]);
+ let proto = this.props.Document.GetPrototype() as Document;
this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...brushingDocs.map((brush, i) => {
brush.SetNumber(KeyStore.BackgroundColor, StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]);
let brushed = brush.GetList(KeyStore.BrushingDocs, [] as Document[]);
@@ -139,8 +139,8 @@ export class HistogramBox extends React.Component<FieldViewProps> {
render() {
let labelY = this.HistoOp && this.HistoOp.Y ? this.HistoOp.Y.PresentedName : "<...>";
let labelX = this.HistoOp && this.HistoOp.X ? this.HistoOp.X.PresentedName : "<...>";
- var h = this.props.isTopMost ? this.PanelHeight : this.props.doc.GetNumber(KeyStore.Height, 0);
- var w = this.props.isTopMost ? this.PanelWidth : this.props.doc.GetNumber(KeyStore.Width, 0);
+ var h = this.props.isTopMost ? this.PanelHeight : this.props.Document.GetNumber(KeyStore.Height, 0);
+ var w = this.props.isTopMost ? this.PanelWidth : this.props.Document.GetNumber(KeyStore.Width, 0);
let loff = this.SizeConverter.LeftOffset;
let toff = this.SizeConverter.TopOffset;
let roff = this.SizeConverter.RightOffset;
diff --git a/src/client/northstar/manager/Gateway.ts b/src/client/northstar/manager/Gateway.ts
index 5ae5e4f47..3e72a50ae 100644
--- a/src/client/northstar/manager/Gateway.ts
+++ b/src/client/northstar/manager/Gateway.ts
@@ -246,18 +246,18 @@ export class Settings {
else {
this.ServerUrl = environment["SERVER_URL"] ? environment["SERVER_URL"] : document.URL;
}*/
- this.ServerUrl = environment["SERVER_URL"] ? environment["SERVER_URL"] : document.URL;
- this.ServerApiPath = environment["SERVER_API_PATH"];
- this.SampleSize = environment["SAMPLE_SIZE"];
- this.XBins = environment["X_BINS"];
- this.YBins = environment["Y_BINS"];
- this.SplashTimeInMS = environment["SPLASH_TIME_IN_MS"];
- this.ShowFpsCounter = environment["SHOW_FPS_COUNTER"];
- this.ShowShutdownButton = environment["SHOW_SHUTDOWN_BUTTON"];
- this.IsMenuFixed = environment["IS_MENU_FIXED"];
- this.IsDarpa = environment["IS_DARPA"];
- this.IsIGT = environment["IS_IGT"];
- this.DegreeOfParallelism = environment["DEGREE_OF_PARALLISM"];
+ this.ServerUrl = environment.SERVER_URL ? environment.SERVER_URL : document.URL;
+ this.ServerApiPath = environment.SERVER_API_PATH;
+ this.SampleSize = environment.SAMPLE_SIZE;
+ this.XBins = environment.X_BINS;
+ this.YBins = environment.Y_BINS;
+ this.SplashTimeInMS = environment.SPLASH_TIME_IN_MS;
+ this.ShowFpsCounter = environment.SHOW_FPS_COUNTER;
+ this.ShowShutdownButton = environment.SHOW_SHUTDOWN_BUTTON;
+ this.IsMenuFixed = environment.IS_MENU_FIXED;
+ this.IsDarpa = environment.IS_DARPA;
+ this.IsIGT = environment.IS_IGT;
+ this.DegreeOfParallelism = environment.DEGREE_OF_PARALLISM;
}
public static get Instance(): Settings {
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index bf59fbb43..fb489edb6 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -29,7 +29,7 @@ export class DocumentManager {
public getAllDocumentViews(collection: Document) {
return this.DocumentViews.filter(dv =>
- dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document == collection);
+ dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document === collection);
}
public getDocumentView(toFind: Document): DocumentView | null {
@@ -42,12 +42,12 @@ export class DocumentManager {
let doc = view.props.Document;
// if (view.props.ContainingCollectionView instanceof CollectionFreeFormView) {
- if (Object.is(doc, toFind)) {
+ if (doc === toFind) {
toReturn = view;
return;
}
let docSrc = doc.GetT(KeyStore.Prototype, Document);
- if (docSrc && docSrc != FieldWaiting && Object.is(docSrc, toFind)) {
+ if (docSrc && docSrc !== FieldWaiting && Object.is(docSrc, toFind)) {
toReturn = view;
}
})
@@ -63,11 +63,11 @@ export class DocumentManager {
let doc = view.props.Document;
// if (view.props.ContainingCollectionView instanceof CollectionFreeFormView) {
- if (Object.is(doc, toFind)) {
+ if (doc === toFind) {
toReturn.push(view);
} else {
let docSrc = doc.GetT(KeyStore.Prototype, Document);
- if (docSrc && docSrc != FieldWaiting && Object.is(docSrc, toFind)) {
+ if (docSrc && docSrc !== FieldWaiting && Object.is(docSrc, toFind)) {
toReturn.push(view);
}
}
@@ -80,11 +80,11 @@ export class DocumentManager {
public get LinkedDocumentViews() {
return DocumentManager.Instance.DocumentViews.reduce((pairs, dv) => {
let linksList = dv.props.Document.GetT(KeyStore.LinkedToDocs, ListField);
- if (linksList && linksList != FieldWaiting && linksList.Data.length) {
+ if (linksList && linksList !== FieldWaiting && linksList.Data.length) {
pairs.push(...linksList.Data.reduce((pairs, link) => {
if (link instanceof Document) {
let linkToDoc = link.GetT(KeyStore.LinkedToDocs, Document);
- if (linkToDoc && linkToDoc != FieldWaiting) {
+ if (linkToDoc && linkToDoc !== FieldWaiting) {
DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => {
pairs.push({ a: dv, b: docView1, l: link })
})
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index e8f8cce7c..02e0a18df 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -6,33 +6,26 @@ import { ImageField } from "../../fields/ImageField";
import { KeyStore } from "../../fields/KeyStore";
import { CollectionView } from "../views/collections/CollectionView";
import { DocumentView } from "../views/nodes/DocumentView";
+import { returnFalse } from "../../Utils";
-export function setupDrag(
- _reference: React.RefObject<HTMLDivElement>,
- docFunc: () => Document,
- removeFunc: (containingCollection: CollectionView) => void = () => { }
-) {
- let onRowMove = action(
- (e: PointerEvent): void => {
- e.stopPropagation();
- e.preventDefault();
+export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction) {
+ let onRowMove = action((e: PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
- document.removeEventListener("pointermove", onRowMove);
- document.removeEventListener("pointerup", onRowUp);
- var dragData = new DragManager.DocumentDragData([docFunc()]);
- dragData.removeDocument = removeFunc;
- DragManager.StartDocumentDrag([_reference.current!], dragData);
- }
- );
- let onRowUp = action(
- (e: PointerEvent): void => {
- document.removeEventListener("pointermove", onRowMove);
- document.removeEventListener("pointerup", onRowUp);
- }
- );
+ document.removeEventListener("pointermove", onRowMove);
+ document.removeEventListener('pointerup', onRowUp);
+ var dragData = new DragManager.DocumentDragData([docFunc()]);
+ dragData.moveDocument = moveFunc;
+ DragManager.StartDocumentDrag([_reference.current!], dragData);
+ });
+ let onRowUp = action((e: PointerEvent): void => {
+ document.removeEventListener("pointermove", onRowMove);
+ document.removeEventListener('pointerup', onRowUp);
+ });
let onItemDown = (e: React.PointerEvent) => {
// if (this.props.isSelected() || this.props.isTopMost) {
- if (e.button == 0) {
+ if (e.button === 0) {
e.stopPropagation();
if (e.shiftKey) {
CollectionDockingView.Instance.StartOtherDrag([docFunc()], e);
@@ -103,7 +96,7 @@ export namespace DragManager {
"Element is already droppable, can't make it droppable again"
);
}
- element.dataset["canDrop"] = "true";
+ element.dataset.canDrop = "true";
const handler = (e: Event) => {
const ce = e as CustomEvent<DropEvent>;
options.handlers.drop(e, ce.detail);
@@ -111,10 +104,11 @@ export namespace DragManager {
element.addEventListener("dashOnDrop", handler);
return () => {
element.removeEventListener("dashOnDrop", handler);
- delete element.dataset["canDrop"];
+ delete element.dataset.canDrop
};
}
+ export type MoveFunction = (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
export class DocumentDragData {
constructor(dragDoc: Document[]) {
this.draggedDocuments = dragDoc;
@@ -125,7 +119,7 @@ export namespace DragManager {
xOffset?: number;
yOffset?: number;
aliasOnDrop?: boolean;
- removeDocument?: (collectionDrop: CollectionView) => void;
+ moveDocument?: MoveFunction;
[id: string]: any;
}
@@ -214,11 +208,11 @@ export namespace DragManager {
let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
if (pdfBox && pdfBox.childElementCount && thumbnail) {
let img = new Image();
- img!.src = thumbnail.toString();
- img!.style.position = "absolute";
- img!.style.width = `${rect.width / scaleX}px`;
- img!.style.height = `${rect.height / scaleY}px`;
- pdfBox.replaceChild(img!, pdfBox.children[0]);
+ img.src = thumbnail.toString();
+ img.style.position = "absolute";
+ img.style.width = `${rect.width / scaleX}px`;
+ img.style.height = `${rect.height / scaleY}px`;
+ pdfBox.replaceChild(img, pdfBox.children[0])
}
}
@@ -287,9 +281,9 @@ export namespace DragManager {
});
const target = document.elementFromPoint(e.x, e.y);
removed.map(r => {
- let dragEle: HTMLElement = r[0]!;
- let parent: HTMLElement | null = r[1];
- if (parent) parent.appendChild(dragEle);
+ let dragEle = r[0];
+ let parent = r[1];
+ if (parent && dragEle) parent.appendChild(dragEle);
});
if (target) {
if (finishDrag) finishDrag(dragData);
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 4e97b9401..8aef44a3a 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -26,7 +26,7 @@ export interface ExecutableScript {
}
function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [name: string]: any }): ExecutableScript {
- const compiled = !(diagnostics && diagnostics.some(diag => diag.category == ts.DiagnosticCategory.Error));
+ const compiled = !(diagnostics && diagnostics.some(diag => diag.category === ts.DiagnosticCategory.Error));
let func: () => Opt<Field>;
if (compiled && script) {
@@ -40,7 +40,7 @@ function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [
paramNames.push(prop);
params.push(scope[prop]);
}
- let thisParam = scope["this"];
+ let thisParam = scope.this;
let compiledFunction = new Function(...paramNames, script);
func = function (): Opt<Field> {
return compiledFunction.apply(thisParam, params)
@@ -49,10 +49,8 @@ function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [
func = () => undefined;
}
- return Object.assign(func,
- {
- compiled
- });
+ Object.assign(func, { compiled });
+ return func as ExecutableScript;
}
interface File {
@@ -125,9 +123,9 @@ export function CompileScript(script: string, scope?: { [name: string]: any }, a
}
export function ToField(data: any): Opt<Field> {
- if (typeof data == "string") {
+ if (typeof data === "string") {
return new TextField(data);
- } else if (typeof data == "number") {
+ } else if (typeof data === "number") {
return new NumberField(data);
}
return undefined;
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 958c14491..5e1fa9576 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -11,13 +11,20 @@ export namespace SelectionManager {
SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
// if doc is not in SelectedDocuments, add it
if (!ctrlPressed) {
- manager.SelectedDocuments = [];
+ this.DeselectAll();
}
if (manager.SelectedDocuments.indexOf(doc) === -1) {
manager.SelectedDocuments.push(doc);
+ doc.props.onActiveChanged(true);
}
}
+
+ @action
+ DeselectAll(): void {
+ manager.SelectedDocuments.map(dv => dv.props.onActiveChanged(false))
+ manager.SelectedDocuments = [];
+ }
}
const manager = new Manager();
@@ -33,13 +40,13 @@ export namespace SelectionManager {
export function DeselectAll(except?: Document): void {
let found: DocumentView | undefined = undefined;
if (except) {
- for (let i = 0; i < manager.SelectedDocuments.length; i++) {
- let view = manager.SelectedDocuments[i];
- if (view.props.Document == except) found = view;
+ for (const view of manager.SelectedDocuments) {
+ if (view.props.Document === except) found = view;
}
}
- manager.SelectedDocuments.length = 0;
- if (found) manager.SelectedDocuments.push(found);
+
+ manager.DeselectAll()
+ if (found) manager.SelectDoc(found, false);
}
export function SelectedDocuments(): Array<DocumentView> {
diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts
index 3e1039166..54effd512 100644
--- a/src/client/util/Transform.ts
+++ b/src/client/util/Transform.ts
@@ -3,7 +3,7 @@ export class Transform {
private _translateY: number = 0;
private _scale: number = 1;
- static get Identity(): Transform {
+ static Identity(): Transform {
return new Transform(0, 0, 1);
}
@@ -62,33 +62,19 @@ export class Transform {
return this;
}
- translated = (x: number, y: number): Transform => {
- return this.copy().translate(x, y);
- }
+ translated = (x: number, y: number): Transform => this.copy().translate(x, y)
- preTranslated = (x: number, y: number): Transform => {
- return this.copy().preTranslate(x, y);
- }
+ preTranslated = (x: number, y: number): Transform => this.copy().preTranslate(x, y)
- scaled = (scale: number): Transform => {
- return this.copy().scale(scale);
- }
+ scaled = (scale: number): Transform => this.copy().scale(scale)
- scaledAbout = (scale: number, x: number, y: number): Transform => {
- return this.copy().scaleAbout(scale, x, y);
- }
+ scaledAbout = (scale: number, x: number, y: number): Transform => this.copy().scaleAbout(scale, x, y)
- preScaled = (scale: number): Transform => {
- return this.copy().preScale(scale);
- }
+ preScaled = (scale: number): Transform => this.copy().preScale(scale)
- transformed = (transform: Transform): Transform => {
- return this.copy().transform(transform);
- }
+ transformed = (transform: Transform): Transform => this.copy().transform(transform)
- preTransformed = (transform: Transform): Transform => {
- return this.copy().preTransform(transform);
- }
+ preTransformed = (transform: Transform): Transform => this.copy().preTransform(transform)
transformPoint = (x: number, y: number): [number, number] => {
x *= this._scale;
@@ -98,9 +84,7 @@ export class Transform {
return [x, y];
}
- transformDirection = (x: number, y: number): [number, number] => {
- return [x * this._scale, y * this._scale];
- }
+ transformDirection = (x: number, y: number): [number, number] => [x * this._scale, y * this._scale]
transformBounds(x: number, y: number, width: number, height: number): { x: number, y: number, width: number, height: number } {
[x, y] = this.transformPoint(x, y);
@@ -108,12 +92,8 @@ export class Transform {
return { x, y, width, height };
}
- inverse = () => {
- return new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale)
- }
+ inverse = () => new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale)
- copy = () => {
- return new Transform(this._translateX, this._translateY, this._scale);
- }
+ copy = () => new Transform(this._translateX, this._translateY, this._scale)
} \ No newline at end of file
diff --git a/src/client/util/TypedEvent.ts b/src/client/util/TypedEvent.ts
index 0714a7f5c..1b251da25 100644
--- a/src/client/util/TypedEvent.ts
+++ b/src/client/util/TypedEvent.ts
@@ -36,7 +36,5 @@ export class TypedEvent<T> {
this.listenersOncer = [];
}
- pipe = (te: TypedEvent<T>): Disposable => {
- return this.on((e) => te.emit(e));
- }
+ pipe = (te: TypedEvent<T>): Disposable => this.on((e) => te.emit(e))
} \ No newline at end of file
diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index 6d1b2f1b8..1e5028375 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -159,8 +159,8 @@ export namespace UndoManager {
}
undoing = true;
- for (let i = 0; i < commands.length; i++) {
- commands[i].redo();
+ for (const command of commands) {
+ command.redo();
}
undoing = false;
diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d
index 4f69053b1..47c3481b2 100644
--- a/src/client/util/type_decls.d
+++ b/src/client/util/type_decls.d
@@ -181,7 +181,7 @@ declare class Key extends Field {
Copy(): Field;
ToScriptString(): string;
}
-declare type FIELD_WAITING = "<Waiting>";
+declare type FIELD_WAITING = null;
declare type Opt<T> = T | undefined;
declare type FieldValue<T> = Opt<T> | FIELD_WAITING;
// @ts-ignore
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 8bf1a42d1..99588480d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -117,16 +117,12 @@ 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, {
+ DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => docView.ContentRef.current!), dragData, {
handlers: {
dragComplete: action(() => this._dragging = false),
},
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 6f66f8f38..33759d38a 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -6,7 +6,7 @@ import { Document } from '../../fields/Document';
import { KeyStore } from '../../fields/KeyStore';
import "./Main.scss";
import { MessageStore } from '../../server/Message';
-import { Utils } from '../../Utils';
+import { Utils, returnTrue, emptyFunction } from '../../Utils';
import * as request from 'request'
import * as rp from 'request-promise'
import { Documents } from '../documents/Documents';
@@ -204,15 +204,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,15 +219,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} />
}
@@ -372,8 +371,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..ee752a2ca
--- /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 (let i = 0; i < data.length; i++) {
+ if (this.createsCycle(data[i], containerDocument))
+ return true;
+ }
+ let annots = documentToAdd.GetList<Document>(KeyStore.Annotations, []);
+ for (let i = 0; i < annots.length; i++) {
+ if (this.createsCycle(annots[i], 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 39e0dd989..1b0ad0bee 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";
@@ -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..14ed70b8c 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 => {
+ 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 0ff6c3b40..9dade94f1 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, value: string) => {
let script = CompileScript(value, { this: doc }, true);
if (!script.compiled) {
@@ -105,21 +110,19 @@ export class CollectionSchemaView extends CollectionViewBase {
return false;
}
return (
- <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "56px" }} key={props.doc.Id} ref={reference}>
+ <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "56px" }} key={props.Document.Id} ref={reference}>
<EditableView
display={"inline"}
contents={contents}
height={56}
GetValue={() => {
- let field = props.doc.Get(props.fieldKey);
+ let field = props.Document.Get(props.fieldKey);
if (field && field instanceof Field) {
return field.ToScriptString();
}
return field || "";
}}
- SetValue={(value: string) => {
- return applyToDoc(props.doc, value);
- }}
+ SetValue={(value: string) => applyToDoc(props.Document, value)}
OnFillDown={(value: string) => {
this.props.Document.GetTAsync<ListField<Document>>(this.props.fieldKey, ListField).then((val) => {
if (val) {
@@ -147,7 +150,7 @@ export class CollectionSchemaView extends CollectionViewBase {
}
}),
style: {
- background: rowInfo.index == this._selectedIndex ? "lightGray" : "white",
+ background: rowInfo.index === this._selectedIndex ? "lightGray" : "white",
//color: rowInfo.index == this._selectedIndex ? "white" : "black"
}
};
@@ -176,8 +179,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);
}
}
@@ -206,8 +209,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) => {
@@ -235,12 +238,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) => { }
@@ -291,28 +290,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
@@ -322,12 +323,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 70790af18..32d74164d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -7,17 +7,19 @@ 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';
export interface TreeViewProps {
document: Document;
deleteDoc: (doc: Document) => void;
+ moveDocument: DragManager.MoveFunction;
}
export enum BulletType {
@@ -48,6 +50,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;
@@ -63,7 +75,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));
+ let onItemDown = setupDrag(reference, () => this.props.document, this.props.moveDocument);
let editableView = (titleString: string) =>
(<EditableView
display={"inline"}
@@ -91,7 +103,7 @@ 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} />)}
+ {children.Data.map(value => <TreeView key={value.Id} document={value} deleteDoc={this.remove} moveDocument={this.move} />)}
</ul>
}
else bulletType = BulletType.Collapsed;
@@ -121,7 +133,7 @@ export class CollectionTreeView extends CollectionViewBase {
var children = this.props.Document.GetT<ListField<Document>>(KeyStore.Data, ListField);
let childrenElement = !children || children === FieldWaiting ? (null) :
(children.Data.map(value =>
- <TreeView document={value} key={value.Id} deleteDoc={this.remove} />)
+ <TreeView document={value} key={value.Id} deleteDoc={this.remove} moveDocument={this.props.moveDocument} />)
)
return (
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 470a853e3..3ab6db5ef 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);
}
@@ -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 => {
+ 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..5b4caf58d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,138 +1,33 @@
-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 => {
+ 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) })
@@ -140,20 +35,11 @@ export class CollectionView extends React.Component<CollectionViewProps> {
}
}
- 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 458bae7ab..b4784ae9c 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.removeDocument(this.props.CollectionView);
+ let added = false;
+ if (de.data.aliasOnDrop) {
+ added = de.data.droppedDocuments.reduce((added, d) => added || this.props.addDocument(d), false);
+ } else if (de.data.moveDocument) {
+ const move = de.data.moveDocument;
+ added = de.data.droppedDocuments.reduce((added, d) => added || move(d, this.props.Document, this.props.addDocument), false)
+ } else {
+ added = de.data.droppedDocuments.reduce((added, d) => added || this.props.addDocument(d), false)
}
e.stopPropagation();
return added;
@@ -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 eb20b3100..b682ab303 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -37,11 +37,11 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
let srcTarg = (protoSrc ? protoSrc : srcDoc);
let findBrush = (field: ListField<Document>) => field.Data.findIndex(brush => {
let bdocs = brush.GetList(KeyStore.BrushingDocs, [] as Document[]);
- return (bdocs.length == 0 || (bdocs[0] == dstTarg && bdocs[1] == srcTarg) || (bdocs[0] == srcTarg && bdocs[1] == dstTarg))
+ return (bdocs.length === 0 || (bdocs[0] === dstTarg && bdocs[1] === srcTarg) || (bdocs[0] === srcTarg && bdocs[1] === dstTarg))
});
let brushAction = (field: ListField<Document>) => {
let found = findBrush(field);
- if (found != -1)
+ if (found !== -1)
field.Data.splice(found, 1);
};
if (Math.abs(x1 + x1w - x2) < 20 || Math.abs(x2 + x2w - x1) < 20) {
@@ -50,7 +50,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
- brushAction = brushAction = (field: ListField<Document>) => (findBrush(field) == -1) && field.Data.push(linkDoc);
+ brushAction = brushAction = (field: ListField<Document>) => (findBrush(field) === -1) && field.Data.push(linkDoc);
}
dstTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
srcTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
@@ -63,10 +63,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
@@ -78,14 +78,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 1ddb84a99..19227f5e0 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";
@observer
@@ -40,15 +42,20 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
public selectDocuments = (docs: Document[]) => {
- this.props.CollectionView.SelectedDocs.length = 0;
- docs.map(d => this.props.CollectionView.SelectedDocs.push(d.Id));
+ SelectionManager.DeselectAll;
+ docs.map(doc => {
+ const dv = DocumentManager.Instance.getDocumentView(doc);
+ if (dv) {
+ SelectionManager.SelectDoc(dv, true);
+ }
+ })
}
public getActiveDocuments = () => {
var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).reduce((active, doc) => {
var page = doc.GetNumber(KeyStore.Page, -1);
- if (page == curPage || page == -1) {
+ if (page === curPage || page === -1) {
active.push(doc);
}
return active;
@@ -60,6 +67,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); }
@@ -67,38 +76,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;
}
@@ -114,7 +125,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);
@@ -136,7 +147,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);
@@ -242,16 +253,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,
}
}
@@ -260,7 +274,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[])
@@ -281,7 +295,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..7022fd972 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -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/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 6daf15f5f..0ce991485 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -28,7 +28,7 @@ export class AudioBox extends React.Component<FieldViewProps> {
render() {
- let field = this.props.doc.Get(this.props.fieldKey)
+ 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";
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..1c9155dce 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,7 +44,34 @@ 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
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b9329f269..31adec0d7 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, {
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(e.x, e.y, 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 0c0efc437..263343da0 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -35,156 +35,156 @@ const { menuBar } = require("prosemirror-menu");
// this will edit the document and assign the new value to that field.
//]
export class FormattedTextBox extends React.Component<FieldViewProps> {
- public static LayoutString(fieldStr: string = "DataKey") {
- return FieldView.LayoutString(FormattedTextBox, fieldStr);
- }
- private _ref: React.RefObject<HTMLDivElement>;
- private _editorView: Opt<EditorView>;
- private _reactionDisposer: Opt<IReactionDisposer>;
-
- constructor(props: FieldViewProps) {
- super(props);
+ public static LayoutString(fieldStr: string = "DataKey") {
+ return FieldView.LayoutString(FormattedTextBox, fieldStr);
+ }
+ private _ref: React.RefObject<HTMLDivElement>;
+ private _editorView: Opt<EditorView>;
+ private _reactionDisposer: Opt<IReactionDisposer>;
- this._ref = React.createRef();
- this.onChange = this.onChange.bind(this);
- }
+ constructor(props: FieldViewProps) {
+ super(props);
- dispatchTransaction = (tx: Transaction) => {
- if (this._editorView) {
- const state = this._editorView.state.apply(tx);
- this._editorView.updateState(state);
- const { doc, fieldKey } = this.props;
- doc.SetDataOnPrototype(
- fieldKey,
- JSON.stringify(state.toJSON()),
- RichTextField
- );
- // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+ this._ref = React.createRef();
+ this.onChange = this.onChange.bind(this);
}
- };
- componentDidMount() {
- let state: EditorState;
- const config = {
- schema,
- inpRules, //these currently don't do anything, but could eventually be helpful
- plugins: [
- history(),
- keymap({ "Mod-z": undo, "Mod-y": redo }),
- keymap(baseKeymap),
- this.tooltipMenuPlugin()
- ]
+ dispatchTransaction = (tx: Transaction) => {
+ if (this._editorView) {
+ const state = this._editorView.state.apply(tx);
+ this._editorView.updateState(state);
+ const { Document, fieldKey } = this.props;
+ Document.SetDataOnPrototype(
+ fieldKey,
+ JSON.stringify(state.toJSON()),
+ RichTextField
+ );
+ // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+ }
};
- let field = this.props.doc.GetT(this.props.fieldKey, RichTextField);
- if (field && field != FieldWaiting && field.Data) {
- state = EditorState.fromJSON(config, JSON.parse(field.Data));
- } else {
- state = EditorState.create(config);
- }
- if (this._ref.current) {
- this._editorView = new EditorView(this._ref.current, {
- state,
- dispatchTransaction: this.dispatchTransaction
- });
- }
+ componentDidMount() {
+ let state: EditorState;
+ const config = {
+ schema,
+ inpRules, //these currently don't do anything, but could eventually be helpful
+ plugins: [
+ history(),
+ keymap({ "Mod-z": undo, "Mod-y": redo }),
+ keymap(baseKeymap),
+ this.tooltipMenuPlugin()
+ ]
+ };
- this._reactionDisposer = reaction(
- () => {
- const field = this.props.doc.GetT(this.props.fieldKey, RichTextField);
- return field && field != FieldWaiting ? field.Data : undefined;
- },
- field => {
- if (field && this._editorView) {
- this._editorView.updateState(
- EditorState.fromJSON(config, JSON.parse(field))
- );
+ let field = this.props.Document.GetT(this.props.fieldKey, RichTextField);
+ if (field && field !== FieldWaiting && field.Data) {
+ state = EditorState.fromJSON(config, JSON.parse(field.Data));
+ } else {
+ state = EditorState.create(config);
+ }
+ if (this._ref.current) {
+ this._editorView = new EditorView(this._ref.current, {
+ state,
+ dispatchTransaction: this.dispatchTransaction
+ });
}
- }
- );
- if (this.props.selectOnLoad) {
- this.props.select();
- this._editorView!.focus();
- }
- }
- componentWillUnmount() {
- if (this._editorView) {
- this._editorView.destroy();
+ this._reactionDisposer = reaction(
+ () => {
+ const field = this.props.Document.GetT(this.props.fieldKey, RichTextField);
+ return field && field !== FieldWaiting ? field.Data : undefined;
+ },
+ field => {
+ if (field && this._editorView) {
+ this._editorView.updateState(
+ EditorState.fromJSON(config, JSON.parse(field))
+ );
+ }
+ }
+ );
+ if (this.props.selectOnLoad) {
+ this.props.select(false);
+ this._editorView!.focus();
+ }
}
- if (this._reactionDisposer) {
- this._reactionDisposer();
+
+ componentWillUnmount() {
+ if (this._editorView) {
+ this._editorView.destroy();
+ }
+ if (this._reactionDisposer) {
+ this._reactionDisposer();
+ }
}
- }
- shouldComponentUpdate() {
- return false;
- }
+ shouldComponentUpdate() {
+ return false;
+ }
- @action
- onChange(e: React.ChangeEvent<HTMLInputElement>) {
- const { fieldKey, doc } = this.props;
- doc.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
- // doc.SetData(fieldKey, e.target.value, RichTextField);
- }
- onPointerDown = (e: React.PointerEvent): void => {
- if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
- e.stopPropagation();
+ @action
+ onChange(e: React.ChangeEvent<HTMLInputElement>) {
+ const { fieldKey, Document } = this.props;
+ Document.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
+ // doc.SetData(fieldKey, e.target.value, RichTextField);
}
- };
+ onPointerDown = (e: React.PointerEvent): void => {
+ if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
+ e.stopPropagation();
+ }
+ };
- //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE
- textCapability = (e: React.MouseEvent): void => {};
+ //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE
+ textCapability = (e: React.MouseEvent): void => { };
- specificContextMenu = (e: React.MouseEvent): void => {
- ContextMenu.Instance.addItem({
- description: "Text Capability",
- event: this.textCapability
- });
+ specificContextMenu = (e: React.MouseEvent): void => {
+ ContextMenu.Instance.addItem({
+ description: "Text Capability",
+ event: this.textCapability
+ });
- // ContextMenu.Instance.addItem({
- // description: "Submenu",
- // items: [
- // {
- // description: "item 1", event:
- // },
- // {
- // description: "item 2", event:
- // }
- // ]
- // })
- // e.stopPropagation()
- };
+ // ContextMenu.Instance.addItem({
+ // description: "Submenu",
+ // items: [
+ // {
+ // description: "item 1", event:
+ // },
+ // {
+ // description: "item 2", event:
+ // }
+ // ]
+ // })
+ // e.stopPropagation()
+ };
- onPointerWheel = (e: React.WheelEvent): void => {
- e.stopPropagation();
- };
+ onPointerWheel = (e: React.WheelEvent): void => {
+ e.stopPropagation();
+ };
- tooltipMenuPlugin() {
- return new Plugin({
- view(_editorView) {
- return new TooltipTextMenu(_editorView);
- }
- });
- }
- onKeyPress(e: React.KeyboardEvent) {
- e.stopPropagation();
- // stop propagation doesn't seem to stop propagation of native keyboard events.
- // so we set a flag on the native event that marks that the event's been handled.
- // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
- }
- render() {
- return (
- <div
- className="formattedTextBox-cont"
- onKeyDown={this.onKeyPress}
- onKeyPress={this.onKeyPress}
- onPointerDown={this.onPointerDown}
- onContextMenu={this.specificContextMenu}
- // tfs: do we need this event handler
- onWheel={this.onPointerWheel}
- ref={this._ref}
- />
- );
- }
+ tooltipMenuPlugin() {
+ return new Plugin({
+ view(_editorView) {
+ return new TooltipTextMenu(_editorView);
+ }
+ });
+ }
+ onKeyPress(e: React.KeyboardEvent) {
+ e.stopPropagation();
+ // stop propagation doesn't seem to stop propagation of native keyboard events.
+ // so we set a flag on the native event that marks that the event's been handled.
+ // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
+ }
+ render() {
+ return (
+ <div
+ className="formattedTextBox-cont"
+ onKeyDown={this.onKeyPress}
+ onKeyPress={this.onKeyPress}
+ onPointerDown={this.onPointerDown}
+ onContextMenu={this.specificContextMenu}
+ // tfs: do we need this event handler
+ onWheel={this.onPointerWheel}
+ ref={this._ref}
+ />
+ );
+ }
}
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 283c1f732..9b067aeeb 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -34,7 +34,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
onEnterKey = (e: React.KeyboardEvent): void => {
if (e.key == 'Enter') {
if (this._keyInput && this._valueInput) {
- let doc = this.props.doc.GetT(KeyStore.Data, Document);
+ let doc = this.props.Document.GetT(KeyStore.Data, Document);
if (!doc || doc == FieldWaiting) {
return
}
@@ -69,7 +69,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
}
createTable = () => {
- let doc = this.props.doc.GetT(KeyStore.Data, Document);
+ let doc = this.props.Document.GetT(KeyStore.Data, Document);
if (!doc || doc == FieldWaiting) {
return <tr><td>Loading...</td></tr>
}
@@ -103,14 +103,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 7ed5ee272..a676844dc 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();
}
@@ -82,12 +87,12 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
}
let field = script();
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/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index f9f5bc8f8..d1fb06153 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..b4590df34 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);
+ 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..92e2fabd4 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -16,10 +16,10 @@ 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 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";
diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx
index 7fdd77bf3..f13cccd24 100644
--- a/src/debug/Viewer.tsx
+++ b/src/debug/Viewer.tsx
@@ -87,7 +87,7 @@ class DocumentViewer extends React.Component<{ field: Document }> {
return (
<div key={kv[0]}>
<b>({key ? key.Name : kv[0]}): </b>
- <DebugViewer fieldId={kv[1]!}></DebugViewer>
+ <DebugViewer fieldId={kv[1]}></DebugViewer>
</div>
)
})
@@ -177,9 +177,7 @@ class Viewer extends React.Component {
onChange={this.inputOnChange}
onKeyDown={this.onKeyPress} />
<div>
- {this.ids.map(id => {
- return <DebugViewer fieldId={id} key={id}></DebugViewer>
- })}
+ {this.ids.map(id => <DebugViewer fieldId={id} key={id}></DebugViewer>)}
</div>
</>
)
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 92d03d765..8eca5e30c 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -34,33 +34,20 @@ export class Document extends Field {
}
}
- public Width = () => {
- return this.GetNumber(KeyStore.Width, 0);
- };
- public Height = () => {
- return this.GetNumber(
- KeyStore.Height,
- this.GetNumber(KeyStore.NativeWidth, 0)
- ? (this.GetNumber(KeyStore.NativeHeight, 0) /
- this.GetNumber(KeyStore.NativeWidth, 0)) *
- this.GetNumber(KeyStore.Width, 0)
- : 0
- );
- };
- public Scale = () => {
- return this.GetNumber(KeyStore.Scale, 1);
- };
+ public Width = () => this.GetNumber(KeyStore.Width, 0)
+ public Height = () => this.GetNumber(KeyStore.Height, this.GetNumber(KeyStore.NativeWidth, 0) ? (this.GetNumber(KeyStore.NativeHeight, 0) / this.GetNumber(KeyStore.NativeWidth, 0)) * this.GetNumber(KeyStore.Width, 0) : 0);
+ public Scale = () => this.GetNumber(KeyStore.Scale, 1)
@computed
public get Title(): string {
let title = this.Get(KeyStore.Title, true);
if (title)
- if (title != FieldWaiting && title instanceof TextField)
+ if (title !== FieldWaiting && title instanceof TextField)
return title.Data;
else return "-waiting-";
let parTitle = this.GetT(KeyStore.Title, TextField);
if (parTitle)
- if (parTitle != FieldWaiting) return parTitle.Data + ".alias";
+ if (parTitle !== FieldWaiting) return parTitle.Data + ".alias";
else return "-waiting-.alias";
return "-untitled-";
}
@@ -106,7 +93,7 @@ export class Document extends Field {
}
} else {
let doc: FieldValue<Document> = this;
- while (doc && doc != FieldWaiting && field != FieldWaiting) {
+ while (doc && field !== FieldWaiting) {
let curField = doc.fields.get(key.Id);
let curProxy = doc._proxies.get(key.Id);
if (!curField || (curProxy && curField.field.Id !== curProxy)) {
@@ -137,7 +124,7 @@ export class Document extends Field {
break;
}
}
- if (doc == FieldWaiting) field = FieldWaiting;
+ if (doc === FieldWaiting) field = FieldWaiting;
}
return field;
@@ -191,7 +178,7 @@ export class Document extends Field {
if (callback) {
fn(callback);
} else {
- return new Promise(res => fn(res));
+ return new Promise(fn);
}
}
@@ -237,7 +224,7 @@ export class Document extends Field {
ignoreProto: boolean = false
): FieldValue<T> {
var getfield = this.Get(key, ignoreProto);
- if (getfield != FieldWaiting) {
+ if (getfield !== FieldWaiting) {
return Cast(getfield, ctor);
}
return FieldWaiting;
@@ -249,7 +236,7 @@ export class Document extends Field {
ignoreProto: boolean = false
): T {
const field = this.GetT(key, ctor, ignoreProto);
- if (field && field != FieldWaiting) {
+ if (field && field !== FieldWaiting) {
return field;
}
const newField = new ctor();
@@ -366,7 +353,7 @@ export class Document extends Field {
GetAllPrototypes(): Document[] {
let protos: Document[] = [];
let doc: FieldValue<Document> = this;
- while (doc && doc != FieldWaiting) {
+ while (doc && doc !== FieldWaiting) {
protos.push(doc);
doc = doc.GetPrototype();
}
@@ -415,7 +402,7 @@ export class Document extends Field {
let fields: [string, string][] = [];
this._proxies.forEach((field, key) => {
if (field) {
- fields.push([key, field as string]);
+ fields.push([key, field]);
}
});
diff --git a/src/fields/Field.ts b/src/fields/Field.ts
index d48509a47..0d0e56f77 100644
--- a/src/fields/Field.ts
+++ b/src/fields/Field.ts
@@ -12,8 +12,8 @@ export function Cast<T extends Field>(field: FieldValue<Field>, ctor: { new(): T
return undefined;
}
-export const FieldWaiting: FIELD_WAITING = "<Waiting>";
-export type FIELD_WAITING = "<Waiting>";
+export const FieldWaiting: FIELD_WAITING = null;
+export type FIELD_WAITING = null;
export type FieldId = string;
export type Opt<T> = T | undefined;
export type FieldValue<T> = Opt<T> | FIELD_WAITING;
diff --git a/src/fields/WebField.ts b/src/fields/WebField.ts
index 6c4de5000..0cbcc6d33 100644
--- a/src/fields/WebField.ts
+++ b/src/fields/WebField.ts
@@ -4,7 +4,7 @@ import { Types } from "../server/Message";
export class WebField extends BasicField<URL> {
constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
- super(data == undefined ? new URL("https://crossorigin.me/" + "https://cs.brown.edu/") : data, save, id);
+ super(data === undefined ? new URL("https://crossorigin.me/" + "https://cs.brown.edu/") : data, save, id);
}
toString(): string {
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index ae48dd2c6..c3684a0eb 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -9,6 +9,7 @@ import { RouteStore } from '../server/RouteStore';
import { ServerUtils } from '../server/ServerUtil';
import "./ImageUpload.scss";
import React = require('react');
+import { Opt } from '../fields/Field';
@@ -20,48 +21,44 @@ import React = require('react');
// }
// }
-const onFileLoad = (file: any) => {
+const onFileLoad = async (file: any) => {
let imgPrev = document.getElementById("img_preview")
if (imgPrev) {
let files: File[] = file.target.files;
- if (files.length != 0) {
+ if (files.length !== 0) {
console.log(files[0]);
let formData = new FormData();
formData.append("file", files[0]);
const upload = window.location.origin + "/upload"
- fetch(upload, {
+ const res = await fetch(upload, {
method: 'POST',
body: formData
- }).then((res: Response) => {
- return res.json()
- }).then(json => {
- json.map((file: any) => {
- let path = window.location.origin + file
- var doc: Document = Documents.ImageDocument(path, { nativeWidth: 200, width: 200 })
+ });
+ const json = await res.json();
+ json.map(async (file: any) => {
+ let path = window.location.origin + file
+ var doc: Document = Documents.ImageDocument(path, { nativeWidth: 200, width: 200 })
- rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId)).then(res => {
- if (res) {
- return Server.GetField(res);
- }
- throw new Error("No user id returned");
- }).then(field => {
- if (field instanceof Document) {
- return field.GetTAsync(KeyStore.OptionalRightCollection, Document)
- }
- }).then(pending => {
- if (pending) {
- pending.GetOrCreateAsync(KeyStore.Data, ListField, list => {
- list.Data.push(doc);
- })
- }
- });
+ const res = await rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId));
+ if (!res) {
+ throw new Error("No user id returned");
+ }
+ const field = await Server.GetField(res);
+ let pending: Opt<Document>;
+ if (field instanceof Document) {
+ pending = await field.GetTAsync(KeyStore.OptionalRightCollection, Document)
+ }
+ if (pending) {
+ pending.GetOrCreateAsync(KeyStore.Data, ListField, list => {
+ list.Data.push(doc);
+ })
+ }
+ });
- // console.log(window.location.origin + file[0])
+ // console.log(window.location.origin + file[0])
- //imgPrev.setAttribute("src", window.location.origin + files[0].name)
- })
- })
+ //imgPrev.setAttribute("src", window.location.origin + files[0].name)
}
}
}
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 8e14cf98e..835432c8e 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -73,7 +73,7 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
<span>{i + 1} - </span>
<EditableView
display={"inline"}
- GetValue={() => { return s.Title }}
+ GetValue={() => s.Title}
SetValue={(title: string): boolean => {
s.SetText(KeyStore.Title, title);
return true;
diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts
index e365b8dce..2bbb334b5 100644
--- a/src/server/authentication/controllers/user_controller.ts
+++ b/src/server/authentication/controllers/user_controller.ts
@@ -4,7 +4,7 @@ import * as passport from "passport";
import { IVerifyOptions } from "passport-local";
import "../config/passport";
import * as request from "express-validator";
-const flash = require("express-flash");
+import flash = require("express-flash");
import * as session from "express-session";
import * as pug from 'pug';
import * as async from 'async';
@@ -109,12 +109,12 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => {
}
passport.authenticate("local", (err: Error, user: DashUserModel, info: IVerifyOptions) => {
- if (err) { return next(err); }
+ if (err) { next(err); return }
if (!user) {
return res.redirect(RouteStore.signup);
}
req.logIn(user, (err) => {
- if (err) { return next(err); }
+ if (err) { next(err); return }
res.redirect(RouteStore.home);
});
})(req, res, next);
@@ -158,7 +158,8 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio
User.findOne({ email }, function (err, user: DashUserModel) {
if (!user) {
// NO ACCOUNT WITH SUBMITTED EMAIL
- return res.redirect(RouteStore.forgot);
+ res.redirect(RouteStore.forgot);
+ return
}
user.passwordResetToken = token;
user.passwordResetExpires = new Date(Date.now() + 3600000); // 1 HOUR
@@ -228,7 +229,8 @@ export let postReset = function (req: Request, res: Response) {
user.save(function (err) {
if (err) {
- return res.redirect(RouteStore.login);
+ res.redirect(RouteStore.login);
+ return;
}
req.logIn(user, function (err) {
if (err) {
diff --git a/src/server/index.ts b/src/server/index.ts
index 17d7432e0..ce8bbefe8 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -263,12 +263,10 @@ function deleteFields() {
return Database.Instance.deleteAll();
}
-function deleteAll() {
- return Database.Instance.deleteAll().then(() => {
- return Database.Instance.deleteAll('sessions')
- }).then(() => {
- return Database.Instance.deleteAll('users')
- });
+async function deleteAll() {
+ await Database.Instance.deleteAll();
+ await Database.Instance.deleteAll('sessions');
+ await Database.Instance.deleteAll('users');
}
function barReceived(guid: String) {
diff --git a/src/server/public/files/upload_a6a70d84ebb65febf7900e29f52cc86d.pdf b/src/server/public/files/upload_a6a70d84ebb65febf7900e29f52cc86d.pdf
deleted file mode 100644
index dfd6ab339..000000000
--- a/src/server/public/files/upload_a6a70d84ebb65febf7900e29f52cc86d.pdf
+++ /dev/null
Binary files differ