From a5bf418707321711559782f0348063681c553cbb Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Wed, 10 Aug 2022 16:11:23 -0400 Subject: added placeholder text box for files being uploaded --- src/client/views/collections/CollectionSubView.tsx | 43 +++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5479929bd..35a14704d 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -448,6 +448,46 @@ export function CollectionSubView(moreProps?: X) { } this.slowLoadDocuments(files, options, generatedDocuments, text, completed, e.clientX, e.clientY, addDocument).then(batch.end); } + + /** + * Creates a placeholder doc view for files being uploaded and removes placeholder docs once files are uplodaded. + * + * @param files the files to upload that we want to create placeholders for + * @param options the document options (primarily the x and y coordinates to put doc) + * @param text in the case of youtube the text is the url to the video + * @returns a disposer action that removes the placeholders created after files get uploaded + */ + placeHolderDisposer = (files: File[] | string, options: DocumentOptions, text: string) => { + // TODO: nda - create a specialized view for placeholder upload with a spinner and ability to retry upload + let placeholders: Doc[] = []; + // handle yt case + if (typeof files === 'string') { + placeholders.push(Docs.Create.TextDocument('Loading: ' + text, { ...options, title: text, _width: 500, _height: 200 })); + } else { + // every other doc type is an array of File + + // Get the file names as a text + let textStr = ''; + files.forEach(file => { + textStr += file.name + '\n'; + }); + placeholders.push(Docs.Create.TextDocument('Loading: \n' + textStr, { ...options, title: files.length + ' files', _width: 500, _height: files.length * 40 })); + } + // disposer action to remove placeholders once files are uploaded + const remove = action(() => { + if (!this.props.DataDoc) { + return; + } + for (let i = 0; i < placeholders.length; i++) { + Doc.RemoveDocFromList(this.props.DataDoc, 'data', placeholders[i]); + } + }); + placeholders.forEach(pl => { + this.addDocument(pl); + }); + return remove; + }; + slowLoadDocuments = async ( files: File[] | string, options: DocumentOptions, @@ -458,7 +498,8 @@ export function CollectionSubView(moreProps?: X) { clientY: number, addDocument: (doc: Doc | Doc[]) => boolean ) => { - const disposer = OverlayView.Instance.addElement(, { x: clientX - 125, y: clientY - 125 }); + const disposer = this.placeHolderDisposer(files, options, text); + // const disposer = OverlayView.Instance.addElement(, { x: clientX - 125, y: clientY - 125 }); if (typeof files === 'string') { generatedDocuments.push(...(await DocUtils.uploadYoutubeVideo(files, options))); } else { -- cgit v1.2.3-70-g09d2 From 6c349731fb84f1c44993d2bc55410da19db29a07 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Wed, 10 Aug 2022 16:16:00 -0400 Subject: added placeholder text box for files being uploaded --- src/client/views/collections/CollectionSubView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 35a14704d..2f3f57bac 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -462,7 +462,7 @@ export function CollectionSubView(moreProps?: X) { let placeholders: Doc[] = []; // handle yt case if (typeof files === 'string') { - placeholders.push(Docs.Create.TextDocument('Loading: ' + text, { ...options, title: text, _width: 500, _height: 200 })); + placeholders.push(Docs.Create.TextDocument('Loading: ' + text, { ...options, title: text, _width: 400, _height: 30 })); } else { // every other doc type is an array of File -- cgit v1.2.3-70-g09d2 From 820d40eea4eeb5977889e0ef6c35f9092df44b4b Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Wed, 10 Aug 2022 17:08:47 -0400 Subject: created placeholder loading box but have to get location of final doc to update with loading box --- src/client/documents/DocumentTypes.ts | 3 ++- src/client/documents/Documents.ts | 18 +++++++++++++ src/client/views/collections/CollectionSubView.tsx | 8 ++++-- src/client/views/nodes/DocumentContentsView.tsx | 2 ++ src/client/views/nodes/LoadingBox.scss | 7 +++++ src/client/views/nodes/LoadingBox.tsx | 31 ++++++++++++++++++++++ 6 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 src/client/views/nodes/LoadingBox.scss create mode 100644 src/client/views/nodes/LoadingBox.tsx (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 9dfadf778..d99cd2dac 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -26,6 +26,7 @@ export enum DocumentType { FUNCPLOT = 'funcplot', // function plotter MAP = 'map', DATAVIZ = 'dataviz', + LOADING = 'loading', // special purpose wrappers that either take no data or are compositions of lower level types LINK = 'link', @@ -63,5 +64,5 @@ export enum CollectionViewType { Grid = 'grid', Pile = 'pileup', StackedTimeline = 'stacked timeline', - NoteTaking = "notetaking" + NoteTaking = 'notetaking', } diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c7ea04839..6ccb4358a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -48,6 +48,7 @@ import { KeyValueBox } from '../views/nodes/KeyValueBox'; import { LabelBox } from '../views/nodes/LabelBox'; import { LinkBox } from '../views/nodes/LinkBox'; import { LinkDescriptionPopup } from '../views/nodes/LinkDescriptionPopup'; +import { LoadingBox } from '../views/nodes/LoadingBox'; import { MapBox } from '../views/nodes/MapBox/MapBox'; import { PDFBox } from '../views/nodes/PDFBox'; import { RecordingBox } from '../views/nodes/RecordingBox/RecordingBox'; @@ -648,6 +649,13 @@ export namespace Docs { options: { _fitWidth: true, nativeDimModifiable: true, links: '@links(self)' }, }, ], + [ + DocumentType.LOADING, + { + layout: { view: LoadingBox, dataField: defaultDataKey }, + options: { _fitWidth: true, _fitHeight: true, nativeDimModifiable: true, links: '@links(self)' }, + }, + ], ]); const suffix = 'Proto'; @@ -875,6 +883,16 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COLOR), '', options); } + export function LoadingDocument(title: string, text: string, width?: number, height?: number, options: DocumentOptions = {}) { + let myWidth = 300; + let myHeight = 300; + if (height && width) { + myWidth = width; + myHeight = height; + } + return InstanceFromProto(Prototypes.get(DocumentType.LOADING), '', { ...options, title, text, _width: myWidth, _height: myHeight }); + } + export function RTFDocument(field: RichTextField, options: DocumentOptions = {}, fieldKey: string = 'text') { return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 2f3f57bac..79f629072 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -462,7 +462,8 @@ export function CollectionSubView(moreProps?: X) { let placeholders: Doc[] = []; // handle yt case if (typeof files === 'string') { - placeholders.push(Docs.Create.TextDocument('Loading: ' + text, { ...options, title: text, _width: 400, _height: 30 })); + placeholders.push(Docs.Create.LoadingDocument('Loading...', text, 500, 500, { ...options })); + // placeholders.push(Docs.Create.TextDocument('Loading: ' + text, { ...options, title: text, _width: 400, _height: 30 })); } else { // every other doc type is an array of File @@ -471,7 +472,9 @@ export function CollectionSubView(moreProps?: X) { files.forEach(file => { textStr += file.name + '\n'; }); - placeholders.push(Docs.Create.TextDocument('Loading: \n' + textStr, { ...options, title: files.length + ' files', _width: 500, _height: files.length * 40 })); + placeholders.push(Docs.Create.LoadingDocument('Loading...', textStr, 500, 500, { ...options })); + + // placeholders.push(Docs.Create.TextDocument('Loading: \n' + textStr, { ...options, title: files.length + ' files', _width: 500, _height: files.length * 40 })); } // disposer action to remove placeholders once files are uploaded const remove = action(() => { @@ -498,6 +501,7 @@ export function CollectionSubView(moreProps?: X) { clientY: number, addDocument: (doc: Doc | Doc[]) => boolean ) => { + // TODO: once loading thing is moved it should update the x and y of the file it is placeholder for const disposer = this.placeHolderDisposer(files, options, text); // const disposer = OverlayView.Instance.addElement(, { x: clientX - 125, y: clientY - 125 }); if (typeof files === 'string') { diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 381436a56..4d4985f2a 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -43,6 +43,7 @@ import { VideoBox } from './VideoBox'; import { WebBox } from './WebBox'; import React = require('react'); import XRegExp = require('xregexp'); +import { LoadingBox } from './LoadingBox'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? @@ -267,6 +268,7 @@ export class DocumentContentsView extends React.Component< DataVizBox, HTMLtag, ComparisonBox, + LoadingBox, }} bindings={bindings} jsx={layoutFrame} diff --git a/src/client/views/nodes/LoadingBox.scss b/src/client/views/nodes/LoadingBox.scss new file mode 100644 index 000000000..239faa78e --- /dev/null +++ b/src/client/views/nodes/LoadingBox.scss @@ -0,0 +1,7 @@ +.loadingBoxContainer { + display: flex; + flex-direction: column; + align-content: center; + justify-content: center; + background-color: #fdfdfd; +} diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx new file mode 100644 index 000000000..0e0619241 --- /dev/null +++ b/src/client/views/nodes/LoadingBox.tsx @@ -0,0 +1,31 @@ +import { observer } from 'mobx-react'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; +import { FieldView, FieldViewProps } from './FieldView'; +import * as React from 'react'; +import './LoadingBox.scss'; +import ReactLoading from 'react-loading'; + +export interface LoadingBoxProps { + title: string; + text: string; +} + +@observer +export class LoadingBox extends ViewBoxAnnotatableComponent() { + public static LayoutString(fieldKey: string) { + return FieldView.LayoutString(LoadingBox, fieldKey); + } + + constructor(props: any) { + super(props); + } + + render() { + return ( +
+ Loading: {this.dataDoc.text} + +
+ ); + } +} -- cgit v1.2.3-70-g09d2 From bb2b38b0e47eaf8e64554d101b605bf35a178239 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Tue, 16 Aug 2022 16:43:01 -0400 Subject: updated placeholder --- src/.DS_Store | Bin 10244 -> 10244 bytes src/client/documents/Documents.ts | 63 +++++++++++++------ src/client/util/CurrentUserUtils.ts | 1 + src/client/views/collections/CollectionSubView.tsx | 70 +++++++-------------- src/client/views/nodes/LoadingBox.tsx | 25 ++++++++ 5 files changed, 94 insertions(+), 65 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/.DS_Store b/src/.DS_Store index 4751acf44..4ed785983 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6ccb4358a..d8497e3af 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,4 +1,5 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { files } from 'jszip'; import { action, runInAction } from 'mobx'; import { basename } from 'path'; import { DateField } from '../../fields/DateField'; @@ -794,7 +795,7 @@ export namespace Docs { * only when creating a DockDocument from the current user's already existing * main document. */ - function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = 'data', protoId?: string) { + function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = 'data', protoId?: string, placeholderDoc?: Doc) { const viewKeys = ['x', 'y', 'system']; // keys that should be addded to the view document even though they don't begin with an "_" const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, '^_'); @@ -813,13 +814,22 @@ export namespace Docs { // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do. dataProps[fieldKey + '-annotations'] = new List(); dataProps[fieldKey + '-sidebar'] = new List(); - const dataDoc = Doc.assign(Doc.MakeDelegate(proto, protoId), dataProps, undefined, true); + + const dataDoc = Doc.assign(placeholderDoc ? Doc.GetProto(placeholderDoc) : Doc.MakeDelegate(proto, protoId), dataProps, undefined, true); + + if (placeholderDoc) { + dataDoc.proto = proto; + } const viewFirstProps: { [id: string]: any } = {}; viewFirstProps['acl-Public'] = options['_acl-Public'] ? options['_acl-Public'] : Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; viewFirstProps['acl-Override'] = 'None'; viewFirstProps.author = Doc.CurrentUserEmail; - const viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true); + let viewDoc: Doc; + if (placeholderDoc) { + viewDoc = Doc.assign(placeholderDoc, viewFirstProps, true, true); + } + viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true); Doc.assign(viewDoc, viewProps, true, true); ![DocumentType.LINK, DocumentType.MARKER, DocumentType.LABEL].includes(viewDoc.type as any) && DocUtils.MakeLinkToActiveAudio(() => viewDoc); @@ -883,14 +893,12 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COLOR), '', options); } - export function LoadingDocument(title: string, text: string, width?: number, height?: number, options: DocumentOptions = {}) { - let myWidth = 300; - let myHeight = 300; - if (height && width) { - myWidth = width; - myHeight = height; - } - return InstanceFromProto(Prototypes.get(DocumentType.LOADING), '', { ...options, title, text, _width: myWidth, _height: myHeight }); + export const filesToDocs = new Map(); + + export function LoadingDocument(file: File, options: DocumentOptions, ytString?: string) { + const loading = InstanceFromProto(Prototypes.get(DocumentType.LOADING), file.name, { _height: 300, _width: 300, ...options }); + // filesToDocs.set(loading, file); + return loading; } export function RTFDocument(field: RichTextField, options: DocumentOptions = {}, fieldKey: string = 'text') { @@ -969,13 +977,13 @@ export namespace Docs { return I; } - export function PdfDocument(url: string, options: DocumentOptions = {}) { + export function PdfDocument(url: string, options: DocumentOptions = {}, overwriteDoc?: Doc) { const width = options._width || undefined; const height = options._height || undefined; const nwid = options._nativeWidth || undefined; const nhght = options._nativeHeight || undefined; if (!nhght && width && height && nwid) options._nativeHeight = (Number(nwid) * Number(height)) / Number(width); - return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(url), options); + return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(url), options, undefined, undefined, undefined, overwriteDoc); } export function WebDocument(url: string, options: DocumentOptions = {}) { @@ -1462,8 +1470,8 @@ export namespace DocUtils { return created; } - export async function DocumentFromType(type: string, path: string, options: DocumentOptions): Promise> { - let ctor: ((path: string, options: DocumentOptions) => Doc | Promise) | undefined = undefined; + export async function DocumentFromType(type: string, path: string, options: DocumentOptions, rootDoc?: Doc): Promise> { + let ctor: ((path: string, options: DocumentOptions, overwriteDoc?: Doc) => Doc | Promise) | undefined = undefined; if (type.indexOf('image') !== -1) { ctor = Docs.Create.ImageDocument; if (!options._width) options._width = 300; @@ -1512,7 +1520,7 @@ export namespace DocUtils { options = { ...options, _width: 400, _height: 512, title: path }; } - return ctor ? ctor(path, options) : undefined; + return ctor ? ctor(path, options, rootDoc) : undefined; } export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number, simpleMenu: boolean = false, pivotField?: string, pivotValue?: string): void { @@ -1728,14 +1736,14 @@ export namespace DocUtils { return dd; } - async function processFileupload(generatedDocuments: Doc[], name: string, type: string, result: Error | Upload.FileInformation, options: DocumentOptions) { + async function processFileupload(generatedDocuments: Doc[], name: string, type: string, result: Error | Upload.FileInformation, options: DocumentOptions, rootDoc?: Doc) { 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); + const doc = await DocUtils.DocumentFromType(type, pathname, full, rootDoc); if (doc) { const proto = Doc.GetProto(doc); proto.text = result.rawText; @@ -1813,6 +1821,25 @@ export namespace DocUtils { return generatedDocuments; } + export function uploadFileToDoc(file: File, options: DocumentOptions, overwriteDoc: Doc) { + const generatedDocuments: Doc[] = []; + Networking.UploadFilesToServer([file]).then(upfiles => { + const { + source: { name, type }, + result, + } = upfiles.lastElement(); + console.log(name, type); + name && type && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); + }); + } + + export function generatePlaceHolder(file: File, options: DocumentOptions) { + return Docs.Create.LoadingDocument(file, options); + // placeholder.file = file + // TODO: nda - modify loading doc so it only takes in options + // Docs.Create.LoadingDocument(options, ) + } + // copies the specified drag factory document export function copyDragFactory(dragFactory: Doc) { if (!dragFactory) return undefined; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d19874720..492513a61 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -196,6 +196,7 @@ export class CurrentUserUtils { makeIconTemplate(DocumentType.RTF, "text", { iconTemplate:DocumentType.LABEL, _showTitle: "creationDate"}), makeIconTemplate(DocumentType.IMG, "data", { iconTemplate:DocumentType.IMG, _height: undefined}), makeIconTemplate(DocumentType.COL, "icon", { iconTemplate:DocumentType.IMG}), + makeIconTemplate(DocumentType.COL, "icon", { iconTemplate:DocumentType.IMG}), makeIconTemplate(DocumentType.VID, "icon", { iconTemplate:DocumentType.IMG}), makeIconTemplate(DocumentType.BUTTON,"data", { iconTemplate:DocumentType.FONTICON}), //nasty hack .. templates are looked up exclusively by type -- but we want a template for a document with a certain field (transcription) .. so this hack and the companion hack in createCustomView does this for now diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 79f629072..1ff4f5ab8 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -449,48 +449,6 @@ export function CollectionSubView(moreProps?: X) { this.slowLoadDocuments(files, options, generatedDocuments, text, completed, e.clientX, e.clientY, addDocument).then(batch.end); } - /** - * Creates a placeholder doc view for files being uploaded and removes placeholder docs once files are uplodaded. - * - * @param files the files to upload that we want to create placeholders for - * @param options the document options (primarily the x and y coordinates to put doc) - * @param text in the case of youtube the text is the url to the video - * @returns a disposer action that removes the placeholders created after files get uploaded - */ - placeHolderDisposer = (files: File[] | string, options: DocumentOptions, text: string) => { - // TODO: nda - create a specialized view for placeholder upload with a spinner and ability to retry upload - let placeholders: Doc[] = []; - // handle yt case - if (typeof files === 'string') { - placeholders.push(Docs.Create.LoadingDocument('Loading...', text, 500, 500, { ...options })); - // placeholders.push(Docs.Create.TextDocument('Loading: ' + text, { ...options, title: text, _width: 400, _height: 30 })); - } else { - // every other doc type is an array of File - - // Get the file names as a text - let textStr = ''; - files.forEach(file => { - textStr += file.name + '\n'; - }); - placeholders.push(Docs.Create.LoadingDocument('Loading...', textStr, 500, 500, { ...options })); - - // placeholders.push(Docs.Create.TextDocument('Loading: \n' + textStr, { ...options, title: files.length + ' files', _width: 500, _height: files.length * 40 })); - } - // disposer action to remove placeholders once files are uploaded - const remove = action(() => { - if (!this.props.DataDoc) { - return; - } - for (let i = 0; i < placeholders.length; i++) { - Doc.RemoveDocFromList(this.props.DataDoc, 'data', placeholders[i]); - } - }); - placeholders.forEach(pl => { - this.addDocument(pl); - }); - return remove; - }; - slowLoadDocuments = async ( files: File[] | string, options: DocumentOptions, @@ -501,13 +459,31 @@ export function CollectionSubView(moreProps?: X) { clientY: number, addDocument: (doc: Doc | Doc[]) => boolean ) => { + // create placeholder docs + // inside placeholder docs have some func that + // TODO: once loading thing is moved it should update the x and y of the file it is placeholder for - const disposer = this.placeHolderDisposer(files, options, text); + let pileUpDoc = undefined; // const disposer = OverlayView.Instance.addElement(, { x: clientX - 125, y: clientY - 125 }); if (typeof files === 'string') { - generatedDocuments.push(...(await DocUtils.uploadYoutubeVideo(files, options))); + // uploadYoutubeVideo and similar should return a placeholder, one for each placeholder + // generatedDocuments.push(Docs.Create.LoadingDocument(files, options)); } else { - generatedDocuments.push(...(await DocUtils.uploadFilesToDocs(files, options))); + // uploadFilesToDocs and similar should return a placeholder, one for each placeholder + generatedDocuments.push( + ...files.map(file => { + const loading = Docs.Create.LoadingDocument(file, options); + // now that there is a doc do whatever slowload was going to do with that file + if (typeof file === 'string') { + // uploadYoutubeVideo and similar should return a placeholder, one for each placeholder + // (await DocUtils.uploadYoutubeVideo(files, options))); + } else { + // uploadFilesToDocs and similar should return a placeholder, one for each placeholder + DocUtils.uploadFileToDoc(file, {}, loading); + } + return loading; + }) + ); } if (generatedDocuments.length) { // Creating a dash document @@ -523,7 +499,8 @@ export function CollectionSubView(moreProps?: X) { if (completed) completed(set); else { if (isFreeformView && generatedDocuments.length > 1) { - addDocument(DocUtils.pileup(generatedDocuments, options.x as number, options.y as number)!); + pileUpDoc = DocUtils.pileup(generatedDocuments, options.x as number, options.y as number)!; + addDocument(pileUpDoc); } else { generatedDocuments.forEach(addDocument); } @@ -535,7 +512,6 @@ export function CollectionSubView(moreProps?: X) { alert('Document upload failed - possibly an unsupported file type.'); } } - disposer(); }; } diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index 0e0619241..9d4668dde 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -4,6 +4,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import * as React from 'react'; import './LoadingBox.scss'; import ReactLoading from 'react-loading'; +import { Docs, DocUtils } from '../../documents/Documents'; export interface LoadingBoxProps { title: string; @@ -16,6 +17,30 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { return FieldView.LayoutString(LoadingBox, fieldKey); } + componentDidMount() { + // const file = Docs.Create.filesToDocs.get(this.rootDoc); + // if (file) { + // console.log('Got to file'); + // Docs.Create.filesToDocs.delete(this.rootDoc); + // // now that there is a doc do whatever slowload was going to do with that file + // if (typeof file === 'string') { + // // uploadYoutubeVideo and similar should return a placeholder, one for each placeholder + // // (await DocUtils.uploadYoutubeVideo(files, options))); + // } else { + // // uploadFilesToDocs and similar should return a placeholder, one for each placeholder + // DocUtils.uploadFileToDoc(file, {}, this.rootDoc); + // } + // } else { + // // check if file now exists on server or not + // // if it does we need to retreieve it and create the appropriate doc (rest of what uploadFileToDoc was doing minus uploading) + // // if it doesn't display an error message "upload failed" + // } + // query endpoints to: + // check if file now exists on server or not + // if it does we need to retreieve it and create the appropriate doc (rest of what uploadFileToDoc was doing minus uploading) + // if it doesn't display an error message "upload failed" + } + constructor(props: any) { super(props); } -- cgit v1.2.3-70-g09d2 From 27945b9a931fa9504404174dd08964556dc3aea2 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Tue, 16 Aug 2022 21:16:03 -0400 Subject: added loading for diff doc types --- src/client/documents/Documents.ts | 47 ++++++++++++++++------ src/client/views/collections/CollectionSubView.tsx | 11 ++--- src/client/views/nodes/LoadingBox.scss | 5 +++ src/client/views/nodes/LoadingBox.tsx | 12 +++--- 4 files changed, 48 insertions(+), 27 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d8497e3af..e54fe16de 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -844,9 +844,9 @@ export namespace Docs { return viewDoc; } - export function ImageDocument(url: string | ImageField, options: DocumentOptions = {}) { + export function ImageDocument(url: string | ImageField, options: DocumentOptions = {}, overwriteDoc?: Doc) { const imgField = url instanceof ImageField ? url : new ImageField(url); - return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(imgField.url.href), ...options }); + return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(imgField.url.href), ...options }, undefined, undefined, undefined, overwriteDoc); } export function PresDocument(options: DocumentOptions = {}) { @@ -857,12 +857,12 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script ? script : undefined, { ...options, layout: fieldKey ? ScriptingBox.LayoutString(fieldKey) : undefined }); } - export function VideoDocument(url: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.VID), new VideoField(url), options); + export function VideoDocument(url: string, options: DocumentOptions = {}, overwriteDoc?: Doc) { + return InstanceFromProto(Prototypes.get(DocumentType.VID), new VideoField(url), options, undefined, undefined, undefined, overwriteDoc); } - export function YoutubeDocument(url: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.YOUTUBE), new YoutubeField(url), options); + export function YoutubeDocument(url: string, options: DocumentOptions = {}, overwriteDoc?: Doc) { + return InstanceFromProto(Prototypes.get(DocumentType.YOUTUBE), new YoutubeField(url), options, undefined, undefined, undefined, overwriteDoc); } export function WebCamDocument(url: string, options: DocumentOptions = {}) { @@ -877,8 +877,16 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), '', options); } - export function AudioDocument(url: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(url), { ...options, backgroundColor: ComputedField.MakeFunction("this._mediaState === 'playing' ? 'green':'gray'") as any }); + export function AudioDocument(url: string, options: DocumentOptions = {}, overwriteDoc?: Doc) { + return InstanceFromProto( + Prototypes.get(DocumentType.AUDIO), + new AudioField(url), + { ...options, backgroundColor: ComputedField.MakeFunction("this._mediaState === 'playing' ? 'green':'gray'") as any }, + undefined, + undefined, + undefined, + overwriteDoc + ); } export function RecordingDocument(url: string, options: DocumentOptions = {}) { @@ -895,8 +903,10 @@ export namespace Docs { export const filesToDocs = new Map(); - export function LoadingDocument(file: File, options: DocumentOptions, ytString?: string) { - const loading = InstanceFromProto(Prototypes.get(DocumentType.LOADING), file.name, { _height: 300, _width: 300, ...options }); + export function LoadingDocument(file: File | string, options: DocumentOptions, ytString?: string) { + const fileName = typeof file == 'string' ? file : file.name; + options.title = fileName; + const loading = InstanceFromProto(Prototypes.get(DocumentType.LOADING), fileName, { _height: 150, _width: 150, ...options }); // filesToDocs.set(loading, file); return loading; } @@ -1114,8 +1124,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) }); } - export function DataVizDocument(url: string, options?: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.DATAVIZ), new CsvField(url), { title: 'Data Viz', ...options }); + export function DataVizDocument(url: string, options?: DocumentOptions, overwriteDoc?: Doc) { + return InstanceFromProto(Prototypes.get(DocumentType.DATAVIZ), new CsvField(url), { title: 'Data Viz', ...options }, undefined, undefined, undefined, overwriteDoc); } export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { @@ -1809,6 +1819,18 @@ export namespace DocUtils { } return generatedDocuments; } + + export function uploadYoutubeVideoLoading(videoId: string, options: DocumentOptions, overwriteDoc?: Doc) { + const generatedDocuments: Doc[] = []; + Networking.UploadYoutubeToServer(videoId).then(upfiles => { + const { + source: { name, type }, + result, + } = upfiles.lastElement(); + name && type && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); + }); + } + export async function uploadFilesToDocs(files: File[], options: DocumentOptions) { const generatedDocuments: Doc[] = []; const upfiles = await Networking.UploadFilesToServer(files); @@ -1828,7 +1850,6 @@ export namespace DocUtils { source: { name, type }, result, } = upfiles.lastElement(); - console.log(name, type); name && type && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); }); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 1ff4f5ab8..30467efa0 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -468,19 +468,16 @@ export function CollectionSubView(moreProps?: X) { if (typeof files === 'string') { // uploadYoutubeVideo and similar should return a placeholder, one for each placeholder // generatedDocuments.push(Docs.Create.LoadingDocument(files, options)); + const loading = Docs.Create.LoadingDocument(files, options); + generatedDocuments.push(loading); + DocUtils.uploadYoutubeVideoLoading(files, {}, loading); } else { // uploadFilesToDocs and similar should return a placeholder, one for each placeholder generatedDocuments.push( ...files.map(file => { const loading = Docs.Create.LoadingDocument(file, options); // now that there is a doc do whatever slowload was going to do with that file - if (typeof file === 'string') { - // uploadYoutubeVideo and similar should return a placeholder, one for each placeholder - // (await DocUtils.uploadYoutubeVideo(files, options))); - } else { - // uploadFilesToDocs and similar should return a placeholder, one for each placeholder - DocUtils.uploadFileToDoc(file, {}, loading); - } + DocUtils.uploadFileToDoc(file, {}, loading); return loading; }) ); diff --git a/src/client/views/nodes/LoadingBox.scss b/src/client/views/nodes/LoadingBox.scss index 239faa78e..e8890cd82 100644 --- a/src/client/views/nodes/LoadingBox.scss +++ b/src/client/views/nodes/LoadingBox.scss @@ -5,3 +5,8 @@ justify-content: center; background-color: #fdfdfd; } + +.text { + text-overflow: ellipsis; + text-align: center; +} diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index 9d4668dde..96620aff9 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -4,12 +4,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import * as React from 'react'; import './LoadingBox.scss'; import ReactLoading from 'react-loading'; -import { Docs, DocUtils } from '../../documents/Documents'; - -export interface LoadingBoxProps { - title: string; - text: string; -} +import { StrCast } from '../../../fields/Types'; @observer export class LoadingBox extends ViewBoxAnnotatableComponent() { @@ -18,6 +13,7 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { } componentDidMount() { + console.log(this.rootDoc); // const file = Docs.Create.filesToDocs.get(this.rootDoc); // if (file) { // console.log('Got to file'); @@ -48,7 +44,9 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { render() { return (
- Loading: {this.dataDoc.text} +

Loading:

+

+

{StrCast(this.rootDoc.title)}

); -- cgit v1.2.3-70-g09d2 From 94c38310c6b54d93e907007f20ba032d12697ca0 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Thu, 18 Aug 2022 12:33:34 -0400 Subject: fixed sizing bug --- src/client/documents/Documents.ts | 14 +++++-------- src/client/views/collections/CollectionSubView.tsx | 2 ++ src/client/views/nodes/LoadingBox.tsx | 24 ++++++++++++++++++---- 3 files changed, 27 insertions(+), 13 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e54fe16de..f3ab7c788 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -827,9 +827,12 @@ export namespace Docs { viewFirstProps.author = Doc.CurrentUserEmail; let viewDoc: Doc; if (placeholderDoc) { + placeholderDoc._height = Number(options._height); + placeholderDoc._width = Number(options._width); viewDoc = Doc.assign(placeholderDoc, viewFirstProps, true, true); + } else { + viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true); } - viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true); Doc.assign(viewDoc, viewProps, true, true); ![DocumentType.LINK, DocumentType.MARKER, DocumentType.LABEL].includes(viewDoc.type as any) && DocUtils.MakeLinkToActiveAudio(() => viewDoc); @@ -901,7 +904,7 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COLOR), '', options); } - export const filesToDocs = new Map(); + export const filesToDocs = new Map(); export function LoadingDocument(file: File | string, options: DocumentOptions, ytString?: string) { const fileName = typeof file == 'string' ? file : file.name; @@ -1854,13 +1857,6 @@ export namespace DocUtils { }); } - export function generatePlaceHolder(file: File, options: DocumentOptions) { - return Docs.Create.LoadingDocument(file, options); - // placeholder.file = file - // TODO: nda - modify loading doc so it only takes in options - // Docs.Create.LoadingDocument(options, ) - } - // copies the specified drag factory document export function copyDragFactory(dragFactory: Doc) { if (!dragFactory) return undefined; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 30467efa0..fd2c722d2 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -470,6 +470,7 @@ export function CollectionSubView(moreProps?: X) { // generatedDocuments.push(Docs.Create.LoadingDocument(files, options)); const loading = Docs.Create.LoadingDocument(files, options); generatedDocuments.push(loading); + Docs.Create.filesToDocs.set(loading, files); DocUtils.uploadYoutubeVideoLoading(files, {}, loading); } else { // uploadFilesToDocs and similar should return a placeholder, one for each placeholder @@ -477,6 +478,7 @@ export function CollectionSubView(moreProps?: X) { ...files.map(file => { const loading = Docs.Create.LoadingDocument(file, options); // now that there is a doc do whatever slowload was going to do with that file + Docs.Create.filesToDocs.set(loading, file); DocUtils.uploadFileToDoc(file, {}, loading); return loading; }) diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index 96620aff9..249461b67 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -5,6 +5,8 @@ import * as React from 'react'; import './LoadingBox.scss'; import ReactLoading from 'react-loading'; import { StrCast } from '../../../fields/Types'; +import { computed, observable } from 'mobx'; +import { Docs } from '../../documents/Documents'; @observer export class LoadingBox extends ViewBoxAnnotatableComponent() { @@ -12,6 +14,12 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { return FieldView.LayoutString(LoadingBox, fieldKey); } + @computed + private get isLoading() { + const file = Docs.Create.filesToDocs.get(this.rootDoc); + return file ? true : false; + } + componentDidMount() { console.log(this.rootDoc); // const file = Docs.Create.filesToDocs.get(this.rootDoc); @@ -44,10 +52,18 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { render() { return (
-

Loading:

-

-

{StrCast(this.rootDoc.title)}

- + {this.isLoading ? ( +
+

Loading:

+

+ {StrCast(this.rootDoc.title)} + +
+ ) : ( +
+ Error Loading File: {StrCast(this.rootDoc.title)} +
+ )}
); } -- cgit v1.2.3-70-g09d2 From b7c4d65a3bf04ff7d2c10d93be282a1b0a4650b3 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Fri, 19 Aug 2022 12:32:23 -0400 Subject: added comments, cleaned up code, could not get spinner to center --- src/client/documents/Documents.ts | 8 ++- src/client/views/collections/CollectionSubView.tsx | 4 +- src/client/views/nodes/LoadingBox.scss | 21 +++++++ src/client/views/nodes/LoadingBox.tsx | 64 ++++++++++------------ 4 files changed, 58 insertions(+), 39 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f3ab7c788..9e140ccd1 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -815,6 +815,7 @@ export namespace Docs { dataProps[fieldKey + '-annotations'] = new List(); dataProps[fieldKey + '-sidebar'] = new List(); + // users placeholderDoc as proto if it exists const dataDoc = Doc.assign(placeholderDoc ? Doc.GetProto(placeholderDoc) : Doc.MakeDelegate(proto, protoId), dataProps, undefined, true); if (placeholderDoc) { @@ -826,6 +827,7 @@ export namespace Docs { viewFirstProps['acl-Override'] = 'None'; viewFirstProps.author = Doc.CurrentUserEmail; let viewDoc: Doc; + // determines whether viewDoc should be created using placeholder Doc or deafult if (placeholderDoc) { placeholderDoc._height = Number(options._height); placeholderDoc._width = Number(options._width); @@ -904,13 +906,13 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COLOR), '', options); } - export const filesToDocs = new Map(); + // Mapping of all loading docs to files, i.e. keeps track of files being uploaded in current session + export const docsToFiles = new Map(); export function LoadingDocument(file: File | string, options: DocumentOptions, ytString?: string) { const fileName = typeof file == 'string' ? file : file.name; options.title = fileName; - const loading = InstanceFromProto(Prototypes.get(DocumentType.LOADING), fileName, { _height: 150, _width: 150, ...options }); - // filesToDocs.set(loading, file); + const loading = InstanceFromProto(Prototypes.get(DocumentType.LOADING), fileName, { _height: 150, _width: 200, ...options }); return loading; } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index fd2c722d2..eef485b95 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -470,7 +470,7 @@ export function CollectionSubView(moreProps?: X) { // generatedDocuments.push(Docs.Create.LoadingDocument(files, options)); const loading = Docs.Create.LoadingDocument(files, options); generatedDocuments.push(loading); - Docs.Create.filesToDocs.set(loading, files); + Docs.Create.docsToFiles.set(loading, files); DocUtils.uploadYoutubeVideoLoading(files, {}, loading); } else { // uploadFilesToDocs and similar should return a placeholder, one for each placeholder @@ -478,7 +478,7 @@ export function CollectionSubView(moreProps?: X) { ...files.map(file => { const loading = Docs.Create.LoadingDocument(file, options); // now that there is a doc do whatever slowload was going to do with that file - Docs.Create.filesToDocs.set(loading, file); + Docs.Create.docsToFiles.set(loading, file); DocUtils.uploadFileToDoc(file, {}, loading); return loading; }) diff --git a/src/client/views/nodes/LoadingBox.scss b/src/client/views/nodes/LoadingBox.scss index e8890cd82..f6912f547 100644 --- a/src/client/views/nodes/LoadingBox.scss +++ b/src/client/views/nodes/LoadingBox.scss @@ -6,7 +6,28 @@ background-color: #fdfdfd; } +.textContainer { + margin: 5px; +} + +.textContainer { + justify-content: center; + align-content: center; +} + +.textContainer, .text { + overflow: hidden; text-overflow: ellipsis; + max-width: 80%; + text-align: center; +} + +.headerText { + text-align: center; + font-weight: bold; +} + +.spinner { text-align: center; } diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index 249461b67..ab8878fc1 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -5,46 +5,42 @@ import * as React from 'react'; import './LoadingBox.scss'; import ReactLoading from 'react-loading'; import { StrCast } from '../../../fields/Types'; -import { computed, observable } from 'mobx'; +import { computed } from 'mobx'; import { Docs } from '../../documents/Documents'; +/** + * LoadingBox Class represents a placeholder doc for documents that are currently + * being uploaded to the server and being fetched by the client. The LoadingBox doc is then used to + * generate the actual type of doc that is required once the document has been successfully uploaded. + * + * Design considerations: + * We are using the docToFiles map in Documents to keep track of all files being uploaded in one session of the client. + * If the file is not found we assume an error has occurred with the file upload, e.g. it has been interrupted by a client refresh + * or network issues. The docToFiles essentially gets reset everytime the page is refreshed. + * + * TODOs: + * 1) ability to query server to retrieve files that already exist if users upload duplicate files. + * 2) ability to restart upload if there is an error + * 3) detect network error and notify the user + * 4 )if file upload gets interrupted, it still gets uploaded to the server if there are no network interruptions which leads to unused space. this could be + * handled with (1) + * + * @author naafiyan + */ @observer export class LoadingBox extends ViewBoxAnnotatableComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LoadingBox, fieldKey); } - @computed - private get isLoading() { - const file = Docs.Create.filesToDocs.get(this.rootDoc); + /** + * Returns true if file is uploading, false otherwise + */ + @computed private get isLoading(): boolean { + const file = Docs.Create.docsToFiles.get(this.rootDoc); return file ? true : false; } - componentDidMount() { - console.log(this.rootDoc); - // const file = Docs.Create.filesToDocs.get(this.rootDoc); - // if (file) { - // console.log('Got to file'); - // Docs.Create.filesToDocs.delete(this.rootDoc); - // // now that there is a doc do whatever slowload was going to do with that file - // if (typeof file === 'string') { - // // uploadYoutubeVideo and similar should return a placeholder, one for each placeholder - // // (await DocUtils.uploadYoutubeVideo(files, options))); - // } else { - // // uploadFilesToDocs and similar should return a placeholder, one for each placeholder - // DocUtils.uploadFileToDoc(file, {}, this.rootDoc); - // } - // } else { - // // check if file now exists on server or not - // // if it does we need to retreieve it and create the appropriate doc (rest of what uploadFileToDoc was doing minus uploading) - // // if it doesn't display an error message "upload failed" - // } - // query endpoints to: - // check if file now exists on server or not - // if it does we need to retreieve it and create the appropriate doc (rest of what uploadFileToDoc was doing minus uploading) - // if it doesn't display an error message "upload failed" - } - constructor(props: any) { super(props); } @@ -53,15 +49,15 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { return (
{this.isLoading ? ( -
-

Loading:

-

+
+

Loading:

{StrCast(this.rootDoc.title)}
) : ( -
- Error Loading File: {StrCast(this.rootDoc.title)} +
+

Error Loading File:

+ {StrCast(this.rootDoc.title)}
)}
-- cgit v1.2.3-70-g09d2 From 5b20224b59f4a6ebc02fbd0a68441bb241c68d63 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Fri, 19 Aug 2022 14:37:32 -0400 Subject: cleaned up comments --- src/client/views/collections/CollectionSubView.tsx | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index d7d988c19..e70cfb13c 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -460,18 +460,13 @@ export function CollectionSubView(moreProps?: X) { // create placeholder docs // inside placeholder docs have some func that - // TODO: once loading thing is moved it should update the x and y of the file it is placeholder for let pileUpDoc = undefined; - // const disposer = OverlayView.Instance.addElement(, { x: clientX - 125, y: clientY - 125 }); if (typeof files === 'string') { - // uploadYoutubeVideo and similar should return a placeholder, one for each placeholder - // generatedDocuments.push(Docs.Create.LoadingDocument(files, options)); const loading = Docs.Create.LoadingDocument(files, options); generatedDocuments.push(loading); Docs.Create.docsToFiles.set(loading, files); DocUtils.uploadYoutubeVideoLoading(files, {}, loading); } else { - // uploadFilesToDocs and similar should return a placeholder, one for each placeholder generatedDocuments.push( ...files.map(file => { const loading = Docs.Create.LoadingDocument(file, options); -- cgit v1.2.3-70-g09d2 From 7f2556568ab635274c483d102fa4555d12e14835 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 30 Aug 2022 13:55:41 -0400 Subject: fixed loadingDocument issues with overwriting height with NaN and setting 'data' field unnecessarily and at the expense of being able to set it for replacement docs when using animation frames --- src/client/documents/Documents.ts | 34 ++++++++++------------ src/client/views/GlobalKeyHandler.ts | 9 +++--- src/client/views/collections/CollectionSubView.tsx | 6 ++-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 6 ++-- src/client/views/nodes/LoadingBox.tsx | 29 ++++-------------- 5 files changed, 30 insertions(+), 54 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9446eb70c..b22e16633 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -653,7 +653,7 @@ export namespace Docs { [ DocumentType.LOADING, { - layout: { view: LoadingBox, dataField: defaultDataKey }, + layout: { view: LoadingBox, dataField: '' }, options: { _fitWidth: true, _fitHeight: true, nativeDimModifiable: true, links: '@links(self)' }, }, ], @@ -806,14 +806,15 @@ export namespace Docs { dataProps.isPrototype = true; dataProps.author = Doc.CurrentUserEmail; dataProps.creationDate = new DateField(); - dataProps[`${fieldKey}-lastModified`] = new DateField(); - - dataProps[fieldKey] = data; - - // so that the list of annotations is already initialised, prevents issues in addonly. - // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do. - dataProps[fieldKey + '-annotations'] = new List(); - dataProps[fieldKey + '-sidebar'] = new List(); + if (fieldKey) { + dataProps[`${fieldKey}-lastModified`] = new DateField(); + dataProps[fieldKey] = data; + + // so that the list of annotations is already initialised, prevents issues in addonly. + // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do. + dataProps[fieldKey + '-annotations'] = new List(); + dataProps[fieldKey + '-sidebar'] = new List(); + } // users placeholderDoc as proto if it exists const dataDoc = Doc.assign(placeholderDoc ? Doc.GetProto(placeholderDoc) : Doc.MakeDelegate(proto, protoId), dataProps, undefined, true); @@ -829,8 +830,8 @@ export namespace Docs { let viewDoc: Doc; // determines whether viewDoc should be created using placeholder Doc or default if (placeholderDoc) { - placeholderDoc._height = Number(options._height); - placeholderDoc._width = Number(options._width); + placeholderDoc._height = options._height !== undefined ? Number(options._height) : undefined; + placeholderDoc._width = options._width !== undefined ? Number(options._width) : undefined; viewDoc = Doc.assign(placeholderDoc, viewFirstProps, true, true); } else { viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true); @@ -846,6 +847,7 @@ export namespace Docs { updateCachedAcls(dataDoc); updateCachedAcls(viewDoc); + return viewDoc; } @@ -905,15 +907,8 @@ export namespace Docs { export function ColorDocument(options: DocumentOptions = {}) { return InstanceFromProto(Prototypes.get(DocumentType.COLOR), '', options); } - - // Mapping of all loading docs to files, i.e. keeps track of files being uploaded in current session - export const docsToFiles = new Map(); - export function LoadingDocument(file: File | string, options: DocumentOptions, ytString?: string) { - const fileName = typeof file == 'string' ? file : file.name; - options.title = fileName; - const loading = InstanceFromProto(Prototypes.get(DocumentType.LOADING), fileName, { _height: 150, _width: 200, ...options }); - return loading; + return InstanceFromProto(Prototypes.get(DocumentType.LOADING), undefined, { _height: 150, _width: 200, title: typeof file == 'string' ? file : file.name, ...options }, undefined, ''); } export function RTFDocument(field: RichTextField, options: DocumentOptions = {}, fieldKey: string = 'text') { @@ -1756,6 +1751,7 @@ export namespace DocUtils { const full = { ...options, _width: 400, title: name }; const pathname = Utils.prepend(result.accessPaths.agnostic.client); const doc = await DocUtils.DocumentFromType(type, pathname, full, rootDoc); + rootDoc && (rootDoc.isLoading = undefined); if (doc) { const proto = Doc.GetProto(doc); proto.text = result.rawText; diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 88ce457c6..50518eec1 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -84,6 +84,7 @@ export class KeyManager { }); private unmodified = action((keyname: string, e: KeyboardEvent) => { + const hasFffView = SelectionManager.Views().some(dv => dv.props.CollectionFreeFormDocumentView?.()); switch (keyname) { case 'u': if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') { @@ -160,16 +161,16 @@ export class KeyManager { break; case 'arrowleft': UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), 'nudge left'); - return { stopPropagation: true, preventDefault: true }; + return { stopPropagation: hasFffView, preventDefault: hasFffView }; case 'arrowright': UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), 'nudge right'); - return { stopPropagation: true, preventDefault: true }; + return { stopPropagation: hasFffView, preventDefault: hasFffView }; case 'arrowup': UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), 'nudge up'); - return { stopPropagation: true, preventDefault: true }; + return { stopPropagation: hasFffView, preventDefault: hasFffView }; case 'arrowdown': UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), 'nudge down'); - return { stopPropagation: true, preventDefault: true }; + return { stopPropagation: hasFffView, preventDefault: hasFffView }; } return { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index e70cfb13c..4227955ef 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -464,14 +464,13 @@ export function CollectionSubView(moreProps?: X) { if (typeof files === 'string') { const loading = Docs.Create.LoadingDocument(files, options); generatedDocuments.push(loading); - Docs.Create.docsToFiles.set(loading, files); + loading.isLoading = true; DocUtils.uploadYoutubeVideoLoading(files, {}, loading); } else { generatedDocuments.push( ...files.map(file => { const loading = Docs.Create.LoadingDocument(file, options); - // now that there is a doc do whatever slowload was going to do with that file - Docs.Create.docsToFiles.set(loading, file); + loading.isLoading = true; DocUtils.uploadFileToDoc(file, {}, loading); return loading; }) @@ -516,5 +515,4 @@ import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes' import { DragManager, dropActionType } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; -import { OverlayView } from '../OverlayView'; import { CollectionView, CollectionViewProps } from './CollectionView'; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index cfa4bb160..7907470dc 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -35,7 +35,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { export class CollectionFreeFormDocumentView extends DocComponent() { public static animFields: { key: string; val?: number }[] = [{ key: '_height' }, { key: '_width' }, { key: 'x' }, { key: 'y' }, { key: '_scrollTop' }, { key: 'opacity', val: 1 }, { key: 'viewScale', val: 1 }, { key: 'panX' }, { key: 'panY' }]; // fields that are configured to be animatable using animation frames public static animStringFields = ['backgroundColor', 'color']; // fields that are configured to be animatable using animation frames - public static animDataFields = ['data', 'text']; // fields that are configured to be animatable using animation frames + public static animDataFields = (doc: Doc) => (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames @observable _animPos: number[] | undefined = undefined; @observable _contentView: DocumentView | undefined | null; get displayName() { @@ -121,7 +121,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { + CollectionFreeFormDocumentView.animDataFields(doc).forEach(val => { const findexed = Cast(doc[`${val}-indexed`], listSpec(InkField), null); findexed?.length <= timecode + 1 && findexed.push(undefined as any); }); @@ -173,7 +173,7 @@ export class CollectionFreeFormDocumentView extends DocComponent (doc[val.key] = ComputedField.MakeInterpolatedNumber(val.key, 'activeFrame', doc, currTimecode, val.val))); CollectionFreeFormDocumentView.animStringFields.forEach(val => (doc[val] = ComputedField.MakeInterpolatedString(val, 'activeFrame', doc, currTimecode))); - CollectionFreeFormDocumentView.animDataFields.forEach(val => (Doc.GetProto(doc)[val] = ComputedField.MakeInterpolatedDataField(val, 'activeFrame', Doc.GetProto(doc), currTimecode))); + CollectionFreeFormDocumentView.animDataFields(doc).forEach(val => (Doc.GetProto(doc)[val] = ComputedField.MakeInterpolatedDataField(val, 'activeFrame', Doc.GetProto(doc), currTimecode))); const targetDoc = doc.type === DocumentType.RTF ? Doc.GetProto(doc) : doc; // data fields, like rtf 'text' exist on the data doc, so doc !== targetDoc && (targetDoc.context = doc.context); // the computed fields don't see the layout doc -- need to copy the context to the data doc (HACK!!!) and set the activeFrame on the data doc (HACK!!!) targetDoc.activeFrame = ComputedField.MakeFunction('self.context?._currentFrame||0'); diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index 90bf90095..f3243f6cd 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -35,33 +35,14 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { return FieldView.LayoutString(LoadingBox, fieldKey); } - /** - * Returns true if file is uploading, false otherwise - */ - @computed private get isLoading(): boolean { - const file = Docs.Create.docsToFiles.get(this.rootDoc); - return file ? true : false; - } - - constructor(props: any) { - super(props); - } - render() { return (
- {this.isLoading ? ( -
-

Loading:

- {StrCast(this.rootDoc.title)} - -
- ) : ( -
-

Error Loading File:

- {StrCast(this.rootDoc.title)} -
- )} +
+

{this.rootDoc.isLoading ? 'Loading:' : 'Error Loading File:'}

+ {StrCast(this.rootDoc.title)} + {!this.rootDoc.isLoading ? null : } +
); } -- cgit v1.2.3-70-g09d2 From 65026fdb919132f6046b45fc3b0490df2e5ad2fe Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 14 Sep 2022 11:12:29 -0400 Subject: changed docking view thumbnails to be imagefields, not docs. allowed docking view to be nested to avoid crashes before when they became nested. fixed dropping docs with dropAction of 'alias' to never remove them. fixed clearing startLink to not deselect when link is already started --- src/client/util/SelectionManager.ts | 2 +- src/client/views/DashboardView.tsx | 4 +-- src/client/views/DocumentDecorations.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 32 ++++++++++++++++------ src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 1 + src/client/views/collections/TabDocView.tsx | 2 +- src/client/views/nodes/DocumentLinksButton.tsx | 4 +-- src/client/views/nodes/LinkDocPreview.tsx | 2 +- src/client/views/topbar/TopBar.tsx | 4 +-- 10 files changed, 36 insertions(+), 19 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 7a555d5f8..a3d6f5227 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -91,7 +91,7 @@ export namespace SelectionManager { } export function Views(): Array { - return Array.from(manager.SelectedViews.keys()).filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking); + return Array.from(manager.SelectedViews.keys()); //.filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking); } export function SelectedSchemaDoc(): Doc | undefined { return manager.SelectedSchemaDocument; diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 6415601f1..12fc3133d 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -50,7 +50,7 @@ export class DashboardView extends React.Component { this.selectedDashboardGroup = group; }; - clickDashboard = async (e: React.MouseEvent, dashboard: Doc) => { + clickDashboard = (e: React.MouseEvent, dashboard: Doc) => { if (e.detail === 2) { Doc.AddDocToList(Doc.MySharedDocs, 'viewed', dashboard); Doc.ActiveDashboard = dashboard; @@ -156,7 +156,7 @@ export class DashboardView extends React.Component {
{this.getDashboards().map(dashboard => { - const href = ImageCast((dashboard.thumb as Doc)?.data)?.url.href; + const href = ImageCast(dashboard.thumb)?.url.href; return (
{ const views = SelectionManager.Views() .slice() - .filter(v => v); + .filter(v => v && v.props.renderDepth > 0); if (forceDeleteOrIconify === false && this._iconifyBatch) return; this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false; if (!this._iconifyBatch) { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 10b54edad..31c839af7 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -6,7 +6,7 @@ import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; -import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { inheritParentAcls } from '../../../fields/util'; import { emptyFunction, incrementTitleCopy } from '../../../Utils'; @@ -56,7 +56,7 @@ export class CollectionDockingView extends CollectionSubView() { constructor(props: SubCollectionViewProps) { super(props); - runInAction(() => (CollectionDockingView.Instance = this)); + if (this.props.renderDepth < 0) runInAction(() => (CollectionDockingView.Instance = this)); //Why is this here? (window as any).React = React; (window as any).ReactDOM = ReactDOM; @@ -73,7 +73,7 @@ export class CollectionDockingView extends CollectionSubView() { public StartOtherDrag = (e: { pageX: number; pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => { this._flush = this._flush ?? UndoManager.StartBatch('golden layout drag'); const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) : { type: 'row', content: dragDocs.map(doc => CollectionDockingView.makeDocumentConfig(doc)) }; - const dragSource = this._goldenLayout.createDragSource(document.createElement('div'), config); + const dragSource = CollectionDockingView.Instance?._goldenLayout.createDragSource(document.createElement('div'), config); this.tabDragStart(dragSource, finishDrag); dragSource._dragListener.onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 }); }; @@ -395,10 +395,10 @@ export class CollectionDockingView extends CollectionSubView() { const _height = Number(getComputedStyle(content).height.replace('px', '')); return CollectionFreeFormView.UpdateIcon(this.layoutDoc[Id] + '-icon' + new Date().getTime(), content, _width, _height, _width, _height, 0, 1, true, this.layoutDoc[Id] + '-icon', (iconFile, _nativeWidth, _nativeHeight) => { const img = Docs.Create.ImageDocument(new ImageField(iconFile), { title: this.rootDoc.title + '-icon', _width, _height, _nativeWidth, _nativeHeight }); - const proto = Cast(img.proto, Doc, null)!; - proto['data-nativeWidth'] = _width; - proto['data-nativeHeight'] = _height; - this.dataDoc.thumb = img; + const proto = this.dataDoc; // Cast(img.proto, Doc, null)!; + proto['thumb-nativeWidth'] = _width; + proto['thumb-nativeHeight'] = _height; + this.dataDoc.thumb = new ImageField(iconFile); }); } } @@ -532,7 +532,23 @@ export class CollectionDockingView extends CollectionSubView() { }; render() { - return
; + const href = ImageCast(this.rootDoc.thumb)?.url.href; + return this.props.renderDepth > -1 ? ( +
+ {href ? ( + docDragData.draggedDocuments[i] === d); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 1ee77d4ce..0a06b6e00 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -116,6 +116,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent; + case CollectionViewType.Docking: return ; case CollectionViewType.Schema: return ; case CollectionViewType.Docking: return ; case CollectionViewType.Tree: return ; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 46386fa71..b9262763f 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -400,7 +400,7 @@ export class TabDocView extends React.Component { hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap); @computed get docView() { - return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? null : ( + return !this._activated || !this._document ? null : ( <> ) : null} {this.props.InMenu && this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again -
+
) : null} diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 93ca22d5d..f50524e4e 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -249,7 +249,7 @@ export class LinkDocPreview extends React.Component { searchFilterDocs={returnEmptyDoclist} ContainingCollectionDoc={undefined} ContainingCollectionView={undefined} - renderDepth={-1} + renderDepth={0} suppressSetHeight={true} PanelWidth={this.width} PanelHeight={this.height} diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index cbcfed06f..096b2561f 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -28,12 +28,12 @@ import { ReportManager } from '../../util/ReportManager'; @observer export class TopBar extends React.Component { navigateToHome = () => { - CollectionDockingView.Instance?.CaptureThumbnail()?.then(() => { + (CollectionDockingView.Instance?.CaptureThumbnail() ?? new Promise(res => res())).then(() => { Doc.ActivePage = 'home'; DashboardView.closeActiveDashboard(); // bcz: if we do this, we need some other way to keep track, for user convenience, of the last dashboard in use }); }; - + render() { const activeDashboard = Doc.ActiveDashboard; return ( -- cgit v1.2.3-70-g09d2 From 945c0cd12fb2a792d10800f81b52cbac8aa12a41 Mon Sep 17 00:00:00 2001 From: mehekj Date: Tue, 20 Sep 2022 11:52:44 -0400 Subject: display error instead of infinitely loading after refresh --- src/client/documents/Documents.ts | 4 +++- src/client/views/collections/CollectionSubView.tsx | 2 ++ src/client/views/nodes/LoadingBox.tsx | 9 +++++++++ src/fields/Doc.ts | 22 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 14e6fe5bb..4f652b6e4 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1758,7 +1758,7 @@ export namespace DocUtils { const full = { ...options, _width: 400, title: name }; const pathname = Utils.prepend(result.accessPaths.agnostic.client); const doc = await DocUtils.DocumentFromType(type, pathname, full, rootDoc); - rootDoc && (rootDoc.isLoading = undefined); + rootDoc && (rootDoc.isLoading = undefined) && Doc.removeCurrentlyLoading(rootDoc); if (doc) { const proto = Doc.GetProto(doc); proto.text = result.rawText; @@ -1840,6 +1840,7 @@ export namespace DocUtils { if (overwriteDoc) { overwriteDoc.isLoading = false; overwriteDoc.errorMessage = (result as any).message; + Doc.removeCurrentlyLoading(overwriteDoc); } } else name && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); }); @@ -1868,6 +1869,7 @@ export namespace DocUtils { if (overwriteDoc) { overwriteDoc.isLoading = false; overwriteDoc.errorMessage = (result as any).message; + Doc.removeCurrentlyLoading(overwriteDoc); } } else name && type && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); }); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 7fc1a800b..3ae965af0 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -465,12 +465,14 @@ export function CollectionSubView(moreProps?: X) { const loading = Docs.Create.LoadingDocument(files, options); generatedDocuments.push(loading); loading.isLoading = true; + Doc.addCurrentlyLoading(loading); DocUtils.uploadYoutubeVideoLoading(files, {}, loading); } else { generatedDocuments.push( ...files.map(file => { const loading = Docs.Create.LoadingDocument(file, options); loading.isLoading = true; + Doc.addCurrentlyLoading(loading); DocUtils.uploadFileToDoc(file, {}, loading); return loading; }) diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index acf728ebb..220cd0880 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -1,6 +1,8 @@ +import { observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import ReactLoading from 'react-loading'; +import { Doc } from '../../../fields/Doc'; import { StrCast } from '../../../fields/Types'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { FieldView, FieldViewProps } from './FieldView'; @@ -33,6 +35,13 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { return FieldView.LayoutString(LoadingBox, fieldKey); } + componentDidMount() { + if (!Doc.CurrentlyLoading || !Doc.CurrentlyLoading.includes(this.rootDoc)) { + this.rootDoc.isLoading = false; + this.rootDoc.errorMessage = 'Upload was interrupted, please try again'; + } + } + render() { return (
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index cf505c45b..74a3d8cf2 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -149,6 +149,28 @@ export class Doc extends RefField { public static set MainDocId(id: string | undefined) { this.mainDocId = id; } + + @observable public static CurrentlyLoading: Doc[]; + // removes from currently loading display + @action + public static removeCurrentlyLoading(doc: Doc) { + if (Doc.CurrentlyLoading) { + const index = Doc.CurrentlyLoading.indexOf(doc); + index !== -1 && Doc.CurrentlyLoading.splice(index, 1); + } + } + + // adds doc to currently loading display + @action + public static addCurrentlyLoading(doc: Doc) { + if (!Doc.CurrentlyLoading) { + Doc.CurrentlyLoading = []; + } + if (Doc.CurrentlyLoading.indexOf(doc) === -1) { + Doc.CurrentlyLoading.push(doc); + } + } + @observable public static GuestDashboard: Doc | undefined; @observable public static GuestTarget: Doc | undefined; @observable public static GuestMobile: Doc | undefined; -- cgit v1.2.3-70-g09d2 From 48e0885b405cbfe728b1eda78efc19e15a104426 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 22 Sep 2022 16:00:17 -0400 Subject: fixed error messages on loading to not generate temporary error message when there is no error. --- src/client/documents/Documents.ts | 22 ++++++---------------- src/client/views/collections/CollectionSubView.tsx | 2 -- src/client/views/nodes/LoadingBox.tsx | 12 +++++------- 3 files changed, 11 insertions(+), 25 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 029c3033d..f046af684 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -908,7 +908,7 @@ export namespace Docs { export function ColorDocument(options: DocumentOptions = {}) { return InstanceFromProto(Prototypes.get(DocumentType.COLOR), '', options); } - export function LoadingDocument(file: File | string, options: DocumentOptions, ytString?: string) { + export function LoadingDocument(file: File | string, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.LOADING), undefined, { _height: 150, _width: 200, title: typeof file == 'string' ? file : file.name, ...options }, undefined, ''); } @@ -1758,7 +1758,6 @@ export namespace DocUtils { const full = { ...options, _width: 400, title: name }; const pathname = Utils.prepend(result.accessPaths.agnostic.client); const doc = await DocUtils.DocumentFromType(type, pathname, full, rootDoc); - rootDoc && (rootDoc.isLoading = undefined) && Doc.removeCurrentlyLoading(rootDoc); if (doc) { const proto = Doc.GetProto(doc); proto.text = result.rawText; @@ -1790,6 +1789,9 @@ export namespace DocUtils { if (Upload.isVideoInformation(result)) { proto['data-duration'] = result.duration; } + if (rootDoc) { + Doc.removeCurrentlyLoading(rootDoc); + } generatedDocuments.push(doc); } } @@ -1818,17 +1820,6 @@ export namespace DocUtils { return tbox; } - export async function uploadYoutubeVideo(videoId: string, options: DocumentOptions) { - const generatedDocuments: Doc[] = []; - for (const { - source: { name, type }, - result, - } of await Networking.UploadYoutubeToServer(videoId)) { - name && processFileupload(generatedDocuments, name, type, result, options); - } - return generatedDocuments; - } - export function uploadYoutubeVideoLoading(videoId: string, options: DocumentOptions, overwriteDoc?: Doc) { const generatedDocuments: Doc[] = []; Networking.UploadYoutubeToServer(videoId).then(upfiles => { @@ -1839,7 +1830,7 @@ export namespace DocUtils { if ((result as any).message) { if (overwriteDoc) { overwriteDoc.isLoading = false; - overwriteDoc.errorMessage = (result as any).message; + overwriteDoc.loadingError = (result as any).message; Doc.removeCurrentlyLoading(overwriteDoc); } } else name && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); @@ -1867,8 +1858,7 @@ export namespace DocUtils { } = upfiles.lastElement() ?? { source: { name: '', type: '' }, result: { message: 'upload failed' } }; if ((result as any).message) { if (overwriteDoc) { - overwriteDoc.isLoading = false; - overwriteDoc.errorMessage = (result as any).message; + overwriteDoc.loadingError = (result as any).message; Doc.removeCurrentlyLoading(overwriteDoc); } } else name && type && processFileupload(generatedDocuments, name, type, result, options, overwriteDoc); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 3ae965af0..30759b766 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -464,14 +464,12 @@ export function CollectionSubView(moreProps?: X) { if (typeof files === 'string') { const loading = Docs.Create.LoadingDocument(files, options); generatedDocuments.push(loading); - loading.isLoading = true; Doc.addCurrentlyLoading(loading); DocUtils.uploadYoutubeVideoLoading(files, {}, loading); } else { generatedDocuments.push( ...files.map(file => { const loading = Docs.Create.LoadingDocument(file, options); - loading.isLoading = true; Doc.addCurrentlyLoading(loading); DocUtils.uploadFileToDoc(file, {}, loading); return loading; diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index 220cd0880..53390328f 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -1,4 +1,3 @@ -import { observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import ReactLoading from 'react-loading'; @@ -36,19 +35,18 @@ export class LoadingBox extends ViewBoxAnnotatableComponent() { } componentDidMount() { - if (!Doc.CurrentlyLoading || !Doc.CurrentlyLoading.includes(this.rootDoc)) { - this.rootDoc.isLoading = false; - this.rootDoc.errorMessage = 'Upload was interrupted, please try again'; + if (!Doc.CurrentlyLoading?.includes(this.rootDoc)) { + this.rootDoc.loadingError = 'Upload interrupted, please try again'; } } render() { return ( -
+
-

{this.rootDoc.isLoading ? 'Loading (can take several minutes):' : StrCast(this.rootDoc.errorMessage, 'Error Loading File:')}

+

{StrCast(this.rootDoc.loadingError, 'Loading (can take several minutes):')}

{StrCast(this.rootDoc.title)} - {!this.rootDoc.isLoading ? null : } + {this.rootDoc.loadingError ? null : }
); -- cgit v1.2.3-70-g09d2