aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-04-08 21:58:34 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-04-08 21:58:34 -0400
commite963f324fe8436ff5fc8ee21cdf091b6265690f9 (patch)
treeb6a4255bd3a0a3c30504639f3e0e7a48ebadd420
parent0c76a60386cc0693b1572b5a8cf23b37243e5ab7 (diff)
parenta2135bcc0a995378aad0e71ade832a4d526a37f0 (diff)
Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web into propsRefactor
-rw-r--r--src/client/documents/Documents.ts132
-rw-r--r--src/client/util/UndoManager.ts22
-rw-r--r--src/client/views/DocumentDecorations.tsx3
-rw-r--r--src/client/views/InkingCanvas.tsx24
-rw-r--r--src/client/views/InkingControl.tsx3
-rw-r--r--src/client/views/Main.tsx8
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx1
-rw-r--r--src/client/views/collections/CollectionView.tsx7
-rw-r--r--src/client/views/collections/CollectionViewBase.tsx39
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx2
11 files changed, 144 insertions, 99 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index aa109e779..613b94abd 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -68,13 +68,16 @@ export namespace Documents {
const audioProtoId = "audioProto";
export function initProtos(): Promise<void> {
- return Server.GetFields([textProtoId, histoProtoId, collProtoId, imageProtoId, webProtoId, kvpProtoId]).then(fields => {
- textProto = fields[textProtoId] as Document;
- histoProto = fields[histoProtoId] as Document;
- collProto = fields[collProtoId] as Document;
- imageProto = fields[imageProtoId] as Document;
- webProto = fields[webProtoId] as Document;
- kvpProto = fields[kvpProtoId] as Document;
+ return Server.GetFields([textProtoId, histoProtoId, collProtoId, pdfProtoId, imageProtoId, videoProtoId, audioProtoId, webProtoId, kvpProtoId]).then(fields => {
+ textProto = fields[textProtoId] as Document || CreateTextPrototype();
+ histoProto = fields[histoProtoId] as Document || CreateHistogramPrototype();
+ collProto = fields[collProtoId] as Document || CreateCollectionPrototype();
+ imageProto = fields[imageProtoId] as Document || CreateImagePrototype();
+ webProto = fields[webProtoId] as Document || CreateWebPrototype();
+ kvpProto = fields[kvpProtoId] as Document || CreateKVPPrototype();
+ videoProto = fields[videoProtoId] as Document || CreateVideoPrototype();
+ audioProto = fields[audioProtoId] as Document || CreateAudioPrototype();
+ pdfProto = fields[pdfProtoId] as Document || CreatePdfPrototype();
});
}
function assignOptions(doc: Document, options: DocumentOptions): Document {
@@ -114,71 +117,64 @@ export namespace Documents {
return assignOptions(deleg, options);
}
- function GetImagePrototype(): Document {
- if (!imageProto) {
- imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("AnnotationsKey"),
- { x: 0, y: 0, nativeWidth: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
- imageProto.SetText(KeyStore.BackgroundLayout, ImageBox.LayoutString());
- imageProto.SetNumber(KeyStore.CurPage, 0);
- }
+ function CreateImagePrototype(): Document {
+ let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("AnnotationsKey"),
+ { x: 0, y: 0, nativeWidth: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
+ imageProto.SetText(KeyStore.BackgroundLayout, ImageBox.LayoutString());
+ imageProto.SetNumber(KeyStore.CurPage, 0);
return imageProto;
}
- function GetHistogramPrototype(): Document {
- if (!histoProto) {
- histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("AnnotationsKey"),
- { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
- histoProto.SetText(KeyStore.BackgroundLayout, HistogramBox.LayoutString());
- }
+
+ function CreateHistogramPrototype(): Document {
+ let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("AnnotationsKey"),
+ { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
+ histoProto.SetText(KeyStore.BackgroundLayout, HistogramBox.LayoutString());
return histoProto;
}
- function GetTextPrototype(): Document {
- return textProto ? textProto :
- textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] });
+ function CreateTextPrototype(): Document {
+ let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] });
+ return textProto
}
- function GetPdfPrototype(): Document {
- if (!pdfProto) {
- pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"),
- { x: 0, y: 0, nativeWidth: 1200, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] });
- pdfProto.SetNumber(KeyStore.CurPage, 1);
- pdfProto.SetText(KeyStore.BackgroundLayout, PDFBox.LayoutString());
- }
+ function CreatePdfPrototype(): Document {
+ let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"),
+ { x: 0, y: 0, nativeWidth: 1200, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] });
+ pdfProto.SetNumber(KeyStore.CurPage, 1);
+ pdfProto.SetText(KeyStore.BackgroundLayout, PDFBox.LayoutString());
return pdfProto;
}
- function GetWebPrototype(): Document {
- return webProto ? webProto :
- webProto = setupPrototypeOptions(webProtoId, "WEB_PROTO", WebBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 300, layoutKeys: [KeyStore.Data] });
+ function CreateWebPrototype(): Document {
+ let webProto = setupPrototypeOptions(webProtoId, "WEB_PROTO", WebBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 300, layoutKeys: [KeyStore.Data] });
+ return webProto;
}
- function GetCollectionPrototype(): Document {
- return collProto ? collProto :
- collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"),
- { panx: 0, pany: 0, scale: 1, width: 500, height: 500, layoutKeys: [KeyStore.Data] });
+ function CreateCollectionPrototype(): Document {
+ let collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"),
+ { panx: 0, pany: 0, scale: 1, width: 500, height: 500, layoutKeys: [KeyStore.Data] });
+ return collProto;
}
- function GetKVPPrototype(): Document {
- return kvpProto ? kvpProto :
- kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValueBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
+ function CreateKVPPrototype(): Document {
+ let kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValueBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] });
+ return kvpProto;
}
- function GetVideoPrototype(): Document {
- if (!videoProto) {
- videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("AnnotationsKey"),
- { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
- videoProto.SetNumber(KeyStore.CurPage, 0);
- videoProto.SetText(KeyStore.BackgroundLayout, VideoBox.LayoutString());
- }
+ function CreateVideoPrototype(): Document {
+ let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("AnnotationsKey"),
+ { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
+ videoProto.SetNumber(KeyStore.CurPage, 0);
+ videoProto.SetText(KeyStore.BackgroundLayout, VideoBox.LayoutString());
return videoProto;
}
- function GetAudioPrototype(): Document {
- return audioProto ? audioProto :
- audioProto = setupPrototypeOptions(audioProtoId, "AUDIO_PROTO", AudioBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
+ function CreateAudioPrototype(): Document {
+ let audioProto = setupPrototypeOptions(audioProtoId, "AUDIO_PROTO", AudioBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
+ return audioProto;
}
export function ImageDocument(url: string, options: DocumentOptions = {}) {
- return assignToDelegate(SetInstanceOptions(GetImagePrototype(), options, [new URL(url), ImageField]).MakeDelegate(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
+ return assignToDelegate(SetInstanceOptions(imageProto, options, [new URL(url), ImageField]).MakeDelegate(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
// let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
// [new URL(url), ImageField]);
// doc.SetText(KeyStore.Caption, "my caption...");
@@ -187,44 +183,44 @@ export namespace Documents {
// return doc;
}
export function VideoDocument(url: string, options: DocumentOptions = {}) {
- return assignToDelegate(SetInstanceOptions(GetVideoPrototype(), options, [new URL(url), VideoField]), options);
+ return assignToDelegate(SetInstanceOptions(videoProto, options, [new URL(url), VideoField]), options);
}
export function AudioDocument(url: string, options: DocumentOptions = {}) {
- return assignToDelegate(SetInstanceOptions(GetAudioPrototype(), options, [new URL(url), AudioField]), options);
+ return assignToDelegate(SetInstanceOptions(audioProto, options, [new URL(url), AudioField]), options);
}
export function HistogramDocument(histoOp: HistogramOperation, options: DocumentOptions = {}, id?: string, delegId?: string) {
- return assignToDelegate(SetInstanceOptions(GetHistogramPrototype(), options, [histoOp, HistogramField], id).MakeDelegate(delegId), options);
+ return assignToDelegate(SetInstanceOptions(histoProto, options, [histoOp, HistogramField], id).MakeDelegate(delegId), options);
}
export function TextDocument(options: DocumentOptions = {}) {
- return assignToDelegate(SetInstanceOptions(GetTextPrototype(), options, ["", TextField]).MakeDelegate(), options);
+ return assignToDelegate(SetInstanceOptions(textProto, options, ["", TextField]).MakeDelegate(), options);
}
export function PdfDocument(url: string, options: DocumentOptions = {}) {
- return assignToDelegate(SetInstanceOptions(GetPdfPrototype(), options, [new URL(url), PDFField]).MakeDelegate(), options);
+ return assignToDelegate(SetInstanceOptions(pdfProto, options, [new URL(url), PDFField]).MakeDelegate(), options);
}
export function WebDocument(url: string, options: DocumentOptions = {}) {
- return assignToDelegate(SetInstanceOptions(GetWebPrototype(), options, [new URL(url), WebField]).MakeDelegate(), options);
+ return assignToDelegate(SetInstanceOptions(webProto, options, [new URL(url), WebField]).MakeDelegate(), options);
}
export function HtmlDocument(html: string, options: DocumentOptions = {}) {
- return assignToDelegate(SetInstanceOptions(GetWebPrototype(), options, [html, HtmlField]).MakeDelegate(), options);
+ return assignToDelegate(SetInstanceOptions(webProto, options, [html, HtmlField]).MakeDelegate(), options);
}
export function KVPDocument(document: Document, options: DocumentOptions = {}, id?: string) {
- return assignToDelegate(SetInstanceOptions(GetKVPPrototype(), options, document, id), options)
+ return assignToDelegate(SetInstanceOptions(kvpProto, options, document, id), options)
}
export function FreeformDocument(documents: Array<Document>, options: DocumentOptions, id?: string, makePrototype: boolean = true) {
if (!makePrototype) {
- return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id)
+ return SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id)
}
- return assignToDelegate(SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate(), options)
+ return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate(), options)
}
export function SchemaDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
- return assignToDelegate(SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options)
+ return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options)
}
export function TreeDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
- return assignToDelegate(SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options)
+ return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options)
}
export function DockDocument(config: string, options: DocumentOptions, id?: string) {
- return assignToDelegate(SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Docking }, [config, TextField], id), options)
+ return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Docking }, [config, TextField], id), options)
}
export function CaptionDocument(doc: Document) {
diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index bdc77f1ba..b4ea4acae 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -35,7 +35,20 @@ function propertyDecorator(target: any, key: string | symbol) {
}
})
}
-export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor<any>): any {
+
+export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor<any>): any;
+export function undoBatch(fn: (...args: any[]) => any): (...args: any[]) => any;
+export function undoBatch(target: any, key?: string | symbol, descriptor?: TypedPropertyDescriptor<any>): any {
+ if (!key) {
+ return function () {
+ let batch = UndoManager.StartBatch("");
+ try {
+ return target.apply(undefined, arguments)
+ } finally {
+ batch.end();
+ }
+ }
+ }
if (!descriptor) {
propertyDecorator(target, key);
return;
@@ -129,8 +142,11 @@ export namespace UndoManager {
export function RunInBatch(fn: () => void, batchName: string) {
let batch = StartBatch(batchName);
- fn();
- batch.end();
+ try {
+ fn();
+ } finally {
+ batch.end();
+ }
}
export const Undo = action(() => {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index deed0fa7c..285d145a2 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -379,6 +379,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
// }
render() {
var bounds = this.Bounds;
+ if (bounds.x === Number.MAX_VALUE) {
+ return (null);
+ }
// console.log(this._documents.length)
// let test = this._documents[0].props.Document.Title;
if (this.Hidden) {
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 4b3ea48c5..4ecc44119 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -10,6 +10,7 @@ import "./InkingCanvas.scss";
import { InkingControl } from "./InkingControl";
import { InkingStroke } from "./InkingStroke";
import React = require("react");
+import { undoBatch, UndoManager } from "../util/UndoManager";
interface InkCanvasProps {
getScreenTransform: () => Transform;
@@ -22,6 +23,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
maxCanvasDim = 8192 / 2; // 1/2 of the maximum canvas dimension for Chrome
@observable inkMidX: number = 0;
@observable inkMidY: number = 0;
+ private previousState?: StrokeMap;
private _currentStrokeId: string = "";
public static IntersectStrokeRect(stroke: StrokeData, selRect: { left: number, top: number, width: number, height: number }): boolean {
return stroke.pathData.reduce((inside: boolean, val) => inside ||
@@ -59,23 +61,28 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
if (e.button !== 0 || e.altKey || e.ctrlKey || InkingControl.Instance.selectedTool === InkTool.None) {
return;
}
+
document.addEventListener("pointermove", this.onPointerMove, true);
document.addEventListener("pointerup", this.onPointerUp, true);
e.stopPropagation();
e.preventDefault();
+ this.previousState = this.inkData;
+
if (InkingControl.Instance.selectedTool !== InkTool.Eraser) {
// start the new line, saves a uuid to represent the field of the stroke
this._currentStrokeId = Utils.GenerateGuid();
- this.inkData.set(this._currentStrokeId, {
+ const data = this.inkData;
+ data.set(this._currentStrokeId, {
pathData: [this.relativeCoordinatesForEvent(e.clientX, e.clientY)],
color: InkingControl.Instance.selectedColor,
width: InkingControl.Instance.selectedWidth,
tool: InkingControl.Instance.selectedTool,
page: this.props.Document.GetNumber(KeyStore.CurPage, -1)
});
+ this.inkData = data;
}
- }
+ };
@action
onPointerUp = (e: PointerEvent): void => {
@@ -88,6 +95,16 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
}
e.stopPropagation();
e.preventDefault();
+
+ const batch = UndoManager.StartBatch("One ink stroke");
+ const oldState = this.previousState || new Map;
+ this.previousState = undefined;
+ const newState = this.inkData;
+ UndoManager.AddEvent({
+ undo: () => this.inkData = oldState,
+ redo: () => this.inkData = newState,
+ });
+ batch.end();
}
@action
@@ -103,13 +120,14 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
}
this.inkData = data;
}
- }
+ };
relativeCoordinatesForEvent = (ex: number, ey: number): { x: number, y: number } => {
let [x, y] = this.props.getScreenTransform().transformPoint(ex, ey);
return { x, y };
}
+ @undoBatch
@action
removeLine = (id: string): void => {
let data = this.inkData;
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 13f0a0acc..64ee66ec7 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -21,7 +21,7 @@ export class InkingControl extends React.Component {
@observable private _selectedColor: string = "rgb(244, 67, 54)";
@observable private _selectedWidth: string = "25";
@observable private _open: boolean = false;
- @observable private _colorPickerDisplay: boolean = false;
+ @observable private _colorPickerDisplay = false;
constructor(props: Readonly<{}>) {
super(props);
@@ -76,6 +76,7 @@ export class InkingControl extends React.Component {
this._open = !this._open;
}
+
@action
toggleColorPicker = () => {
this._colorPickerDisplay = !this._colorPickerDisplay;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 9868f6c74..6376fd694 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -321,7 +321,7 @@ export class Main extends React.Component {
isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} />
}
return (
- [
+ <>
<div id="main-div">
<DocumentDecorations />
<Measure onResize={(r: any) => runInAction(() => {
@@ -339,9 +339,9 @@ export class Main extends React.Component {
{this.miscButtons}
{workspaceMenu}
<InkingControl />
- </div>,
- this.activeTextBox
- ]
+ </div>
+ {this.activeTextBox}
+ </>
);
}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 6640c843e..c5e1e7f4b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -226,6 +226,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
itemDropped = () => {
this.stateChanged();
}
+
tabCreated = (tab: any) => {
if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
if (tab.titleElement[0].textContent.indexOf("-waiting") !== -1) {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 1b0cfd57b..b31dcc888 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -9,6 +9,7 @@ import { ContextMenu } from '../ContextMenu';
import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
import { KeyStore } from '../../../fields/KeyStore';
import { observer } from 'mobx-react';
+import { undoBatch } from '../../util/UndoManager';
@observer
export class CollectionView extends React.Component<FieldViewProps> {
@@ -29,9 +30,9 @@ export class CollectionView extends React.Component<FieldViewProps> {
onContextMenu = (e: React.MouseEvent): void => {
if (!e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
- ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) })
- ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) })
- ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) })
+ ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)) })
+ ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema)) })
+ ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree)) })
}
}
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 84d378e1c..ad1294f76 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -4,20 +4,17 @@ import { ListField } from "../../../fields/ListField";
import React = require("react");
import { KeyStore } from "../../../fields/KeyStore";
import { FieldWaiting, Opt } from "../../../fields/Field";
-import { undoBatch } from "../../util/UndoManager";
+import { undoBatch, UndoManager } from "../../util/UndoManager";
import { DragManager } from "../../util/DragManager";
import { Documents, DocumentOptions } from "../../documents/Documents";
-import { Key } from "../../../fields/Key";
-import { Transform } from "../../util/Transform";
-import { CollectionView } from "./CollectionView";
import { RouteStore } from "../../../server/RouteStore";
import { TupleField } from "../../../fields/TupleField";
import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
import { NumberField } from "../../../fields/NumberField";
-import request = require("request");
import { ServerUtils } from "../../../server/ServerUtil";
import { Server } from "../../Server";
import { FieldViewProps } from "../nodes/FieldView";
+import * as rp from 'request-promise'
export interface CollectionViewProps extends FieldViewProps {
addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
@@ -145,6 +142,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
return ctor ? ctor(path, options) : undefined;
}
+ @undoBatch
@action
protected onDrop(e: React.DragEvent, options: DocumentOptions): void {
let html = e.dataTransfer.getData("text/html");
@@ -164,23 +162,29 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
return;
}
+ let batch = UndoManager.StartBatch("collection view drop");
+ let promises: Promise<void>[] = [];
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < e.dataTransfer.items.length; i++) {
const upload = window.location.origin + RouteStore.upload;
let item = e.dataTransfer.items[i];
if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
- e.dataTransfer.items[i].getAsString(action((s: string) => {
- request.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s), (err, res, body) => {
+ let str: string;
+ let prom = new Promise<string>(res =>
+ e.dataTransfer.items[i].getAsString(res)).then(action((s: string) => {
+ str = s;
+ return rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s))
+ })).then(res => {
let type = res.headers["content-type"];
if (type) {
- let doc = this.getDocumentFromType(type, s, { ...options, width: 300, nativeWidth: 300 })
+ let doc = this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 })
if (doc) {
this.props.addDocument(doc, false);
}
}
});
- // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false)
- }))
+ promises.push(prom);
+ // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false)
}
let type = item.type
if (item.kind === "file") {
@@ -191,7 +195,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
formData.append('file', file)
}
- fetch(upload, {
+ let prom = fetch(upload, {
method: 'POST',
body: formData
}).then(async (res: Response) => {
@@ -211,10 +215,17 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
docs.Data.push(doc);
}
}
- })
- })
- })
+ });
+ });
+ });
+ promises.push(prom);
}
}
+
+ if (promises.length) {
+ Promise.all(promises).catch(() => { }).then(() => batch.end());
+ } else {
+ batch.end();
+ }
}
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d542b8bc2..731ba3332 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -209,7 +209,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
onDrop = (e: React.DragEvent): void => {
var pt = this.getTransform().transformPoint(e.pageX, e.pageY);
super.onDrop(e, { x: pt[0], y: pt[1] });
- }
+ };
onDragOver = (): void => {
}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index ebac61c78..7a94be12b 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -153,8 +153,6 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
e.stopPropagation();
}
- if (e.buttons === 1 && this.props.fieldKey !== KeyStore.Archives)
- e.preventDefault();
};
onPointerUp = (e: React.PointerEvent): void => {
if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {