/** * An element which displays a form for manually starting a dockerfile build. */ angular.module('quay').directive('dockerfileBuildForm', function () { var directiveDefinitionObject = { priority: 0, templateUrl: '/static/directives/dockerfile-build-form.html', replace: false, transclude: false, restrict: 'C', scope: { 'repository': '=repository', 'startNow': '=startNow', 'isReady': '=isReady', 'uploadFailed': '&uploadFailed', 'uploadStarted': '&uploadStarted', 'buildStarted': '&buildStarted', 'buildFailed': '&buildFailed', 'missingFile': '&missingFile', 'uploading': '=uploading', 'building': '=building' }, controller: function($scope, $element, ApiService) { $scope.internal = {'hasDockerfile': false}; $scope.pull_entity = null; $scope.is_public = true; var handleBuildFailed = function(message) { message = message || 'Dockerfile build failed to start'; var result = false; if ($scope.buildFailed) { result = $scope.buildFailed({'message': message}); } if (!result) { bootbox.dialog({ "message": message, "title": "Cannot start Dockerfile build", "buttons": { "close": { "label": "Close", "className": "btn-primary" } } }); } }; var handleUploadFailed = function(message) { message = message || 'Error with file upload'; var result = false; if ($scope.uploadFailed) { result = $scope.uploadFailed({'message': message}); } if (!result) { bootbox.dialog({ "message": message, "title": "Cannot upload file for Dockerfile build", "buttons": { "close": { "label": "Close", "className": "btn-primary" } } }); } }; var handleMissingFile = function() { var result = false; if ($scope.missingFile) { result = $scope.missingFile({}); } if (!result) { bootbox.dialog({ "message": 'A Dockerfile or an archive containing a Dockerfile is required', "title": "Missing Dockerfile", "buttons": { "close": { "label": "Close", "className": "btn-primary" } } }); } }; var startBuild = function(fileId) { $scope.building = true; var repo = $scope.repository; var data = { 'file_id': fileId }; if (!$scope.is_public && $scope.pull_entity) { data['pull_robot'] = $scope.pull_entity['name']; } var params = { 'repository': repo.namespace + '/' + repo.name, }; ApiService.requestRepoBuild(data, params).then(function(resp) { $scope.building = false; $scope.uploading = false; if ($scope.buildStarted) { $scope.buildStarted({'build': resp}); } }, function(resp) { $scope.building = false; $scope.uploading = false; handleBuildFailed(resp.message); }); }; var conductUpload = function(file, url, fileId, mimeType) { if ($scope.uploadStarted) { $scope.uploadStarted({}); } var request = new XMLHttpRequest(); request.open('PUT', url, true); request.setRequestHeader('Content-Type', mimeType); request.onprogress = function(e) { $scope.$apply(function() { var percentLoaded; if (e.lengthComputable) { $scope.upload_progress = (e.loaded / e.total) * 100; } }); }; request.onerror = function() { $scope.$apply(function() { handleUploadFailed(); }); }; request.onreadystatechange = function() { var state = request.readyState; if (state == 4) { $scope.$apply(function() { startBuild(fileId); $scope.uploading = false; }); return; } }; request.send(file); }; var startFileUpload = function(repo) { $scope.uploading = true; $scope.uploading_progress = 0; var uploader = $('#file-drop')[0]; if (uploader.files.length == 0) { handleMissingFile(); $scope.uploading = false; return; } var file = uploader.files[0]; $scope.upload_file = file.name; var mimeType = file.type || 'application/octet-stream'; var data = { 'mimeType': mimeType }; var getUploadUrl = ApiService.getFiledropUrl(data).then(function(resp) { conductUpload(file, resp.url, resp.file_id, mimeType); }, function() { handleUploadFailed('Could not retrieve upload URL'); }); }; var checkIsReady = function() { $scope.isReady = $scope.internal.hasDockerfile && ($scope.is_public || $scope.pull_entity); }; $scope.$watch('pull_entity', checkIsReady); $scope.$watch('is_public', checkIsReady); $scope.$watch('internal.hasDockerfile', checkIsReady); $scope.$watch('startNow', function() { if ($scope.startNow && $scope.repository && !$scope.uploading && !$scope.building) { startFileUpload(); } }); } }; return directiveDefinitionObject; });