mirror of https://github.com/portainer/portainer
Added pause/unpause to containers,
Auto-update /container and /containers views after performing an action, Display spinner when container actions are being performed, Unified stylepull/2/head
parent
9dccf95152
commit
8652285227
|
@ -155,34 +155,83 @@ function SettingsController($scope, System, Docker, Settings, Messages) {
|
|||
function ContainerController($scope, $routeParams, $location, Container, Messages, ViewSpinner) {
|
||||
$scope.changes = [];
|
||||
|
||||
var update = function() {
|
||||
Container.get({id: $routeParams.id}, function(d) {
|
||||
$scope.container = d;
|
||||
ViewSpinner.stop();
|
||||
}, function(e) {
|
||||
if (e.status === 404) {
|
||||
$('.detail').hide();
|
||||
Messages.error("Not found", "Container not found.");
|
||||
} else {
|
||||
Messages.error("Failure", e.data);
|
||||
}
|
||||
ViewSpinner.stop();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.start = function(){
|
||||
ViewSpinner.spin();
|
||||
Container.start({id: $routeParams.id}, function(d) {
|
||||
update();
|
||||
Messages.send("Container started", $routeParams.id);
|
||||
}, function(e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to start." + e.data);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.stop = function() {
|
||||
ViewSpinner.spin();
|
||||
Container.stop({id: $routeParams.id}, function(d) {
|
||||
update();
|
||||
Messages.send("Container stopped", $routeParams.id);
|
||||
}, function(e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to stop." + e.data);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.kill = function() {
|
||||
ViewSpinner.spin();
|
||||
Container.kill({id: $routeParams.id}, function(d) {
|
||||
update();
|
||||
Messages.send("Container killed", $routeParams.id);
|
||||
}, function(e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to die." + e.data);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.pause = function() {
|
||||
ViewSpinner.spin();
|
||||
Container.pause({id: $routeParams.id}, function(d) {
|
||||
update();
|
||||
Messages.send("Container paused", $routeParams.id);
|
||||
}, function(e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to pause." + e.data);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.unpause = function() {
|
||||
ViewSpinner.spin();
|
||||
Container.unpause({id: $routeParams.id}, function(d) {
|
||||
update();
|
||||
Messages.send("Container unpaused", $routeParams.id);
|
||||
}, function(e) {
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to unpause." + e.data);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.remove = function() {
|
||||
ViewSpinner.spin();
|
||||
Container.remove({id: $routeParams.id}, function(d) {
|
||||
update();
|
||||
Messages.send("Container removed", $routeParams.id);
|
||||
}, function(e){
|
||||
update();
|
||||
Messages.error("Failure", "Container failed to remove." + e.data);
|
||||
});
|
||||
};
|
||||
|
@ -192,23 +241,15 @@ function ContainerController($scope, $routeParams, $location, Container, Message
|
|||
};
|
||||
|
||||
$scope.getChanges = function() {
|
||||
ViewSpinner.spin();
|
||||
Container.changes({id: $routeParams.id}, function(d) {
|
||||
$scope.changes = d;
|
||||
ViewSpinner.stop();
|
||||
});
|
||||
};
|
||||
|
||||
Container.get({id: $routeParams.id}, function(d) {
|
||||
$scope.container = d;
|
||||
}, function(e) {
|
||||
if (e.status === 404) {
|
||||
$('.detail').hide();
|
||||
Messages.error("Not found", "Container not found.");
|
||||
} else {
|
||||
Messages.error("Failure", e.data);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.getChanges();
|
||||
update();
|
||||
$scope.getChanges();
|
||||
}
|
||||
|
||||
// Controller for the list of containers
|
||||
|
@ -220,8 +261,8 @@ function ContainersController($scope, Container, Settings, Messages, ViewSpinner
|
|||
var update = function(data) {
|
||||
ViewSpinner.spin();
|
||||
Container.query(data, function(d) {
|
||||
$scope.containers = d.map(function(item) {
|
||||
return new ContainerViewModel(item); });
|
||||
$scope.containers = d.map(function(item) {
|
||||
return new ContainerViewModel(item); });
|
||||
ViewSpinner.stop();
|
||||
});
|
||||
};
|
||||
|
@ -233,22 +274,25 @@ function ContainersController($scope, Container, Settings, Messages, ViewSpinner
|
|||
counter = counter -1;
|
||||
if (counter === 0) {
|
||||
ViewSpinner.stop();
|
||||
update({all: Settings.displayAll ? 1 : 0});
|
||||
}
|
||||
};
|
||||
angular.forEach(items, function(c) {
|
||||
if (c.Checked) {
|
||||
counter = counter + 1;
|
||||
action({id: c.Id}, function(d) {
|
||||
angular.forEach(items, function(c) {
|
||||
if (c.Checked) {
|
||||
counter = counter + 1;
|
||||
action({id: c.Id}, function(d) {
|
||||
Messages.send("Container " + msg, c.Id);
|
||||
var index = $scope.containers.indexOf(c);
|
||||
$scope.containers.splice(index, 1);
|
||||
complete();
|
||||
}, function(e) {
|
||||
}, function(e) {
|
||||
Messages.error("Failure", e.data);
|
||||
complete();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (counter === 0) {
|
||||
ViewSpinner.stop();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.toggleSelectAll = function() {
|
||||
|
@ -274,6 +318,14 @@ function ContainersController($scope, Container, Settings, Messages, ViewSpinner
|
|||
batch($scope.containers, Container.kill, "Killed");
|
||||
};
|
||||
|
||||
$scope.pauseAction = function() {
|
||||
batch($scope.containers, Container.pause, "Paused");
|
||||
};
|
||||
|
||||
$scope.unpauseAction = function() {
|
||||
batch($scope.containers, Container.unpause, "Unpaused");
|
||||
};
|
||||
|
||||
$scope.removeAction = function() {
|
||||
batch($scope.containers, Container.remove, "Removed");
|
||||
};
|
||||
|
|
|
@ -34,6 +34,9 @@ angular.module('dockerui.filters', [])
|
|||
if (state.Ghost && state.Running) {
|
||||
return 'Ghost';
|
||||
}
|
||||
if (state.Running && state.Paused) {
|
||||
return 'Running (Paused)';
|
||||
}
|
||||
if (state.Running) {
|
||||
return 'Running';
|
||||
}
|
||||
|
@ -62,22 +65,22 @@ angular.module('dockerui.filters', [])
|
|||
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
||||
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[[i]];
|
||||
};
|
||||
})
|
||||
.filter('containername', function() {
|
||||
return function(container) {
|
||||
var name = container.Names[0];
|
||||
return name.substring(1, name.length);
|
||||
};
|
||||
})
|
||||
.filter('repotag', function() {
|
||||
return function(image) {
|
||||
if (image.RepoTags && image.RepoTags.length > 0) {
|
||||
var tag = image.RepoTags[0];
|
||||
if (tag == '<none>:<none>') { tag = ''; }
|
||||
return tag;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
})
|
||||
.filter('containername', function() {
|
||||
return function(container) {
|
||||
var name = container.Names[0];
|
||||
return name.substring(1, name.length);
|
||||
};
|
||||
})
|
||||
.filter('repotag', function() {
|
||||
return function(image) {
|
||||
if (image.RepoTags && image.RepoTags.length > 0) {
|
||||
var tag = image.RepoTags[0];
|
||||
if (tag == '<none>:<none>') { tag = ''; }
|
||||
return tag;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
})
|
||||
.filter('getdate', function() {
|
||||
return function(data) {
|
||||
|
|
|
@ -5,17 +5,19 @@ angular.module('dockerui.services', ['ngResource'])
|
|||
// Resource for interacting with the docker containers
|
||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#containers
|
||||
return $resource(Settings.url + '/containers/:id/:action', {
|
||||
name: '@name'
|
||||
name: '@name'
|
||||
}, {
|
||||
query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true},
|
||||
get :{method: 'GET', params: { action:'json'}},
|
||||
get: {method: 'GET', params: { action:'json'}},
|
||||
start: {method: 'POST', params: {id: '@id', action: 'start'}},
|
||||
stop: {method: 'POST', params: {id: '@id', t: 5, action: 'stop'}},
|
||||
restart: {method: 'POST', params: {id: '@id', t: 5, action: 'restart' }},
|
||||
kill :{method: 'POST', params: {id: '@id', action:'kill'}},
|
||||
changes :{method: 'GET', params: {action:'changes'}, isArray: true},
|
||||
create :{method: 'POST', params: {action:'create'}},
|
||||
remove :{method: 'DELETE', params: {id: '@id', v:0}}
|
||||
kill: {method: 'POST', params: {id: '@id', action: 'kill'}},
|
||||
pause: {method: 'POST', params: {id: '@id', action: 'pause'}},
|
||||
unpause: {method: 'POST', params: {id: '@id', action: 'unpause'}},
|
||||
changes: {method: 'GET', params: {action:'changes'}, isArray: true},
|
||||
create: {method: 'POST', params: {action:'create'}},
|
||||
remove: {method: 'DELETE', params: {id: '@id', v:0}}
|
||||
});
|
||||
})
|
||||
.factory('Image', function($resource, Settings) {
|
||||
|
@ -23,14 +25,14 @@ angular.module('dockerui.services', ['ngResource'])
|
|||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#images
|
||||
return $resource(Settings.url + '/images/:id/:action', {}, {
|
||||
query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true},
|
||||
get :{method: 'GET', params: { action:'json'}},
|
||||
search :{method: 'GET', params: { action:'search'}},
|
||||
history :{method: 'GET', params: { action:'history'}, isArray: true},
|
||||
create :{method: 'POST', params: {action:'create'}},
|
||||
insert :{method: 'POST', params: {id: '@id', action:'insert'}},
|
||||
push :{method: 'POST', params: {id: '@id', action:'push'}},
|
||||
tag :{method: 'POST', params: {id: '@id', action:'tag', force: 0, repo: '@repo'}},
|
||||
remove :{method: 'DELETE', params: {id: '@id'}, isArray: true}
|
||||
get: {method: 'GET', params: { action:'json'}},
|
||||
search: {method: 'GET', params: { action:'search'}},
|
||||
history: {method: 'GET', params: { action:'history'}, isArray: true},
|
||||
create: {method: 'POST', params: {action:'create'}},
|
||||
insert: {method: 'POST', params: {id: '@id', action:'insert'}},
|
||||
push: {method: 'POST', params: {id: '@id', action:'push'}},
|
||||
tag: {method: 'POST', params: {id: '@id', action:'tag', force: 0, repo: '@repo'}},
|
||||
remove: {method: 'DELETE', params: {id: '@id'}, isArray: true}
|
||||
});
|
||||
})
|
||||
.factory('Docker', function($resource, Settings) {
|
||||
|
@ -74,52 +76,51 @@ angular.module('dockerui.services', ['ngResource'])
|
|||
var spinner = new Spinner();
|
||||
var target = document.getElementById('view');
|
||||
|
||||
return {
|
||||
spin: function() { spinner.spin(target); },
|
||||
stop: function() { spinner.stop(); }
|
||||
};
|
||||
return {
|
||||
spin: function() { spinner.spin(target); },
|
||||
stop: function() { spinner.stop(); }
|
||||
};
|
||||
})
|
||||
.factory('Messages', function($rootScope) {
|
||||
return {
|
||||
send: function(title, text) {
|
||||
$.gritter.add({
|
||||
title: title,
|
||||
text: text,
|
||||
time: 2000,
|
||||
before_open: function() {
|
||||
if($('.gritter-item-wrapper').length == 3) {
|
||||
send: function(title, text) {
|
||||
$.gritter.add({
|
||||
title: title,
|
||||
text: text,
|
||||
time: 2000,
|
||||
before_open: function() {
|
||||
if($('.gritter-item-wrapper').length == 3) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
error: function(title, text) {
|
||||
});
|
||||
},
|
||||
error: function(title, text) {
|
||||
$.gritter.add({
|
||||
title: title,
|
||||
text: text,
|
||||
time: 6000,
|
||||
before_open: function() {
|
||||
if($('.gritter-item-wrapper').length == 4) {
|
||||
if($('.gritter-item-wrapper').length == 4) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.factory('Dockerfile', function(Settings) {
|
||||
var url = Settings.rawUrl + '/build';
|
||||
return {
|
||||
build: function(file, callback) {
|
||||
var data = new FormData();
|
||||
var dockerfile = new Blob([file], { type: 'text/text' });
|
||||
data.append('Dockerfile', dockerfile);
|
||||
build: function(file, callback) {
|
||||
var data = new FormData();
|
||||
var dockerfile = new Blob([file], { type: 'text/text' });
|
||||
data.append('Dockerfile', dockerfile);
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.onload = callback;
|
||||
request.open('POST', url);
|
||||
request.send(data);
|
||||
}
|
||||
var request = new XMLHttpRequest();
|
||||
request.onload = callback;
|
||||
request.open('POST', url);
|
||||
request.send(data);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -3,9 +3,21 @@
|
|||
<h4>Container: {{ container.Name }}</h4>
|
||||
|
||||
<div class="btn-group detail">
|
||||
<button class="btn btn-success" ng-click="start()">Start</button>
|
||||
<button class="btn btn-warning" ng-click="stop()">Stop</button>
|
||||
<button class="btn btn-danger" ng-click="kill()">Kill</button>
|
||||
<button class="btn btn-success"
|
||||
ng-click="start()"
|
||||
ng-show="!container.State.Running">Start</button>
|
||||
<button class="btn btn-warning"
|
||||
ng-click="stop()"
|
||||
ng-show="container.State.Running && !container.State.Paused">Stop</button>
|
||||
<button class="btn btn-danger"
|
||||
ng-click="kill()"
|
||||
ng-show="container.State.Running && !container.State.Paused">Kill</button>
|
||||
<button class="btn btn-info"
|
||||
ng-click="pause()"
|
||||
ng-show="container.State.Running && !container.State.Paused">Pause</button>
|
||||
<button class="btn btn-success"
|
||||
ng-click="unpause()"
|
||||
ng-show="container.State.Running && container.State.Paused">Unpause</button>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped">
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
<li><a tabindex="-1" href="" ng-click="startAction()">Start</a></li>
|
||||
<li><a tabindex="-1" href="" ng-click="stopAction()">Stop</a></li>
|
||||
<li><a tabindex="-1" href="" ng-click="killAction()">Kill</a></li>
|
||||
<li><a tabindex="-1" href="" ng-click="pauseAction()">Pause</a></li>
|
||||
<li><a tabindex="-1" href="" ng-click="unpauseAction()">Unpause</a></li>
|
||||
<li><a tabindex="-1" href="" ng-click="removeAction()">Remove</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue