This repository has been archived on 2020-03-24. You can view files and clone it, but cannot push or open issues or pull requests.
quay/static/js/directives/ui/file-upload-box.js
Joseph Schorr e509eb4cba Better custom cert handling in the superuser tool
We now only allow certificates ending in .crt to be uploaded and we automatically install the certificate once it has been validated
2017-03-24 17:15:26 -04:00

172 lines
No EOL
5.1 KiB
JavaScript

/**
* An element which adds a stylize box for uploading a file.
*/
angular.module('quay').directive('fileUploadBox', function () {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/file-upload-box.html',
replace: false,
transclude: true,
restrict: 'C',
scope: {
'selectMessage': '@selectMessage',
'filesSelected': '&filesSelected',
'filesCleared': '&filesCleared',
'filesValidated': '&filesValidated',
'extensions': '<extensions',
'reset': '=?reset'
},
controller: function($rootScope, $scope, $element, ApiService) {
var MEGABYTE = 1000000;
var MAX_FILE_SIZE = MAX_FILE_SIZE_MB * MEGABYTE;
var MAX_FILE_SIZE_MB = 100;
var number = $rootScope.__fileUploadBoxIdCounter || 0;
$rootScope.__fileUploadBoxIdCounter = number + 1;
$scope.boxId = number;
$scope.state = 'clear';
$scope.selectedFiles = [];
var conductUpload = function(file, url, fileId, mimeType, progressCb, doneCb) {
var request = new XMLHttpRequest();
request.open('PUT', url, true);
request.setRequestHeader('Content-Type', mimeType);
request.onprogress = function(e) {
$scope.$apply(function() {
if (e.lengthComputable) { progressCb((e.loaded / e.total) * 100); }
});
};
request.onerror = function() {
$scope.$apply(function() { doneCb(false, 'Error when uploading'); });
};
request.onreadystatechange = function() {
var state = request.readyState;
var status = request.status;
if (state == 4) {
if (Math.floor(status / 100) == 2) {
$scope.$apply(function() { doneCb(true, fileId); });
} else {
var message = request.statusText;
if (status == 413) {
message = 'Selected file too large to upload';
}
$scope.$apply(function() { doneCb(false, message); });
}
}
};
request.send(file);
};
var uploadFiles = function(callback) {
var currentIndex = 0;
var fileIds = [];
var progressCb = function(progress) {
$scope.uploadProgress = progress;
};
var doneCb = function(status, messageOrId) {
if (status) {
fileIds.push(messageOrId);
currentIndex++;
performFileUpload();
} else {
callback(false, messageOrId);
}
};
var performFileUpload = function() {
// If we have finished uploading all of the files, invoke the overall callback
// with the list of file IDs.
if (currentIndex >= $scope.selectedFiles.length) {
callback(true, fileIds);
return;
}
// For the current file, retrieve a file-drop URL from the API for the file.
var currentFile = $scope.selectedFiles[currentIndex];
var mimeType = currentFile.type || 'application/octet-stream';
var data = {
'mimeType': mimeType
};
$scope.currentlyUploadingFile = currentFile;
$scope.uploadProgress = 0;
ApiService.getFiledropUrl(data).then(function(resp) {
// Perform the upload.
conductUpload(currentFile, resp.url, resp.file_id, mimeType, progressCb, doneCb);
}, function() {
callback(false, 'Could not retrieve upload URL');
});
};
// Start the uploading.
$scope.state = 'uploading';
performFileUpload();
};
$scope.handleFilesChanged = function(files) {
if ($scope.state == 'uploading') { return; }
$scope.message = null;
$scope.selectedFiles = files;
if (files.length == 0) {
$scope.state = 'clear';
$scope.filesCleared();
} else {
for (var i = 0; i < files.length; ++i) {
if (files[i].size > MAX_FILE_SIZE) {
$scope.state = 'error';
$scope.message = 'File ' + files[i].name + ' is larger than the maximum file ' +
'size of ' + MAX_FILE_SIZE_MB + ' MB';
return;
}
}
$scope.state = 'checking';
$scope.filesSelected({
'files': files,
'callback': function(status, message) {
$scope.state = status ? 'okay' : 'error';
$scope.message = message;
if (status) {
$scope.filesValidated({
'files': files,
'uploadFiles': uploadFiles
});
}
}
});
}
};
$scope.getAccepts = function(extensions) {
if (!extensions || !extensions.length) {
return '*';
}
return extensions.join(',');
};
$scope.$watch('reset', function(reset) {
if (reset) {
$scope.state = 'clear';
$element.find('#file-drop-' + $scope.boxId).parent().trigger('reset');
}
});
}
};
return directiveDefinitionObject;
});