1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
import { observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import ReactLoading from 'react-loading';
import { Doc } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { StrCast } from '../../../fields/Types';
import { Networking } from '../../Network';
import { DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { FieldView, FieldViewProps } from './FieldView';
import './LoadingBox.scss';
/**
* 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)
* 5) Fixing the stacking view bug
* 6) Fixing the CSS
*
* @author naafiyan
*/
@observer
export class LoadingBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(LoadingBox, fieldKey);
}
_timer: NodeJS.Timeout | undefined;
@observable progress = '';
componentDidMount() {
if (!Doc.CurrentlyLoading?.includes(this.Document)) {
this.Document.loadingError ??= 'Upload interrupted, please try again';
} else {
const updateFunc = async () => {
const result = await Networking.QueryYoutubeProgress(StrCast(this.Document[Id])); // We use the guid of the overwriteDoc to track file uploads.
runInAction(() => {
this.progress = result.progress;
});
!this.Document.loadingError && this._timer && (this._timer = setTimeout(updateFunc, 1000));
};
this._timer = setTimeout(updateFunc, 1000);
}
}
componentWillUnmount() {
clearTimeout(this._timer);
this._timer = undefined;
}
render() {
return (
<div className="loadingBoxContainer" style={{ background: !this.Document.loadingError ? '' : 'red' }}>
<div className="loadingBox-textContainer">
<span className="loadingBox-title">{StrCast(this.Document.title)}</span>
<p className="loadingBox-headerText">{StrCast(this.Document.loadingError, 'Loading ' + (this.progress.replace('[download]', '') || '(can take several minutes)'))}</p>
{this.Document.loadingError ? null : (
<div className="loadingBox-spinner">
<ReactLoading type="spinningBubbles" color="blue" height={100} width={100} />
</div>
)}
</div>
</div>
);
}
}
Docs.Prototypes.TemplateMap.set(DocumentType.LOADING, {
layout: { view: LoadingBox, dataField: '' },
options: { acl: '', _layout_fitWidth: true, _layout_nativeDimEditable: true },
});
|