diff --git a/app/app.js b/app/app.js
index ba41b6d47..cbd9deb47 100644
--- a/app/app.js
+++ b/app/app.js
@@ -12,6 +12,7 @@ angular.module('uifordocker', [
'containers',
'createContainer',
'docker',
+ 'events',
'images',
'image',
'containerLogs',
@@ -84,6 +85,11 @@ angular.module('uifordocker', [
templateUrl: 'app/components/docker/docker.html',
controller: 'DockerController'
})
+ .state('events', {
+ url: '/events/',
+ templateUrl: 'app/components/events/events.html',
+ controller: 'EventsController'
+ })
.state('images', {
url: '/images/',
templateUrl: 'app/components/images/images.html',
diff --git a/app/components/events/events.html b/app/components/events/events.html
new file mode 100644
index 000000000..17764e1fb
--- /dev/null
+++ b/app/components/events/events.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+ Events
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/events/eventsController.js b/app/components/events/eventsController.js
new file mode 100644
index 000000000..8450bdb71
--- /dev/null
+++ b/app/components/events/eventsController.js
@@ -0,0 +1,27 @@
+angular.module('events', [])
+.controller('EventsController', ['$scope', 'Settings', 'Messages', 'Events',
+function ($scope, Settings, Messages, Events) {
+ $scope.state = {};
+ $scope.sortType = 'Time';
+ $scope.sortReverse = true;
+
+ $scope.order = function(sortType) {
+ $scope.sortReverse = ($scope.sortType === sortType) ? !$scope.sortReverse : false;
+ $scope.sortType = sortType;
+ };
+
+ var from = moment().subtract(24, 'hour').unix();
+ var to = moment().unix();
+
+ Events.query({since: from, until: to},
+ function(d) {
+ $scope.events = d.map(function (item) {
+ return new EventViewModel(item);
+ });
+ $('#loadEventsSpinner').hide();
+ },
+ function (e) {
+ Messages.error("Unable to load events", e.data);
+ $('#loadEventsSpinner').hide();
+ });
+}]);
diff --git a/app/shared/filters.js b/app/shared/filters.js
index 10fe596ff..e6f096017 100644
--- a/app/shared/filters.js
+++ b/app/shared/filters.js
@@ -163,6 +163,12 @@ angular.module('dockerui.filters', [])
return date.toDateString();
};
})
+.filter('getdatefromtimestamp', function () {
+ 'use strict';
+ return function (timestamp) {
+ return moment.unix(timestamp).format('YYYY-MM-DD HH:mm:ss');
+ };
+})
.filter('errorMsg', function () {
return function (object) {
var idx = 0;
diff --git a/app/shared/services.js b/app/shared/services.js
index 75d979db1..0516fd3ac 100644
--- a/app/shared/services.js
+++ b/app/shared/services.js
@@ -98,6 +98,16 @@ angular.module('dockerui.services', ['ngResource', 'ngSanitize'])
inspect: {method: 'GET', params: {id: '@id', action: 'json'}}
});
}])
+ .factory('Events', ['$resource', 'Settings', function EventFactory($resource, Settings) {
+ 'use strict';
+ // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#/monitor-docker-s-events
+ return $resource(Settings.url + '/events', {}, {
+ query: {method: 'GET', params: {since: '@since', until: '@until'}, isArray: true, transformResponse: [function f(data) {
+ var str = "[" + data.replace(/\n/g, " ").replace(/\}\s*\{/g, "}, {") + "]";
+ return angular.fromJson(str);
+ }]}
+ });
+ }])
.factory('Version', ['$resource', 'Settings', function VersionFactory($resource, Settings) {
'use strict';
// http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#show-the-docker-version-information
diff --git a/app/shared/viewmodel.js b/app/shared/viewmodel.js
index 1b222692e..f0bf07f1e 100644
--- a/app/shared/viewmodel.js
+++ b/app/shared/viewmodel.js
@@ -1,22 +1,128 @@
function ImageViewModel(data) {
- this.Id = data.Id;
- this.Tag = data.Tag;
- this.Repository = data.Repository;
- this.Created = data.Created;
- this.Checked = false;
- this.RepoTags = data.RepoTags;
- this.VirtualSize = data.VirtualSize;
+ this.Id = data.Id;
+ this.Tag = data.Tag;
+ this.Repository = data.Repository;
+ this.Created = data.Created;
+ this.Checked = false;
+ this.RepoTags = data.RepoTags;
+ this.VirtualSize = data.VirtualSize;
}
function ContainerViewModel(data) {
- this.Id = data.Id;
- this.Status = data.Status;
- this.Names = data.Names;
- // Unavailable in Docker < 1.10
- if (data.NetworkSettings) {
- this.IP = data.NetworkSettings.Networks[Object.keys(data.NetworkSettings.Networks)[0]].IPAddress;
+ this.Id = data.Id;
+ this.Status = data.Status;
+ this.Names = data.Names;
+ // Unavailable in Docker < 1.10
+ if (data.NetworkSettings) {
+ this.IP = data.NetworkSettings.Networks[Object.keys(data.NetworkSettings.Networks)[0]].IPAddress;
+ }
+ this.Image = data.Image;
+ this.Command = data.Command;
+ this.Checked = false;
+}
+
+function EventViewModel(data) {
+ // Type, Action, Actor unavailable in Docker < 1.10
+ this.Time = data.time;
+ if (data.Type) {
+ this.Type = data.Type;
+ this.Details = createEventDetails(data);
+ } else {
+ this.Type = data.status;
+ this.Details = data.from;
+ }
+}
+
+function createEventDetails(event) {
+ var eventAttr = event.Actor.Attributes;
+ var details = '';
+ switch (event.Type) {
+ case 'container':
+ switch (event.Action) {
+ case 'stop':
+ details = 'Container ' + eventAttr.name + ' stopped';
+ break;
+ case 'destroy':
+ details = 'Container ' + eventAttr.name + ' deleted';
+ break;
+ case 'create':
+ details = 'Container ' + eventAttr.name + ' created';
+ break;
+ case 'start':
+ details = 'Container ' + eventAttr.name + ' started';
+ break;
+ case 'kill':
+ details = 'Container ' + eventAttr.name + ' killed';
+ break;
+ case 'die':
+ details = 'Container ' + eventAttr.name + ' exited with status code ' + eventAttr.exitCode;
+ break;
+ case 'commit':
+ details = 'Container ' + eventAttr.name + ' committed';
+ break;
+ case 'restart':
+ details = 'Container ' + eventAttr.name + ' restarted';
+ break;
+ case 'pause':
+ details = 'Container ' + eventAttr.name + ' paused';
+ break;
+ case 'unpause':
+ details = 'Container ' + eventAttr.name + ' unpaused';
+ break;
+ default:
+ details = 'Unsupported event';
+ }
+ break;
+ case 'image':
+ switch (event.Action) {
+ case 'delete':
+ details = 'Image deleted';
+ break;
+ case 'tag':
+ details = 'New tag created for ' + eventAttr.name;
+ break;
+ case 'untag':
+ details = 'Image untagged';
+ break;
+ case 'pull':
+ details = 'Image ' + event.Actor.ID + ' pulled';
+ break;
+ default:
+ details = 'Unsupported event';
+ }
+ break;
+ case 'network':
+ switch (event.Action) {
+ case 'create':
+ details = 'Network ' + eventAttr.name + ' created';
+ break;
+ case 'destroy':
+ details = 'Network ' + eventAttr.name + ' deleted';
+ break;
+ case 'connect':
+ details = 'Container connected to ' + eventAttr.name + ' network';
+ break;
+ case 'disconnect':
+ details = 'Container disconnected from ' + eventAttr.name + ' network';
+ break;
+ default:
+ details = 'Unsupported event';
+ }
+ break;
+ case 'volume':
+ switch (event.Action) {
+ case 'create':
+ details = 'Volume ' + event.Actor.ID + ' created';
+ break;
+ case 'destroy':
+ details = 'Volume ' + event.Actor.ID + ' deleted';
+ break;
+ default:
+ details = 'Unsupported event';
}
- this.Image = data.Image;
- this.Command = data.Command;
- this.Checked = false;
+ break;
+ default:
+ details = 'Unsupported event';
+ }
+ return details;
}
diff --git a/bower.json b/bower.json
index 56800d37d..12974762a 100644
--- a/bower.json
+++ b/bower.json
@@ -30,7 +30,6 @@
"angular-ui-router": "^0.2.15",
"angular-sanitize": "~1.5.0",
"angular-mocks": "~1.5.0",
- "angular-oboe": "*",
"angular-resource": "~1.5.0",
"angular-ui-select": "~0.17.1",
"bootstrap": "~3.3.6",
@@ -39,6 +38,7 @@
"jquery.gritter": "1.7.4",
"lodash": "4.12.0",
"rdash-ui": "1.0.*",
+ "moment": "~2.14.1"
},
"resolutions": {
"angular": "1.5.5"
diff --git a/gruntFile.js b/gruntFile.js
index 3ff9bbc31..7482b3ecb 100644
--- a/gruntFile.js
+++ b/gruntFile.js
@@ -68,11 +68,11 @@ module.exports = function (grunt) {
jsTpl: ['<%= distdir %>/templates/**/*.js'],
jsVendor: [
'bower_components/jquery/dist/jquery.min.js',
- 'assets/js/jquery.gritter.js', // Using custom version to fix error in minified build due to "use strict"
'bower_components/bootstrap/dist/js/bootstrap.min.js',
'bower_components/Chart.js/Chart.min.js',
'bower_components/lodash/dist/lodash.min.js',
- 'bower_components/oboe/dist/oboe-browser.js',
+ 'bower_components/moment/min/moment.min.js',
+ 'assets/js/jquery.gritter.js', // Using custom version to fix error in minified build due to "use strict"
'assets/js/legend.js' // Not a bower package
],
specs: ['test/**/*.spec.js'],
@@ -156,7 +156,6 @@ module.exports = function (grunt) {
'bower_components/angular-ui-router/release/angular-ui-router.min.js',
'bower_components/angular-resource/angular-resource.min.js',
'bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js',
- 'bower_components/angular-oboe/dist/angular-oboe.min.js',
'bower_components/angular-ui-select/dist/select.min.js'],
dest: '<%= distdir %>/js/angular.js'
}
diff --git a/index.html b/index.html
index a42f292a7..434d0f048 100644
--- a/index.html
+++ b/index.html
@@ -52,6 +52,9 @@
+