diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/Network.ts | 34 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 17 | ||||
-rw-r--r-- | src/client/util/Import & Export/DirectoryImportBox.tsx | 2 | ||||
-rw-r--r-- | src/client/util/ReportManager.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/LoadingBox.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/RecordingBox/RecordingView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/ScreenshotBox.tsx | 4 | ||||
-rw-r--r-- | src/mobile/ImageUpload.tsx | 2 | ||||
-rw-r--r-- | src/server/ApiManagers/UploadManager.ts | 2 | ||||
-rw-r--r-- | src/server/DashUploadUtils.ts | 3 |
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]}`; |