mirror of https://github.com/portainer/portainer
commit
2974f69932
|
@ -0,0 +1 @@
|
||||||
|
node_modules
|
|
@ -3,4 +3,5 @@ logs/*
|
||||||
dockerui
|
dockerui
|
||||||
*.esproj/*
|
*.esproj/*
|
||||||
node_modules
|
node_modules
|
||||||
|
dist
|
||||||
.idea
|
.idea
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
FROM crosbymichael/golang
|
FROM crosbymichael/golang
|
||||||
|
|
||||||
ADD . /app/
|
COPY dockerui.go /app/
|
||||||
|
COPY dist/ /app/
|
||||||
WORKDIR /app/
|
WORKDIR /app/
|
||||||
RUN go build dockerui.go
|
RUN go build dockerui.go
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -5,9 +5,16 @@
|
||||||
OPEN = $(shell which xdg-open || which open)
|
OPEN = $(shell which xdg-open || which open)
|
||||||
PORT ?= 9000
|
PORT ?= 9000
|
||||||
|
|
||||||
|
install:
|
||||||
|
npm install -g grunt-cli
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
grunt build
|
||||||
docker build --rm -t dockerui .
|
docker build --rm -t dockerui .
|
||||||
|
|
||||||
|
test:
|
||||||
|
grunt
|
||||||
|
|
||||||
run:
|
run:
|
||||||
-docker stop dockerui
|
-docker stop dockerui
|
||||||
-docker rm dockerui
|
-docker rm dockerui
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use strict';
|
angular.module('<%= pkg.name %>', ['<%= pkg.name %>.templates', 'ngRoute', '<%= pkg.name %>.services', '<%= pkg.name %>.filters', 'masthead', 'footer', 'dashboard', 'container', 'containers', 'images', 'image', 'startContainer', 'sidebar', 'settings', 'builder', 'containerLogs'])
|
||||||
|
|
||||||
angular.module('dockerui', ['ngRoute', 'dockerui.services', 'dockerui.filters', 'masthead', 'footer', 'dashboard', 'container', 'containers', 'images', 'image', 'startContainer', 'sidebar', 'settings', 'builder', 'containerLogs'])
|
|
||||||
.config(['$routeProvider', function ($routeProvider) {
|
.config(['$routeProvider', function ($routeProvider) {
|
||||||
|
'use strict';
|
||||||
$routeProvider.when('/', {templateUrl: 'app/components/dashboard/dashboard.html', controller: 'DashboardController'});
|
$routeProvider.when('/', {templateUrl: 'app/components/dashboard/dashboard.html', controller: 'DashboardController'});
|
||||||
$routeProvider.when('/containers/', {templateUrl: 'app/components/containers/containers.html', controller: 'ContainersController'});
|
$routeProvider.when('/containers/', {templateUrl: 'app/components/containers/containers.html', controller: 'ContainersController'});
|
||||||
$routeProvider.when('/containers/:id/', {templateUrl: 'app/components/container/container.html', controller: 'ContainerController'});
|
$routeProvider.when('/containers/:id/', {templateUrl: 'app/components/container/container.html', controller: 'ContainerController'});
|
||||||
|
@ -15,5 +14,5 @@ angular.module('dockerui', ['ngRoute', 'dockerui.services', 'dockerui.filters',
|
||||||
// You need to set this to the api endpoint without the port i.e. http://192.168.1.9
|
// You need to set this to the api endpoint without the port i.e. http://192.168.1.9
|
||||||
.constant('DOCKER_ENDPOINT', '/dockerapi')
|
.constant('DOCKER_ENDPOINT', '/dockerapi')
|
||||||
.constant('DOCKER_PORT', '') // Docker port, leave as an empty string if no port is requred. If you have a port, prefix it with a ':' i.e. :4243
|
.constant('DOCKER_PORT', '') // Docker port, leave as an empty string if no port is requred. If you have a port, prefix it with a ':' i.e. :4243
|
||||||
.constant('UI_VERSION', 'v0.5')
|
.constant('UI_VERSION', 'v<%= pkg.version %>')
|
||||||
.constant('DOCKER_API_VERSION', 'v1.15');
|
.constant('DOCKER_API_VERSION', 'v1.15');
|
||||||
|
|
|
@ -70,10 +70,10 @@
|
||||||
<td>Hostname:</td>
|
<td>Hostname:</td>
|
||||||
<td>{{ container.Config.Hostname }}</td>
|
<td>{{ container.Config.Hostname }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>IPAddress:</td>
|
<td>IPAddress:</td>
|
||||||
<td>{{ container.NetworkSettings.IPAddress }}</td>
|
<td>{{ container.NetworkSettings.IPAddress }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cmd:</td>
|
<td>Cmd:</td>
|
||||||
<td>{{ container.Config.Cmd }}</td>
|
<td>{{ container.Config.Cmd }}</td>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
angular.module('containerLogs', [])
|
angular.module('containerLogs', [])
|
||||||
.controller('ContainerLogsController', ['$scope', '$routeParams', '$location', '$anchorScroll', 'ContainerLogs', 'Container', 'ViewSpinner',
|
.controller('ContainerLogsController', ['$scope', '$routeParams', '$location', '$anchorScroll', 'ContainerLogs', 'Container', 'ViewSpinner',
|
||||||
function($scope, $routeParams, $location, $anchorScroll, ContainerLogs, Container, ViewSpinner) {
|
function($scope, $routeParams, $location, $anchorScroll, ContainerLogs, Container, ViewSpinner) {
|
||||||
$scope.stdout = '';
|
$scope.stdout = '';
|
||||||
$scope.stderr = '';
|
$scope.stderr = '';
|
||||||
$scope.showTimestamps = false;
|
$scope.showTimestamps = false;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ function($scope, $routeParams, $location, $anchorScroll, ContainerLogs, Containe
|
||||||
|
|
||||||
function getLogs() {
|
function getLogs() {
|
||||||
ContainerLogs.get($routeParams.id, {stdout: 1, stderr: 0, timestamps: $scope.showTimestamps}, function(data, status, headers, config) {
|
ContainerLogs.get($routeParams.id, {stdout: 1, stderr: 0, timestamps: $scope.showTimestamps}, function(data, status, headers, config) {
|
||||||
// Replace carriage returns twith newlines to clean up output
|
// Replace carriage returns twith newlines to clean up output
|
||||||
$scope.stdout = data.replace(/[\r]/g, '\n');
|
$scope.stdout = data.replace(/[\r]/g, '\n');
|
||||||
});
|
});
|
||||||
ContainerLogs.get($routeParams.id, {stdout: 0, stderr: 1}, function(data, status, headers, config) {
|
ContainerLogs.get($routeParams.id, {stdout: 0, stderr: 1}, function(data, status, headers, config) {
|
||||||
|
@ -40,9 +40,9 @@ function($scope, $routeParams, $location, $anchorScroll, ContainerLogs, Containe
|
||||||
$scope.scrollTo = function(id) {
|
$scope.scrollTo = function(id) {
|
||||||
$location.hash(id);
|
$location.hash(id);
|
||||||
$anchorScroll();
|
$anchorScroll();
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.toggleTimestamps = function() {
|
$scope.toggleTimestamps = function() {
|
||||||
getLogs();
|
getLogs();
|
||||||
}
|
};
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<input type="checkbox" ng-model="displayAll"
|
<input type="checkbox" ng-model="displayAll"
|
||||||
ng-change="toggleGetAll()"/> Display All
|
ng-change="toggleGetAll()"/> Display All
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
|
|
|
@ -27,7 +27,7 @@ angular.module('dashboard', [])
|
||||||
}
|
}
|
||||||
|
|
||||||
Container.query({all: 1}, function(d) {
|
Container.query({all: 1}, function(d) {
|
||||||
var running = 0
|
var running = 0;
|
||||||
var ghost = 0;
|
var ghost = 0;
|
||||||
var stopped = 0;
|
var stopped = 0;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ function($scope, $q, $routeParams, $location, Image, Container, Messages, LineCh
|
||||||
var containers = [];
|
var containers = [];
|
||||||
for (var i = 0; i < d.length; i++) {
|
for (var i = 0; i < d.length; i++) {
|
||||||
var c = d[i];
|
var c = d[i];
|
||||||
if (c.Image == tag) {
|
if (c.Image === tag) {
|
||||||
containers.push(new ContainerViewModel(c));
|
containers.push(new ContainerViewModel(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,40 @@
|
||||||
'use strict';
|
angular.module('<%= pkg.name %>.filters', [])
|
||||||
|
|
||||||
angular.module('dockerui.filters', [])
|
|
||||||
.filter('truncate', function() {
|
.filter('truncate', function() {
|
||||||
|
'use strict';
|
||||||
return function(text, length, end) {
|
return function(text, length, end) {
|
||||||
if (isNaN(length))
|
if (isNaN(length)) {
|
||||||
length = 10;
|
length = 10;
|
||||||
|
}
|
||||||
|
|
||||||
if (end === undefined)
|
if (end === undefined){
|
||||||
end = "...";
|
end = '...';
|
||||||
|
}
|
||||||
|
|
||||||
if (text.length <= length || text.length - end.length <= length) {
|
if (text.length <= length || text.length - end.length <= length) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return String(text).substring(0, length-end.length) + end;
|
return String(text).substring(0, length - end.length) + end;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('statusbadge', function() {
|
.filter('statusbadge', function() {
|
||||||
|
'use strict';
|
||||||
return function(text) {
|
return function(text) {
|
||||||
if (text === 'Ghost') {
|
if (text === 'Ghost') {
|
||||||
return 'important';
|
return 'important';
|
||||||
} else if (text.indexOf('Exit') != -1 && text !== 'Exit 0') {
|
} else if (text.indexOf('Exit') !== -1 && text !== 'Exit 0') {
|
||||||
return 'warning';
|
return 'warning';
|
||||||
}
|
}
|
||||||
return 'success';
|
return 'success';
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('getstatetext', function() {
|
.filter('getstatetext', function() {
|
||||||
|
'use strict';
|
||||||
return function(state) {
|
return function(state) {
|
||||||
if (state == undefined) return '';
|
if (state === undefined) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
if (state.Ghost && state.Running) {
|
if (state.Ghost && state.Running) {
|
||||||
return 'Ghost';
|
return 'Ghost';
|
||||||
}
|
}
|
||||||
|
@ -44,8 +48,11 @@ angular.module('dockerui.filters', [])
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('getstatelabel', function() {
|
.filter('getstatelabel', function() {
|
||||||
|
'use strict';
|
||||||
return function(state) {
|
return function(state) {
|
||||||
if (state == undefined) return '';
|
if (state === undefined) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
if (state.Ghost && state.Running) {
|
if (state.Ghost && state.Running) {
|
||||||
return 'label-important';
|
return 'label-important';
|
||||||
|
@ -57,32 +64,36 @@ angular.module('dockerui.filters', [])
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('humansize', function() {
|
.filter('humansize', function() {
|
||||||
|
'use strict';
|
||||||
return function(bytes) {
|
return function(bytes) {
|
||||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||||
if (bytes == 0) {
|
if (bytes === 0) {
|
||||||
return 'n/a';
|
return 'n/a';
|
||||||
}
|
}
|
||||||
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);
|
||||||
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[[i]];
|
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[[i]];
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('containername', function() {
|
.filter('containername', function() {
|
||||||
|
'use strict';
|
||||||
return function(container) {
|
return function(container) {
|
||||||
var name = container.Names[0];
|
var name = container.Names[0];
|
||||||
return name.substring(1, name.length);
|
return name.substring(1, name.length);
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('repotag', function() {
|
.filter('repotag', function() {
|
||||||
|
'use strict';
|
||||||
return function(image) {
|
return function(image) {
|
||||||
if (image.RepoTags && image.RepoTags.length > 0) {
|
if (image.RepoTags && image.RepoTags.length > 0) {
|
||||||
var tag = image.RepoTags[0];
|
var tag = image.RepoTags[0];
|
||||||
if (tag == '<none>:<none>') { tag = ''; }
|
if (tag === '<none>:<none>') { tag = ''; }
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('getdate', function() {
|
.filter('getdate', function() {
|
||||||
|
'use strict';
|
||||||
return function(data) {
|
return function(data) {
|
||||||
//Multiply by 1000 for the unix format
|
//Multiply by 1000 for the unix format
|
||||||
var date = new Date(data * 1000);
|
var date = new Date(data * 1000);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use strict';
|
angular.module('<%= pkg.name %>.services', ['ngResource'])
|
||||||
|
|
||||||
angular.module('dockerui.services', ['ngResource'])
|
|
||||||
.factory('Container', function($resource, Settings) {
|
.factory('Container', function($resource, Settings) {
|
||||||
|
'use strict';
|
||||||
// Resource for interacting with the docker containers
|
// Resource for interacting with the docker containers
|
||||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#containers
|
// http://docs.docker.io/en/latest/api/docker_remote_api.html#containers
|
||||||
return $resource(Settings.url + '/containers/:id/:action', {
|
return $resource(Settings.url + '/containers/:id/:action', {
|
||||||
|
@ -21,6 +20,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('ContainerLogs', function($resource, $http, Settings) {
|
.factory('ContainerLogs', function($resource, $http, Settings) {
|
||||||
|
'use strict';
|
||||||
return {
|
return {
|
||||||
get: function(id, params, callback) {
|
get: function(id, params, callback) {
|
||||||
$http({
|
$http({
|
||||||
|
@ -31,9 +31,10 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
console.log(error, data);
|
console.log(error, data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
})
|
})
|
||||||
.factory('Image', function($resource, Settings) {
|
.factory('Image', function($resource, Settings) {
|
||||||
|
'use strict';
|
||||||
// Resource for docker images
|
// Resource for docker images
|
||||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#images
|
// http://docs.docker.io/en/latest/api/docker_remote_api.html#images
|
||||||
return $resource(Settings.url + '/images/:id/:action', {}, {
|
return $resource(Settings.url + '/images/:id/:action', {}, {
|
||||||
|
@ -49,6 +50,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('Docker', function($resource, Settings) {
|
.factory('Docker', function($resource, Settings) {
|
||||||
|
'use strict';
|
||||||
// Information for docker
|
// Information for docker
|
||||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
|
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
|
||||||
return $resource(Settings.url + '/version', {}, {
|
return $resource(Settings.url + '/version', {}, {
|
||||||
|
@ -56,6 +58,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('Auth', function($resource, Settings) {
|
.factory('Auth', function($resource, Settings) {
|
||||||
|
'use strict';
|
||||||
// Auto Information for docker
|
// Auto Information for docker
|
||||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#set-auth-configuration
|
// http://docs.docker.io/en/latest/api/docker_remote_api.html#set-auth-configuration
|
||||||
return $resource(Settings.url + '/auth', {}, {
|
return $resource(Settings.url + '/auth', {}, {
|
||||||
|
@ -64,6 +67,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('System', function($resource, Settings) {
|
.factory('System', function($resource, Settings) {
|
||||||
|
'use strict';
|
||||||
// System for docker
|
// System for docker
|
||||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
|
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
|
||||||
return $resource(Settings.url + '/info', {}, {
|
return $resource(Settings.url + '/info', {}, {
|
||||||
|
@ -71,6 +75,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('Settings', function(DOCKER_ENDPOINT, DOCKER_PORT, DOCKER_API_VERSION, UI_VERSION) {
|
.factory('Settings', function(DOCKER_ENDPOINT, DOCKER_PORT, DOCKER_API_VERSION, UI_VERSION) {
|
||||||
|
'use strict';
|
||||||
var url = DOCKER_ENDPOINT;
|
var url = DOCKER_ENDPOINT;
|
||||||
if (DOCKER_PORT) {
|
if (DOCKER_PORT) {
|
||||||
url = url + DOCKER_PORT + '\\' + DOCKER_PORT;
|
url = url + DOCKER_PORT + '\\' + DOCKER_PORT;
|
||||||
|
@ -82,10 +87,11 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
rawUrl: DOCKER_ENDPOINT + DOCKER_PORT + '/' + DOCKER_API_VERSION,
|
rawUrl: DOCKER_ENDPOINT + DOCKER_PORT + '/' + DOCKER_API_VERSION,
|
||||||
uiVersion: UI_VERSION,
|
uiVersion: UI_VERSION,
|
||||||
url: url,
|
url: url,
|
||||||
firstLoad: true,
|
firstLoad: true
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.factory('ViewSpinner', function() {
|
.factory('ViewSpinner', function() {
|
||||||
|
'use strict';
|
||||||
var spinner = new Spinner();
|
var spinner = new Spinner();
|
||||||
var target = document.getElementById('view');
|
var target = document.getElementById('view');
|
||||||
|
|
||||||
|
@ -95,6 +101,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.factory('Messages', function($rootScope) {
|
.factory('Messages', function($rootScope) {
|
||||||
|
'use strict';
|
||||||
return {
|
return {
|
||||||
send: function(title, text) {
|
send: function(title, text) {
|
||||||
$.gritter.add({
|
$.gritter.add({
|
||||||
|
@ -102,7 +109,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
text: text,
|
text: text,
|
||||||
time: 2000,
|
time: 2000,
|
||||||
before_open: function() {
|
before_open: function() {
|
||||||
if($('.gritter-item-wrapper').length == 3) {
|
if($('.gritter-item-wrapper').length === 3) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +121,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
text: text,
|
text: text,
|
||||||
time: 6000,
|
time: 6000,
|
||||||
before_open: function() {
|
before_open: function() {
|
||||||
if($('.gritter-item-wrapper').length == 4) {
|
if($('.gritter-item-wrapper').length === 4) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,6 +130,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.factory('Dockerfile', function(Settings) {
|
.factory('Dockerfile', function(Settings) {
|
||||||
|
'use strict';
|
||||||
var url = Settings.rawUrl + '/build';
|
var url = Settings.rawUrl + '/build';
|
||||||
return {
|
return {
|
||||||
build: function(file, callback) {
|
build: function(file, callback) {
|
||||||
|
@ -138,6 +146,7 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.factory('LineChart', function(Settings) {
|
.factory('LineChart', function(Settings) {
|
||||||
|
'use strict';
|
||||||
var url = Settings.rawUrl + '/build';
|
var url = Settings.rawUrl + '/build';
|
||||||
return {
|
return {
|
||||||
build: function(id, data, getkey){
|
build: function(id, data, getkey){
|
||||||
|
@ -157,10 +166,10 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
}
|
}
|
||||||
|
|
||||||
var labels = [];
|
var labels = [];
|
||||||
var data = [];
|
data = [];
|
||||||
var keys = Object.keys(map);
|
var keys = Object.keys(map);
|
||||||
|
|
||||||
for (var i = keys.length - 1; i > -1; i--) {
|
for (i = keys.length - 1; i > -1; i--) {
|
||||||
var k = keys[i];
|
var k = keys[i];
|
||||||
labels.push(k);
|
labels.push(k);
|
||||||
data.push(map[k]);
|
data.push(map[k]);
|
||||||
|
|
|
@ -22,8 +22,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.jumbotron .btn {
|
.jumbotron .btn {
|
||||||
font-size: 21px;
|
|
||||||
padding: 14px 24px;
|
padding: 14px 24px;
|
||||||
|
font-size: 21px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.marketing {
|
.marketing {
|
||||||
|
@ -46,15 +46,15 @@ body {
|
||||||
|
|
||||||
.masthead .nav li {
|
.masthead .nav li {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
width: 1%;
|
|
||||||
float: none;
|
float: none;
|
||||||
|
width: 1%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.masthead .nav li a {
|
.masthead .nav li a {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-left: 1px solid rgba(255,255,255,.75);
|
|
||||||
border-right: 1px solid rgba(0,0,0,.1);
|
border-right: 1px solid rgba(0,0,0,.1);
|
||||||
|
border-left: 1px solid rgba(255,255,255,.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
.masthead .nav li:first-child a {
|
.masthead .nav li:first-child a {
|
||||||
|
@ -81,8 +81,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-remove {
|
.btn-remove {
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
|
@ -97,33 +97,15 @@ body {
|
||||||
padding: 10px 15px 0 15px;
|
padding: 10px 15px 0 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#response {
|
|
||||||
width: 80%;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#editor {
|
|
||||||
height: 300px;
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid #DDD;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.messages {
|
.messages {
|
||||||
max-height: 50px;
|
max-height: 50px;
|
||||||
overflow-y: scroll;
|
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.legend .title {
|
.legend .title {
|
||||||
|
padding: 0 0.3em;
|
||||||
margin: 0.5em;
|
margin: 0.5em;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 0 0 0 1em;
|
border-width: 0 0 0 1em;
|
||||||
padding: 0 0.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre.pre-x-scrollable {
|
|
||||||
max-height: 700px;
|
|
||||||
word-wrap: normal;
|
|
||||||
white-space: pre;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
module.exports = function (grunt) {
|
||||||
|
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||||
|
grunt.loadNpmTasks('grunt-recess');
|
||||||
|
grunt.loadNpmTasks('grunt-karma');
|
||||||
|
grunt.loadNpmTasks('grunt-html2js');
|
||||||
|
|
||||||
|
// Default task.
|
||||||
|
grunt.registerTask('default', ['jshint','build','karma:unit']);
|
||||||
|
grunt.registerTask('build', ['clean','html2js','concat','recess:build', 'copy']);
|
||||||
|
grunt.registerTask('release', ['clean','html2js','uglify','jshint','karma:unit','concat:index', 'recess:min', 'copy']);
|
||||||
|
grunt.registerTask('test-watch', ['karma:watch']);
|
||||||
|
|
||||||
|
// Print a timestamp (useful for when watching)
|
||||||
|
grunt.registerTask('timestamp', function() {
|
||||||
|
grunt.log.subhead(Date());
|
||||||
|
});
|
||||||
|
|
||||||
|
var karmaConfig = function(configFile, customOptions) {
|
||||||
|
var options = { configFile: configFile, keepalive: true };
|
||||||
|
var travisOptions = process.env.TRAVIS && { browsers: ['Firefox'], reporters: 'dots' };
|
||||||
|
return grunt.util._.extend(options, customOptions, travisOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Project configuration.
|
||||||
|
grunt.initConfig({
|
||||||
|
distdir: 'dist',
|
||||||
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
|
banner:
|
||||||
|
'/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
|
||||||
|
'<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
|
||||||
|
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
|
||||||
|
' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
|
||||||
|
src: {
|
||||||
|
js: ['app/**/*.js'],
|
||||||
|
jsTpl: ['<%= distdir %>/templates/**/*.js'],
|
||||||
|
specs: ['test/**/*.spec.js'],
|
||||||
|
scenarios: ['test/**/*.scenario.js'],
|
||||||
|
html: ['index.html'],
|
||||||
|
tpl: {
|
||||||
|
app: ['app/components/**/*.html']
|
||||||
|
},
|
||||||
|
css: ['assets/css/app.css']
|
||||||
|
},
|
||||||
|
clean: ['<%= distdir %>/*'],
|
||||||
|
copy: {
|
||||||
|
assets: {
|
||||||
|
files: [{ dest: '<%= distdir %>/assets', src : '**', expand: true, cwd: 'assets/' }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
karma: {
|
||||||
|
unit: { options: karmaConfig('test/unit/karma.conf.js') },
|
||||||
|
watch: { options: karmaConfig('test/unit/karma.conf.js', { singleRun:false, autoWatch: true}) }
|
||||||
|
},
|
||||||
|
html2js: {
|
||||||
|
app: {
|
||||||
|
options: {
|
||||||
|
base: '.'
|
||||||
|
},
|
||||||
|
src: ['<%= src.tpl.app %>'],
|
||||||
|
dest: '<%= distdir %>/templates/app.js',
|
||||||
|
module: '<%= pkg.name %>.templates'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
concat:{
|
||||||
|
dist:{
|
||||||
|
options: {
|
||||||
|
banner: "<%= banner %>",
|
||||||
|
process: true
|
||||||
|
},
|
||||||
|
src:['<%= src.js %>', '<%= src.jsTpl %>'],
|
||||||
|
dest:'<%= distdir %>/<%= pkg.name %>.js'
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
src: ['index.html'],
|
||||||
|
dest: '<%= distdir %>/index.html',
|
||||||
|
options: {
|
||||||
|
process: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
angular: {
|
||||||
|
src:['assets/js/angularjs/1.2.6/angular.min.js',
|
||||||
|
'assets/js/angularjs/1.2.6/angular-route.min.js',
|
||||||
|
'assets/js/angularjs/1.2.6/angular-resource.min.js'],
|
||||||
|
dest: '<%= distdir %>/angular.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
uglify: {
|
||||||
|
dist:{
|
||||||
|
options: {
|
||||||
|
banner: "<%= banner %>"
|
||||||
|
},
|
||||||
|
src:['<%= src.js %>' ,'<%= src.jsTpl %>'],
|
||||||
|
dest:'<%= distdir %>/<%= pkg.name %>.js'
|
||||||
|
},
|
||||||
|
angular: {
|
||||||
|
src:['<%= concat.angular.src %>'],
|
||||||
|
dest: '<%= distdir %>/angular.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
recess: {
|
||||||
|
build: {
|
||||||
|
files: {
|
||||||
|
'<%= distdir %>/<%= pkg.name %>.css':
|
||||||
|
['<%= src.css %>'] },
|
||||||
|
options: {
|
||||||
|
compile: true,
|
||||||
|
noOverqualifying: false // TODO: Added because of .nav class, rename
|
||||||
|
}
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
files: {
|
||||||
|
'<%= distdir %>/<%= pkg.name %>.css': ['<%= src.css %>']
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
compress: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
all: {
|
||||||
|
files:['<%= src.js %>', '<%= src.specs %>', '<%= src.css %>', '<%= src.tpl.app %>', '<%= src.tpl.common %>', '<%= src.html %>'],
|
||||||
|
tasks:['default','timestamp']
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
files:['<%= src.js %>', '<%= src.specs %>', '<%= src.css %>', '<%= src.tpl.app %>', '<%= src.tpl.common %>', '<%= src.html %>'],
|
||||||
|
tasks:['build','timestamp']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
jshint:{
|
||||||
|
files:['gruntFile.js', '<%= src.js %>', '<%= src.jsTpl %>', '<%= src.specs %>', '<%= src.scenarios %>'],
|
||||||
|
options:{
|
||||||
|
curly:true,
|
||||||
|
eqeqeq:true,
|
||||||
|
immed:true,
|
||||||
|
latedef:true,
|
||||||
|
newcap:true,
|
||||||
|
noarg:true,
|
||||||
|
sub:true,
|
||||||
|
boss:true,
|
||||||
|
eqnull:true,
|
||||||
|
globals:{
|
||||||
|
angular: false,
|
||||||
|
'$': false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
25
index.html
25
index.html
|
@ -1,16 +1,17 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" ng-app="dockerui">
|
<html lang="en" ng-app="<%= pkg.name %>">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>DockerUI</title>
|
<title>DockerUI</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="author" content="Michael Crosby crosbymichael.com">
|
<meta name="author" content="<%= pkg.author %>">
|
||||||
|
|
||||||
<link href="assets/css/bootstrap.min.css" rel="stylesheet">
|
<link href="assets/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<link href="assets/css/jquery.gritter.css" rel="stylesheet">
|
<link href="assets/css/jquery.gritter.css" rel="stylesheet">
|
||||||
|
|
||||||
<link href="assets/css/app.css" rel="stylesheet">
|
<link href="<%= pkg.name %>.css" rel="stylesheet">
|
||||||
|
|
||||||
|
|
||||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||||
<!--[if lt IE 9]>
|
<!--[if lt IE 9]>
|
||||||
|
@ -31,23 +32,7 @@
|
||||||
<script src="assets/js/Chart.min.js"></script>
|
<script src="assets/js/Chart.min.js"></script>
|
||||||
<script src="assets/js/legend.js"></script>
|
<script src="assets/js/legend.js"></script>
|
||||||
|
|
||||||
<script src="app/app.js"></script>
|
<script src="<%= pkg.name %>.js"></script>
|
||||||
<script src="app/shared/services.js"></script>
|
|
||||||
<script src="app/shared/filters.js"></script>
|
|
||||||
<script src="app/shared/viewmodel.js"></script>
|
|
||||||
<!-- TODO: Add minification build step -->
|
|
||||||
<script src="app/components/masthead/mastheadController.js"></script>
|
|
||||||
<script src="app/components/footer/footerController.js"></script>
|
|
||||||
<script src="app/components/dashboard/dashboardController.js"></script>
|
|
||||||
<script src="app/components/container/containerController.js"></script>
|
|
||||||
<script src="app/components/containers/containersController.js"></script>
|
|
||||||
<script src="app/components/containerLogs/containerLogsController.js"></script>
|
|
||||||
<script src="app/components/startContainer/startContainerController.js"></script>
|
|
||||||
<script src="app/components/image/imageController.js"></script>
|
|
||||||
<script src="app/components/images/imagesController.js"></script>
|
|
||||||
<script src="app/components/sidebar/sidebarController.js"></script>
|
|
||||||
<script src="app/components/settings/settingsController.js"></script>
|
|
||||||
<script src="app/components/builder/builderController.js"></script>
|
|
||||||
|
|
||||||
<!-- Fav and touch icons -->
|
<!-- Fav and touch icons -->
|
||||||
<link rel="shortcut icon" href="assets/ico/favicon.ico">
|
<link rel="shortcut icon" href="assets/ico/favicon.ico">
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"author": "Michael Crosby",
|
||||||
|
"name": "dockerui",
|
||||||
|
"homepage": "https://github.com/crosbymichael/dockerui",
|
||||||
|
"version": "0.6.0-SNAPSHOT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git@github.com:crosbymichael/dockerui.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/crosbymichael/dockerui/issues"
|
||||||
|
},
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "https://raw.githubusercontent.com/crosbymichael/dockerui/master/LICENSE"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.4"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"grunt": "~0.4.0",
|
||||||
|
"grunt-recess": "~0.3",
|
||||||
|
"grunt-contrib-clean": "~0.4.0",
|
||||||
|
"grunt-contrib-copy": "~0.4.0",
|
||||||
|
"grunt-contrib-jshint": "~0.2.0",
|
||||||
|
"grunt-contrib-concat": "~0.1.3",
|
||||||
|
"grunt-contrib-uglify": "~0.1.1",
|
||||||
|
"grunt-karma": "~0.4.4",
|
||||||
|
"grunt-html2js": "~0.1.0",
|
||||||
|
"grunt-contrib-watch": "~0.3.1"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,56 @@
|
||||||
|
// base path, that will be used to resolve files and exclude
|
||||||
|
basePath = '../..';
|
||||||
|
|
||||||
|
// list of files / patterns to load in the browser
|
||||||
|
files = [
|
||||||
|
JASMINE,
|
||||||
|
JASMINE_ADAPTER,
|
||||||
|
'assets/js/jquery-1.11.1.min.js',
|
||||||
|
'assets/js/angularjs/1.2.6/angular.min.js',
|
||||||
|
'assets/js/angularjs/1.2.6/angular-route.min.js',
|
||||||
|
'assets/js/angularjs/1.2.6/angular-resource.min.js',
|
||||||
|
'test/assets/angular/angular-mocks.js',
|
||||||
|
'app/**/*.js',
|
||||||
|
'test/unit/**/*.spec.js',
|
||||||
|
'dist/templates/**/*.js'
|
||||||
|
];
|
||||||
|
|
||||||
|
// use dots reporter, as travis terminal does not support escaping sequences
|
||||||
|
// possible values: 'dots' || 'progress'
|
||||||
|
reporters = 'progress';
|
||||||
|
|
||||||
|
// these are default values, just to show available options
|
||||||
|
|
||||||
|
// web server port
|
||||||
|
port = 8089;
|
||||||
|
|
||||||
|
// cli runner port
|
||||||
|
runnerPort = 9109;
|
||||||
|
|
||||||
|
urlRoot = '/__test/';
|
||||||
|
|
||||||
|
// enable / disable colors in the output (reporters and logs)
|
||||||
|
colors = true;
|
||||||
|
|
||||||
|
// level of logging
|
||||||
|
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
|
||||||
|
logLevel = LOG_INFO;
|
||||||
|
|
||||||
|
// enable / disable watching file and executing tests whenever any file changes
|
||||||
|
autoWatch = false;
|
||||||
|
|
||||||
|
// polling interval in ms (ignored on OS that support inotify)
|
||||||
|
autoWatchInterval = 0;
|
||||||
|
|
||||||
|
// Start these browsers, currently available:
|
||||||
|
// - Chrome
|
||||||
|
// - ChromeCanary
|
||||||
|
// - Firefox
|
||||||
|
// - Opera
|
||||||
|
// - Safari
|
||||||
|
// - PhantomJS
|
||||||
|
browsers = ['Chrome'];
|
||||||
|
|
||||||
|
// Continuous Integration mode
|
||||||
|
// if true, it capture browsers, run tests and exit
|
||||||
|
singleRun = true;
|
|
@ -0,0 +1,156 @@
|
||||||
|
describe('filters', function () {
|
||||||
|
beforeEach(module('<%= pkg.name %>.filters'));
|
||||||
|
|
||||||
|
describe('truncate', function () {
|
||||||
|
it('should truncate the string to 10 characters ending in "..." by default', inject(function(truncateFilter) {
|
||||||
|
expect(truncateFilter('this is 20 chars long')).toBe('this is...');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should truncate the string to 7 characters ending in "..."', inject(function(truncateFilter) {
|
||||||
|
expect(truncateFilter('this is 20 chars long', 7)).toBe('this...');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should truncate the string to 10 characters ending in "???"', inject(function(truncateFilter) {
|
||||||
|
expect(truncateFilter('this is 20 chars long', 10, '???')).toBe('this is???');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('statusbadge', function () {
|
||||||
|
it('should be "important" when input is "Ghost"', inject(function(statusbadgeFilter) {
|
||||||
|
expect(statusbadgeFilter('Ghost')).toBe('important');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be "success" when input is "Exit 0"', inject(function(statusbadgeFilter) {
|
||||||
|
expect(statusbadgeFilter('Exit 0')).toBe('success');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be "warning" when exit code is non-zero', inject(function(statusbadgeFilter) {
|
||||||
|
expect(statusbadgeFilter('Exit 1')).toBe('warning');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getstatetext', function () {
|
||||||
|
|
||||||
|
it('should return an empty string when state is undefined', inject(function(getstatetextFilter) {
|
||||||
|
expect(getstatetextFilter(undefined)).toBe('');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should detect a Ghost state', inject(function(getstatetextFilter) {
|
||||||
|
var state = {
|
||||||
|
Ghost: true,
|
||||||
|
Running: true,
|
||||||
|
Paused: false
|
||||||
|
};
|
||||||
|
expect(getstatetextFilter(state)).toBe('Ghost');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should detect a Paused state', inject(function(getstatetextFilter) {
|
||||||
|
var state = {
|
||||||
|
Ghost: false,
|
||||||
|
Running: true,
|
||||||
|
Paused: true
|
||||||
|
};
|
||||||
|
expect(getstatetextFilter(state)).toBe('Running (Paused)');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should detect a Running state', inject(function(getstatetextFilter) {
|
||||||
|
var state = {
|
||||||
|
Ghost: false,
|
||||||
|
Running: true,
|
||||||
|
Paused: false
|
||||||
|
};
|
||||||
|
expect(getstatetextFilter(state)).toBe('Running');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should detect a Stopped state', inject(function(getstatetextFilter) {
|
||||||
|
var state = {
|
||||||
|
Ghost: false,
|
||||||
|
Running: false,
|
||||||
|
Paused: false
|
||||||
|
};
|
||||||
|
expect(getstatetextFilter(state)).toBe('Stopped');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getstatelabel', function () {
|
||||||
|
it('should return an empty string when state is undefined', inject(function(getstatelabelFilter) {
|
||||||
|
expect(getstatelabelFilter(undefined)).toBe('');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should return label-important when a ghost state is detected', inject(function(getstatelabelFilter) {
|
||||||
|
var state = {
|
||||||
|
Ghost: true,
|
||||||
|
Running: true,
|
||||||
|
Paused: false
|
||||||
|
};
|
||||||
|
expect(getstatelabelFilter(state)).toBe('label-important');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should return label-success when a running state is detected', inject(function(getstatelabelFilter) {
|
||||||
|
var state = {
|
||||||
|
Ghost: false,
|
||||||
|
Running: true,
|
||||||
|
Paused: false
|
||||||
|
};
|
||||||
|
expect(getstatelabelFilter(state)).toBe('label-success');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('humansize', function () {
|
||||||
|
it('should return n/a when size is zero', inject(function(humansizeFilter) {
|
||||||
|
expect(humansizeFilter(0)).toBe('n/a');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle Bytes values', inject(function(humansizeFilter) {
|
||||||
|
expect(humansizeFilter(512)).toBe('512 Bytes');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle KB values', inject(function(humansizeFilter) {
|
||||||
|
expect(humansizeFilter(5120)).toBe('5 KB');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle MB values', inject(function(humansizeFilter) {
|
||||||
|
expect(humansizeFilter(5 * Math.pow(10, 6))).toBe('5 MB');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle GB values', inject(function(humansizeFilter) {
|
||||||
|
expect(humansizeFilter(5 * Math.pow(10, 9))).toBe('5 GB');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle TB values', inject(function(humansizeFilter) {
|
||||||
|
expect(humansizeFilter(5 * Math.pow(10, 12))).toBe('5 TB');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('containername', function () {
|
||||||
|
it('should strip the leading slash from container name', inject(function(containernameFilter) {
|
||||||
|
var container = {
|
||||||
|
Names: ['/elegant_ardinghelli']
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(containernameFilter(container)).toBe('elegant_ardinghelli');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('repotag', function () {
|
||||||
|
it('should not display empty repo tag', inject(function(repotagFilter) {
|
||||||
|
var image = {
|
||||||
|
RepoTags: ['<none>:<none>']
|
||||||
|
};
|
||||||
|
expect(repotagFilter(image)).toBe('');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display a normal repo tag', inject(function(repotagFilter) {
|
||||||
|
var image = {
|
||||||
|
RepoTags: ['ubuntu:latest']
|
||||||
|
};
|
||||||
|
expect(repotagFilter(image)).toBe('ubuntu:latest');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getdate', function () {
|
||||||
|
it('should convert the Docker date to a human readable form', inject(function(getdateFilter) {
|
||||||
|
expect(getdateFilter(1420424998)).toBe('Sun Jan 04 2015');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue