3781: Fix trigger() usage: second argument is an array of handler args.
[arvados.git] / apps / workbench / app / assets / javascripts / upload_to_collection.js
index 9e205423f33911a24c4ee6f2e83765e48cb4ae0b..acdcb24b93c32a04e8b4e36c02cc9c7a81795324 100644 (file)
@@ -262,7 +262,8 @@ function UploadToCollection($scope, $filter, $q, $timeout,
             that.state = 'Paused';
             setProgress(_readPos);
             _currentUploader = null;
-            _deferred.reject(reason);
+            if (_deferred)
+                _deferred.reject(reason);
         }
         function onUploaderProgress(sliceDone, sliceSize) {
             setProgress(_readPos + sliceDone);
@@ -282,7 +283,10 @@ function UploadToCollection($scope, $filter, $q, $timeout,
         }
         function setProgress(bytesDone) {
             var kBps;
-            that.progress = Math.min(100, 100 * bytesDone / that.file.size)
+            if (that.file.size == 0)
+                that.progress = 100;
+            else
+                that.progress = Math.min(100, 100 * bytesDone / that.file.size);
             if (bytesDone > _startByte) {
                 kBps = (bytesDone - _startByte) /
                     (Date.now() - _startTime);
@@ -301,7 +305,7 @@ function UploadToCollection($scope, $filter, $q, $timeout,
             } else {
                 that.statistics = that.state;
             }
-            if (that.state === 'Uploading' || that.state === 'Uploaded') {
+            if (that.state === 'Uploaded') {
                 // 'Uploaded' gets reported as 'finished', which is a
                 // little misleading because the collection hasn't
                 // been updated yet. But FileUploader's portion of the
@@ -311,13 +315,14 @@ function UploadToCollection($scope, $filter, $q, $timeout,
                     $filter('date')(Date.now(), 'shortTime');
                 _finishTime = Date.now();
             }
-            _deferred.notify();
+            if (_deferred)
+                _deferred.notify();
         }
     }
 
     function QueueUploader() {
         $.extend(this, {
-            state: 'Idle',
+            state: 'Idle',      // Idle, Running, Stopped, Failed
             stateReason: null,
             statusSuccess: null,
             go: go,
@@ -344,9 +349,6 @@ function UploadToCollection($scope, $filter, $q, $timeout,
             if (_deferred) {
                 _deferred.reject({});
             }
-            if (_deferredAppend) {
-                _deferredAppend.reject({});
-            }
             for (var i=0; i<$scope.uploadQueue.length; i++)
                 $scope.uploadQueue[i].stop();
             onQueueProgress();
@@ -363,20 +365,28 @@ function UploadToCollection($scope, $filter, $q, $timeout,
             return doQueueWork();
         }
         function doQueueWork() {
-            if (!_deferred) {
-                // Queue work has been stopped.
-                return;
-            }
-            that.stateReason = null;
             // If anything is not Done, do it.
             if ($scope.uploadQueue.length > 0 &&
                 $scope.uploadQueue[0].state !== 'Done') {
-                return $scope.uploadQueue[0].go().
-                    then(appendToCollection, null, onQueueProgress).
-                    then(doQueueWork, onQueueReject);
+                if (_deferred) {
+                    that.stateReason = null;
+                    return $scope.uploadQueue[0].go().
+                        then(appendToCollection, null, onQueueProgress).
+                        then(doQueueWork, onQueueReject);
+                } else {
+                    // Queue work has been stopped. Just update the
+                    // view.
+                    onQueueProgress();
+                    return;
+                }
             }
-            // If everything is Done, resolve the promise and clean up.
-            return onQueueResolve();
+            // If everything is Done, resolve the promise and clean
+            // up. Note this can happen even after the _deferred
+            // promise has been rejected: specifically, when stop() is
+            // called too late to prevent completion of the last
+            // upload. In that case we want to update state to "Idle",
+            // rather than leave it at "Stopped".
+            onQueueResolve();
         }
         function onQueueReject(reason) {
             if (!_deferred) {
@@ -399,7 +409,8 @@ function UploadToCollection($scope, $filter, $q, $timeout,
         function onQueueResolve() {
             that.state = 'Idle';
             that.stateReason = 'Done!';
-            _deferred.resolve();
+            if (_deferred)
+                _deferred.resolve();
             onQueueProgress();
         }
         function onQueueProgress() {
@@ -414,11 +425,18 @@ function UploadToCollection($scope, $filter, $q, $timeout,
                 then(function(collection) {
                     var manifestText = '';
                     $.each(uploads, function(_, upload) {
+                        var locators = upload.locators;
+                        if (locators.length === 0) {
+                            // Every stream must have at least one
+                            // data locator, even if it is zero bytes
+                            // long:
+                            locators = ['d41d8cd98f00b204e9800998ecf8427e+0'];
+                        }
                         filename = ArvadosClient.uniqueNameForManifest(
                             collection.manifest_text,
                             '.', upload.file.name);
                         collection.manifest_text += '. ' +
-                            upload.locators.join(' ') +
+                            locators.join(' ') +
                             ' 0:' + upload.file.size.toString() + ':' +
                             filename +
                             '\n';