aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/Network.ts34
-rw-r--r--src/client/documents/Documents.ts17
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx2
-rw-r--r--src/client/util/ReportManager.tsx2
-rw-r--r--src/client/views/nodes/AudioBox.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/LoadingBox.tsx3
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingView.tsx2
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx4
-rw-r--r--src/mobile/ImageUpload.tsx2
-rw-r--r--src/server/ApiManagers/UploadManager.ts2
-rw-r--r--src/server/DashUploadUtils.ts3
12 files changed, 54 insertions, 21 deletions
diff --git a/src/client/Network.ts b/src/client/Network.ts
index 19eff3b3b..d606b9854 100644
--- a/src/client/Network.ts
+++ b/src/client/Network.ts
@@ -2,6 +2,11 @@ import { Utils } from '../Utils';
import requestPromise = require('request-promise');
import { Upload } from '../server/SharedMediaTypes';
+/**
+ * Networking is repsonsible for connecting the client to the server. Networking
+ * mainly provides methods that the client can use to begin the process of
+ * interacting with the server, such as fetching or uploading files.
+ */
export namespace Networking {
export async function FetchFromServer(relativeRoute: string) {
return (await fetch(relativeRoute)).text();
@@ -18,20 +23,31 @@ export namespace Networking {
}
/**
+ * FileGuidPair attaches a guid to a file that is being uploaded,
+ * allowing the client to track the upload progress.
+ *
+ * When files are dragged to the canvas, the overWriteDoc's ID is
+ * used as the guid. Otherwise, a new guid is generated.
+ */
+ export interface FileGuidPair {
+ file: File;
+ guid?: string;
+ }
+ /**
* Handles uploading basic file types to server and makes the API call to "/uploadFormData" endpoint
- * with the mapping of GUID to filem as parameters.
+ * with the mapping of guid to files as parameters.
*
- * @param files the files to be uploaded to the server
+ * @param fileguidpairs the files and corresponding guids to be uploaded to the server
* @returns the response as a json from the server
*/
- export async function UploadFilesToServer<T extends Upload.FileInformation = Upload.FileInformation>(files: File | File[]): Promise<Upload.FileResponse<T>[]> {
+ export async function UploadFilesToServer<T extends Upload.FileInformation = Upload.FileInformation>(fileguidpairs: FileGuidPair | FileGuidPair[]): Promise<Upload.FileResponse<T>[]> {
const formData = new FormData();
- if (Array.isArray(files)) {
- if (!files.length) {
+ if (Array.isArray(fileguidpairs)) {
+ if (!fileguidpairs.length) {
return [];
}
const maxFileSize = 50000000;
- if (files.some(f => f.size > maxFileSize)) {
+ if (fileguidpairs.some(f => f.file.size > maxFileSize)) {
return new Promise<any>(res =>
res([
{
@@ -41,9 +57,11 @@ export namespace Networking {
])
);
}
- files.forEach(file => formData.append(Utils.GenerateGuid(), file));
+ // If the fileguidpair has a guid to use (From the overwriteDoc) use that guid. Otherwise, generate a new guid.
+ fileguidpairs.forEach(fileguidpair => formData.append(fileguidpair.guid ?? Utils.GenerateGuid(), fileguidpair.file));
} else {
- formData.append(Utils.GenerateGuid(), files);
+ // Handle the case where fileguidpairs is a single file.
+ formData.append(fileguidpairs.guid ?? Utils.GenerateGuid(), fileguidpairs.file);
}
const parameters = {
method: 'POST',
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 250a501e0..c1abd6e71 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1841,9 +1841,21 @@ export namespace DocUtils {
});
}
+ /**
+ * uploadFilesToDocs will take in an array of Files, and creates documents for the
+ * new files.
+ *
+ * @param files an array of files that will be uploaded
+ * @param options options to use while uploading
+ * @returns
+ */
export async function uploadFilesToDocs(files: File[], options: DocumentOptions) {
const generatedDocuments: Doc[] = [];
- const upfiles = await Networking.UploadFilesToServer(files);
+
+ // These files do not have overwriteDocs, so we do not set the guid and let the client generate one.
+ const fileNoGuidPairs: Networking.FileGuidPair[] = files.map(file => ({file}));
+
+ const upfiles = await Networking.UploadFilesToServer(fileNoGuidPairs);
for (const {
source: { name, type },
result,
@@ -1855,7 +1867,8 @@ export namespace DocUtils {
export function uploadFileToDoc(file: File, options: DocumentOptions, overwriteDoc: Doc) {
const generatedDocuments: Doc[] = [];
- Networking.UploadFilesToServer([file]).then(upfiles => {
+ // Since this file has an overwriteDoc, we can set the client tracking guid to the overwriteDoc's guid.
+ Networking.UploadFilesToServer([{file, guid: overwriteDoc[Id]}]).then(upfiles => {
const {
source: { name, type },
result,
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index b9bb22564..1a4c2450e 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx
@@ -112,7 +112,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
sizes.push(file.size);
modifiedDates.push(file.lastModified);
});
- collector.push(...(await Networking.UploadFilesToServer<Upload.ImageInformation>(batch)));
+ collector.push(...(await Networking.UploadFilesToServer<Upload.ImageInformation>(batch.map(file =>({file})))));
runInAction(() => (this.completed += batch.length));
});
diff --git a/src/client/util/ReportManager.tsx b/src/client/util/ReportManager.tsx
index 51742d455..4c1020455 100644
--- a/src/client/util/ReportManager.tsx
+++ b/src/client/util/ReportManager.tsx
@@ -173,7 +173,7 @@ export class ReportManager extends React.Component<{}> {
// upload the files to the server
if (input.files && input.files.length !== 0) {
const fileArray: File[] = Array.from(input.files);
- (Networking.UploadFilesToServer(fileArray)).then(links => {
+ (Networking.UploadFilesToServer(fileArray.map(file =>({file})))).then(links => {
console.log('finshed uploading', links.map(this.getServerPath));
this.setFileLinks((links ?? []).map(this.getServerPath));
})
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 0cb849923..6558d215a 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -233,7 +233,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
this.dataDoc[this.fieldKey + '-recordingStart'] = new DateField();
DocUtils.ActiveRecordings.push(this);
this._recorder.ondataavailable = async (e: any) => {
- const [{ result }] = await Networking.UploadFilesToServer(e.data);
+ const [{ result }] = await Networking.UploadFilesToServer({file: e.data});
if (!(result instanceof Error)) {
this.props.Document[this.fieldKey] = new AudioField(result.accessPaths.agnostic.client);
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 0769e26d0..687683e6e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1013,7 +1013,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
gumStream = stream;
recorder = new MediaRecorder(stream);
recorder.ondataavailable = async (e: any) => {
- const [{ result }] = await Networking.UploadFilesToServer(e.data);
+ const [{ result }] = await Networking.UploadFilesToServer({file: e.data});
if (!(result instanceof Error)) {
const audioField = new AudioField(result.accessPaths.agnostic.client);
const audioAnnos = Cast(dataDoc[field + '-audioAnnotations'], listSpec(AudioField), null);
diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx
index 8c5255f80..fcbd0128d 100644
--- a/src/client/views/nodes/LoadingBox.tsx
+++ b/src/client/views/nodes/LoadingBox.tsx
@@ -8,6 +8,7 @@ import { Networking } from '../../Network';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { FieldView, FieldViewProps } from './FieldView';
import './LoadingBox.scss';
+import { Id } from '../../../fields/FieldSymbols';
/**
* LoadingBox Class represents a placeholder doc for documents that are currently
@@ -43,7 +44,7 @@ export class LoadingBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.rootDoc.loadingError = 'Upload interrupted, please try again';
} else {
const updateFunc = async () => {
- const result = await Networking.QueryYoutubeProgress(StrCast(this.rootDoc.title));
+ const result = await Networking.QueryYoutubeProgress(StrCast(this.rootDoc[Id])); // We use the guid of the overwriteDoc to track file uploads.
runInAction(() => (this.progress = result.progress));
this._timer = setTimeout(updateFunc, 1000);
};
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 424ebc384..51eb774e2 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -67,7 +67,7 @@ export function RecordingView(props: IRecordingViewProps) {
const videoFiles = videos.map((vid, i) => new File(vid.videoChunks, `segvideo${i}.mkv`, { type: vid.videoChunks[0].type, lastModified: Date.now() }));
// upload the segments to the server and get their server access paths
- const serverPaths: string[] = (await Networking.UploadFilesToServer(videoFiles)).map(res => (res.result instanceof Error ? '' : res.result.accessPaths.agnostic.server));
+ const serverPaths: string[] = (await Networking.UploadFilesToServer(videoFiles.map(file => ({file})))).map(res => (res.result instanceof Error ? '' : res.result.accessPaths.agnostic.server));
// concat the segments together using post call
const result: Upload.AccessPathInfo | Error = await Networking.PostToServer('/concatVideos', serverPaths);
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 1e178b123..312b3c619 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -224,7 +224,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
const aud_chunks: any = [];
this._audioRec.ondataavailable = (e: any) => aud_chunks.push(e.data);
this._audioRec.onstop = async (e: any) => {
- const [{ result }] = await Networking.UploadFilesToServer(aud_chunks);
+ const [{ result }] = await Networking.UploadFilesToServer(aud_chunks.map((file: any) => ({file})));
if (!(result instanceof Error)) {
this.dataDoc[this.props.fieldKey + '-audio'] = new AudioField(result.accessPaths.agnostic.client);
}
@@ -237,7 +237,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
this._videoRec.onstop = async (e: any) => {
console.log('screenshotbox: upload');
const file = new File(vid_chunks, `${this.rootDoc[Id]}.mkv`, { type: vid_chunks[0].type, lastModified: Date.now() });
- const [{ result }] = await Networking.UploadFilesToServer(file);
+ const [{ result }] = await Networking.UploadFilesToServer({file});
this.dataDoc[this.fieldKey + '_duration'] = (new Date().getTime() - this.recordingStart!) / 1000;
if (!(result instanceof Error)) {
// convert this screenshotBox into normal videoBox
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index f910d765e..da38fcaee 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -42,7 +42,7 @@ export class Uploader extends React.Component<ImageUploadProps> {
this.process = "Uploading Files";
for (let index = 0; index < files.length; ++index) {
const file = files[index];
- const res = await Networking.UploadFilesToServer(file);
+ const res = await Networking.UploadFilesToServer({file});
this.setOpacity(3, "1"); // Slab 3
// For each item that the user has selected
res.map(async ({ result }) => {
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index 74c06b4a6..ba6d7acfe 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -75,7 +75,7 @@ export default class UploadManager extends ApiManager {
for (const key in files) {
const f = files[key];
if (!Array.isArray(f)) {
- const result = await DashUploadUtils.upload(f);
+ const result = await DashUploadUtils.upload(f, key); // key is the guid used by the client to track upload progress.
result && !(result.result instanceof Error) && results.push(result);
}
}
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index 11523a9d8..eaaac4e6d 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -181,9 +181,10 @@ export namespace DashUploadUtils {
});
}
- export async function upload(file: File): Promise<Upload.FileResponse> {
+ export async function upload(file: File, overwriteGuid?: string): Promise<Upload.FileResponse> {
const { type, path, name } = file;
const types = type?.split('/') ?? [];
+ uploadProgress.set(overwriteGuid ?? name, 'uploading'); // If the client sent a guid it uses to track upload progress, use that guid. Otherwise, use the file's name.
const category = types[0];
let format = `.${types[1]}`;