aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts16
-rw-r--r--src/client/documents/Documents.ts30
-rw-r--r--src/client/views/PreviewCursor.tsx21
-rw-r--r--src/client/views/collections/CollectionSubView.tsx59
4 files changed, 75 insertions, 51 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index dba802f98..a01a94134 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -7,6 +7,22 @@ import { ColorState } from 'react-color';
export namespace Utils {
export let DRAG_THRESHOLD = 4;
+ export function readUploadedFileAsText(inputFile: File) {
+ const temporaryFileReader = new FileReader();
+
+ return new Promise((resolve, reject) => {
+ temporaryFileReader.onerror = () => {
+ temporaryFileReader.abort();
+ reject(new DOMException("Problem parsing input file."));
+ };
+
+ temporaryFileReader.onload = () => {
+ resolve(temporaryFileReader.result);
+ };
+ temporaryFileReader.readAsText(inputFile);
+ });
+ }
+
export function GenerateGuid(): string {
return v4();
}
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4c27cf47d..85da621e0 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1,5 +1,5 @@
import { runInAction } from "mobx";
-import { extname } from "path";
+import { extname, basename } from "path";
import { DateField } from "../../fields/DateField";
import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym } from "../../fields/Doc";
import { HtmlField } from "../../fields/HtmlField";
@@ -48,6 +48,8 @@ import { PresElementBox } from "../views/presentationview/PresElementBox";
import { RecommendationsBox } from "../views/RecommendationsBox";
import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
import { DocumentType } from "./DocumentTypes";
+import { Networking } from "../Network";
+import { Upload } from "../../server/SharedMediaTypes";
const path = require('path');
export interface DocumentOptions {
@@ -1104,6 +1106,32 @@ export namespace DocUtils {
});
return optionsCollection;
}
+
+ export async function uploadFilesToDocs(files: File[], options: DocumentOptions) {
+ const generatedDocuments: Doc[] = [];
+ for (const { source: { name, type }, result } of await Networking.UploadFilesToServer(files)) {
+ if (result instanceof Error) {
+ alert(`Upload failed: ${result.message}`);
+ return [];
+ }
+ const full = { ...options, _width: 400, title: name };
+ const pathname = Utils.prepend(result.accessPaths.agnostic.client);
+ const doc = await DocUtils.DocumentFromType(type, pathname, full);
+ if (!doc) {
+ continue;
+ }
+ const proto = Doc.GetProto(doc);
+ proto.text = result.rawText;
+ proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
+ if (Upload.isImageInformation(result)) {
+ proto["data-nativeWidth"] = (result.nativeWidth > result.nativeHeight) ? 400 * result.nativeWidth / result.nativeHeight : 400;
+ proto["data-nativeHeight"] = (result.nativeWidth > result.nativeHeight) ? 400 : 400 / (result.nativeWidth / result.nativeHeight);
+ proto.contentSize = result.contentSize;
+ }
+ generatedDocuments.push(doc);
+ }
+ return generatedDocuments;
+ }
}
Scripting.addGlobal("Docs", Docs);
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 1ab99881d..6583589f3 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -3,13 +3,18 @@ import { observer } from 'mobx-react';
import "normalize.css";
import * as React from 'react';
import "./PreviewCursor.scss";
-import { Docs } from '../documents/Documents';
+import { Docs, DocUtils } from '../documents/Documents';
import { Doc } from '../../fields/Doc';
import { Transform } from "../util/Transform";
import { DocServer } from '../DocServer';
-import { undoBatch } from '../util/UndoManager';
+import { undoBatch, UndoManager } from '../util/UndoManager';
import { NumCast } from '../../fields/Types';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import * as rp from 'request-promise';
+import { Utils } from '../../Utils';
+import { Networking } from '../Network';
+import { Upload } from '../../server/SharedMediaTypes';
+import { basename } from 'path';
@observer
export class PreviewCursor extends React.Component<{}> {
@@ -26,7 +31,7 @@ export class PreviewCursor extends React.Component<{}> {
document.addEventListener("paste", this.paste);
}
- paste = (e: ClipboardEvent) => {
+ paste = async (e: ClipboardEvent) => {
if (PreviewCursor.Visible && e.clipboardData) {
const newPoint = PreviewCursor._getTransform().transformPoint(PreviewCursor._clickPoint[0], PreviewCursor._clickPoint[1]);
runInAction(() => PreviewCursor.Visible = false);
@@ -104,6 +109,16 @@ export class PreviewCursor extends React.Component<{}> {
x: newPoint[0],
y: newPoint[1],
})))();
+ } else if (e.clipboardData.items.length) {
+ const batch = UndoManager.StartBatch("collection view drop");
+ const files: File[] = [];
+ for (let i = 0; i < e.clipboardData.items.length; i++) {
+ const file = e.clipboardData.items[i].getAsFile();
+ file && files.push(file);
+ }
+ const generatedDocuments = await DocUtils.uploadFilesToDocs(files, { x: newPoint[0], y: newPoint[1] });
+ generatedDocuments.forEach(PreviewCursor._addDocument);
+ batch.end();
}
}
}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 95c4898cc..ecd16d22f 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -238,21 +238,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
}
return false;
}
- readUploadedFileAsText = (inputFile: File) => {
- const temporaryFileReader = new FileReader();
- return new Promise((resolve, reject) => {
- temporaryFileReader.onerror = () => {
- temporaryFileReader.abort();
- reject(new DOMException("Problem parsing input file."));
- };
-
- temporaryFileReader.onload = () => {
- resolve(temporaryFileReader.result);
- };
- temporaryFileReader.readAsText(inputFile);
- });
- }
@undoBatch
@action
protected async onExternalDrop(e: React.DragEvent, options: DocumentOptions, completed?: () => void) {
@@ -271,8 +257,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
e.stopPropagation();
e.preventDefault();
- const { addDocument } = this;
- if (!addDocument) {
+ if (!this.addDocument) {
alert("this.props.addDocument does not exist. Aborting drop operation.");
return;
}
@@ -286,14 +271,14 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
DocServer.GetRefField(docid).then(f => {
if (f instanceof Doc) {
if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView
- (f instanceof Doc) && addDocument(f);
+ (f instanceof Doc) && this.addDocument(f);
}
});
} else {
- addDocument(Docs.Create.WebDocument(href, { ...options, title: href }));
+ this.addDocument(Docs.Create.WebDocument(href, { ...options, title: href }));
}
} else if (text) {
- addDocument(Docs.Create.TextDocument(text, { ...options, _width: 100, _height: 25 }));
+ this.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 100, _height: 25 }));
}
return;
}
@@ -313,7 +298,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
if (source.startsWith("http")) {
const doc = Docs.Create.ImageDocument(source, { ...options, _width: 300 });
ImageUtils.ExtractExif(doc);
- addDocument(doc);
+ this.addDocument(doc);
}
return;
} else {
@@ -360,7 +345,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
if (text) {
if (text.includes("www.youtube.com/watch") || text.includes("www.youtube.com/embed")) {
const url = text.replace("youtube.com/watch?v=", "youtube.com/embed/").split("&")[0];
- addDocument(Docs.Create.VideoDocument(url, {
+ this.addDocument(Docs.Create.VideoDocument(url, {
...options,
title: url,
_width: 400,
@@ -413,10 +398,10 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
const file = item.getAsFile();
file?.type && files.push(file);
- file?.type === "application/json" && this.readUploadedFileAsText(file).then(result => {
+ file?.type === "application/json" && Utils.readUploadedFileAsText(file).then(result => {
console.log(result);
const json = JSON.parse(result as string);
- addDocument(Docs.Create.TreeDocument(
+ this.addDocument(Docs.Create.TreeDocument(
json["rectangular-puzzle"].crossword.clues[0].clue.map((c: any) => {
const label = Docs.Create.LabelDocument({ title: c["#text"], _width: 120, _height: 20 });
const proto = Doc.GetProto(label);
@@ -428,38 +413,18 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
});
}
}
- for (const { source: { name, type }, result } of await Networking.UploadFilesToServer(files)) {
- if (result instanceof Error) {
- alert(`Upload failed: ${result.message}`);
- return;
- }
- const full = { ...options, _width: 400, title: name };
- const pathname = Utils.prepend(result.accessPaths.agnostic.client);
- const doc = await DocUtils.DocumentFromType(type, pathname, full);
- if (!doc) {
- continue;
- }
- const proto = Doc.GetProto(doc);
- proto.text = result.rawText;
- proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
- if (Upload.isImageInformation(result)) {
- proto["data-nativeWidth"] = (result.nativeWidth > result.nativeHeight) ? 400 * result.nativeWidth / result.nativeHeight : 400;
- proto["data-nativeHeight"] = (result.nativeWidth > result.nativeHeight) ? 400 : 400 / (result.nativeWidth / result.nativeHeight);
- proto.contentSize = result.contentSize;
- }
- generatedDocuments.push(doc);
- }
+ generatedDocuments.push(...await DocUtils.uploadFilesToDocs(files, options));
if (generatedDocuments.length) {
const set = generatedDocuments.length > 1 && generatedDocuments.map(d => DocUtils.iconify(d));
if (set) {
- addDocument(DocUtils.pileup(generatedDocuments, options.x!, options.y!)!);
+ this.addDocument(DocUtils.pileup(generatedDocuments, options.x!, options.y!)!);
} else {
- generatedDocuments.forEach(addDocument);
+ generatedDocuments.forEach(this.addDocument);
}
completed?.();
} else {
if (text && !text.includes("https://")) {
- addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 }));
+ this.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 }));
}
}
batch.end();