diff --git a/Makefile b/Makefile
deleted file mode 100644
index efc1779fb..000000000
--- a/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-REF = HEAD
-VERSION = $(shell git describe --always $(REF))
-
-all: less
-
-less:
- less css/*.less > css/app.css
-
-.PHONY: all less
diff --git a/README.md b/README.md
index ca73374fb..05e7aa42f 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ DockerUI is a web interface to interact with the Remote API. The goal is to pro
![Container](/container.png)
###Installation
-Open js/app.(ts/js - js file if you don't want to compile typescript) and change the DOCKER_ENDPOINT constant to your docker ip and port. Then host the site like any other html/js application.
+Open js/app.js and change the DOCKER_ENDPOINT constant to your docker ip and port. Then host the site like any other html/js application.
.constant('DOCKER_ENDPOINT', 'http://192.168.1.9:4243\:4243');
@@ -14,7 +14,6 @@ Open js/app.(ts/js - js file if you don't want to compile typescript) and change
###Stack
* Angular.js
-* Less
* Flatstrap ( Flat Twitter Bootstrap )
diff --git a/css/app.less b/css/app.less
deleted file mode 100644
index 62c986b38..000000000
--- a/css/app.less
+++ /dev/null
@@ -1,85 +0,0 @@
- body {
- padding-top: 20px;
- padding-bottom: 60px;
- }
-
- /* Custom container */
- .container {
- margin: 0 auto;
- max-width: 1000px;
- }
- .container > hr {
- margin: 60px 0;
- }
-
- /* Main marketing message and sign up button */
- .jumbotron {
- margin: 80px 0;
- text-align: center;
- }
- .jumbotron h1 {
- font-size: 100px;
- line-height: 1;
- }
- .jumbotron .lead {
- font-size: 24px;
- line-height: 1.25;
- }
- .jumbotron .btn {
- font-size: 21px;
- padding: 14px 24px;
- }
-
- /* Supporting marketing content */
- .marketing {
- margin: 60px 0;
- }
- .marketing p + h4 {
- margin-top: 28px;
- }
-
-
- /* Customize the navbar links to be fill the entire space of the .navbar */
- .navbar .navbar-inner {
- padding: 0;
- }
- .navbar .nav {
- margin: 0;
- }
- .navbar .nav li {
- display: table-cell;
- width: 1%;
- float: none;
- }
- .navbar .nav li a {
- font-weight: bold;
- text-align: center;
- border-left: 1px solid rgba(255,255,255,.75);
- border-right: 1px solid rgba(0,0,0,.1);
- }
- .navbar .nav li:first-child a {
- border-left: 0;
- border-radius: 3px 0 0 3px;
- }
- .navbar .nav li:last-child a {
- border-right: 0;
- border-radius: 0 3px 3px 0;
- }
-
- .btn-group button {
- margin: 3px;
- }
-
- .detail {
- width: 80%;
- margin: 0 auto;
- }
-
- .btn-remove {
- margin: 0 auto;
- max-width: 70%;
- }
-
- .actions {
- margin: 0 auto;
- }
diff --git a/js/controllers.js b/js/controllers.js
index 6df90d70b..362d097b0 100644
--- a/js/controllers.js
+++ b/js/controllers.js
@@ -1,4 +1,5 @@
+// Controller for the top masthead
function MastheadController($scope) {
$scope.template = 'partials/masthead.html';
@@ -13,6 +14,7 @@ function MastheadController($scope) {
$scope.iclass = '';
$scope.sclass = '';
+ //This is shitty, I need help with this crap.
switch(link) {
case 'home':
$scope.hclass = 'active';
@@ -32,40 +34,124 @@ function MastheadController($scope) {
};
}
-function SideBarController($scope, Container) {
- $scope.template = 'partials/sidebar.html';
-
- Container.query({}, function(d) {
- $scope.containers = d;
- });
-}
-
function HomeController() {
}
-function SettingsController() {
-
+function SettingsController($scope, Auth, System, Docker, Settings) {
+ $scope.auth = {};
+ $scope.info = {};
+ $scope.docker = {};
+
+ $('#response').hide();
+ $scope.alertClass = 'block';
+
+ var showAndHide = function(hide) {
+ $('#response').show();
+ if (hide) {
+ setTimeout(function() { $('#response').hide();}, 5000);
+ }
+ };
+
+ $scope.updateAuthInfo = function() {
+ if ($scope.auth.password != $scope.auth.cpassword) {
+ $scope.response = 'Your passwords do not match.';
+ showAndHide(true);
+ return;
+ }
+ Auth.update(
+ {username: $scope.auth.username, email: $scope.auth.email, password: $scope.auth.password}, function(d) {
+ console.log(d);
+ $scope.alertClass = 'success';
+ $scope.response = 'Auth information updated.';
+ showAndHide(true);
+ }, function(e) {
+ console.log(e);
+ $scope.alertClass = 'error';
+ $scope.response = e.data;
+ showAndHide(false);
+ });
+ };
+
+ Auth.get({}, function(d) {
+ $scope.auth = d;
+ });
+
+ Docker.get({}, function(d) {
+ $scope.docker = d;
+ });
+
+ System.get({}, function(d) {
+ $scope.info = d;
+ });
}
-function ContainerController($scope, $routeParams, Container) {
+// Controls the page that displays a single container and actions on that container.
+function ContainerController($scope, $routeParams, $location, Container) {
+ $('#response').hide();
+ $scope.alertClass = 'block';
+
+ var showAndHide = function(hide) {
+ $('#response').show();
+ if (hide) {
+ setTimeout(function() { $('#response').hide();}, 5000);
+ }
+ };
$scope.start = function(){
Container.start({id: $routeParams.id}, function(d) {
- $scope.response = d;
- });
+ console.log(d);
+ $scope.alertClass = 'success';
+ $scope.response = 'Container started.';
+ showAndHide(true);
+ }, function(e) {
+ console.log(e);
+ $scope.alertClass = 'error';
+ $scope.response = e.data;
+ showAndHide(false);
+ });
};
$scope.stop = function() {
Container.stop({id: $routeParams.id}, function(d) {
- $scope.response = d;
+ console.log(d);
+ $scope.alertClass = 'success';
+ $scope.response = 'Container stopped.';
+ showAndHide(true);
+ }, function(e) {
+ console.log(e);
+ $scope.alertClass = 'error';
+ $scope.response = e.data;
+ showAndHide(false);
+ });
+ };
+
+ $scope.kill = function() {
+ Container.kill({id: $routeParams.id}, function(d) {
+ console.log(d);
+ $scope.alertClass = 'success';
+ $scope.response = 'Container killed.';
+ showAndHide(true);
+ }, function(e) {
+ console.log(e);
+ $scope.alertClass = 'error';
+ $scope.response = e.data;
+ showAndHide(false);
});
};
$scope.remove = function() {
if (confirm("Are you sure you want to remove the container?")) {
Container.remove({id: $routeParams.id}, function(d) {
- $scope.response = d;
+ console.log(d);
+ $scope.alertClass = 'success';
+ $scope.response = 'Container removed.';
+ showAndHide(true);
+ }, function(e){
+ console.log(e);
+ $scope.alertClass = 'error';
+ $scope.response = e.data;
+ showAndHide(false);
});
}
};
@@ -80,13 +166,149 @@ function ContainerController($scope, $routeParams, Container) {
Container.get({id: $routeParams.id}, function(d) {
$scope.container = d;
+ }, function(e) {
+ console.log(e);
+ $location.path('/containers/');
});
$scope.getChanges();
}
-function ContainersController($scope, Container) {
- Container.query({}, function(d) {
- $scope.containers = d;
- });
+// Controller for the list of containers
+function ContainersController($scope, Container, Settings) {
+ $scope.displayAll = Settings.displayAll;
+ $scope.predicate = '-Created';
+
+ var update = function(data) {
+ Container.query(data, function(d) {
+ $scope.containers = d;
+ });
+ };
+
+ $scope.toggleGetAll = function() {
+ Settings.displayAll = $scope.displayAll;
+ var u = update;
+ var data = {all: 0};
+
+ if ($scope.displayAll) {
+ data.all = 1;
+ }
+ u(data);
+ };
+
+ update({all: $scope.displayAll ? 1 : 0});
+}
+
+// Controller for the list of images
+function ImagesController($scope, Image) {
+ $scope.predicate = '-Created';
+
+ Image.query({}, function(d) {
+ $scope.images = d;
+ });
+}
+
+// Controller for a single image and actions on that image
+function ImageController($scope, $routeParams, $location, Image) {
+ $scope.history = [];
+ $scope.tag = {repo: '', force: false};
+
+ $('#response').hide();
+ $scope.alertClass = 'block';
+
+ var showAndHide = function(hide) {
+ $('#response').show();
+ if (hide) {
+ setTimeout(function() { $('#response').hide();}, 5000);
+ }
+ };
+
+ $scope.remove = function() {
+ if (confirm("Are you sure you want to delete this image?")) {
+ Image.remove({id: $routeParams.id}, function(d) {
+ console.log(d);
+ $scope.alertClass = 'success';
+ $scope.response = 'Image removed.';
+ showAndHide(true);
+ }, function(e) {
+ console.log(e);
+ $scope.alertClass = 'error';
+ $scope.response = e.data;
+ showAndHide(false);
+ });
+ }
+ };
+
+ $scope.getHistory = function() {
+ Image.history({id: $routeParams.id}, function(d) {
+ $scope.history = d;
+ });
+ };
+
+ $scope.updateTag = function() {
+ var tag = $scope.tag;
+ Image.tag({id: $routeParams.id, repo: tag.repo, force: tag.force ? 1 : 0}, function(d) {
+ console.log(d);
+ $scope.alertClass = 'success';
+ $scope.response = 'Tag added.';
+ showAndHide(true);
+ }, function(e) {
+ console.log(e);
+ $scope.alertClass = 'error';
+ $scope.response = e.data;
+ showAndHide(false);
+ });
+ };
+
+ Image.get({id: $routeParams.id}, function(d) {
+ $scope.image = d;
+ }, function(e) {
+ console.log(e);
+ $location.path('/images/');
+ });
+
+ $scope.getHistory();
+}
+
+function StartContainerController($scope, $routeParams, $location, Container) {
+ $scope.template = 'partials/startcontainer.html';
+ $scope.memory = 0;
+ $scope.memorySwap = 0;
+ $scope.env = '';
+ $scope.dns = '';
+ $scope.volumesFrom = '';
+ $scope.commands = '';
+
+ $scope.launchContainer = function() {
+ var cmds = null;
+ if ($scope.commands !== '') {
+ cmds = $scope.commands.split('\n');
+ }
+ var id = $routeParams.id;
+ var ctor = Container;
+ var loc = $location;
+ var s = $scope;
+
+ Container.create({
+ Image: id,
+ Memory: $scope.memory,
+ MemorySwap: $scope.memorySwap,
+ Cmd: cmds,
+ VolumesFrom: $scope.volumesFrom
+ }, function(d) {
+ console.log(d);
+ if (d.Id) {
+ ctor.start({id: d.Id}, function(cd) {
+ console.log(cd);
+ loc.path('/containers/' + d.Id + '/');
+ }, function(e) {
+ console.log(e);
+ s.resonse = e.data;
+ });
+ }
+ }, function(e) {
+ console.log(e);
+ $scope.response = e.data;
+ });
+ };
}
diff --git a/js/filters.js b/js/filters.js
index c068dd12a..bac632e30 100644
--- a/js/filters.js
+++ b/js/filters.js
@@ -21,7 +21,42 @@ angular.module('dockerui.filters', [])
return function(text) {
if (text === 'Ghost') {
return 'important';
+ } else if (text.indexOf('Exit') != -1 && text !== 'Exit 0') {
+ return 'warning';
}
return 'success';
};
+ })
+ .filter('getstatetext', function() {
+ return function(state) {
+ if (state == undefined) return '';
+
+ if (state.Ghost && state.Running) {
+ return 'Ghost';
+ }
+ if (state.Running) {
+ return 'Running';
+ }
+ return 'Stopped';
+ };
+ })
+ .filter('getstatelabel', function() {
+ return function(state) {
+ if (state == undefined) return '';
+
+ if (state.Ghost && state.Running) {
+ return 'label-important';
+ }
+ if (state.Running) {
+ return 'label-success';
+ }
+ return '';
+ };
+ })
+ .filter('getdate', function() {
+ return function(data) {
+ //Multiply by 1000 for the unix format
+ var date = new Date(data * 1000);
+ return date.toDateString();
+ };
});
diff --git a/js/services.js b/js/services.js
index daab27383..21a15056a 100644
--- a/js/services.js
+++ b/js/services.js
@@ -7,27 +7,54 @@ angular.module('dockerui.services', ['ngResource'])
return $resource(DOCKER_ENDPOINT + '/containers/:id/:action', {}, {
query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true},
get :{method: 'GET', params: { action:'json'}},
- start: {method: 'POST', params: { action: 'start'}},
- stop: {method: 'POST', params: {t: 5, action: 'stop'}},
- restart: {method: 'POST', params: {t: 5, action: 'restart' }},
- kill :{method: 'POST', params: {action:'kill'}},
+ 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: {v:0}}
+ remove :{method: 'DELETE', params: {id: '@id', v:0}}
});
})
.factory('Image', function($resource, DOCKER_ENDPOINT) {
// Resource for docker images
// http://docs.docker.io/en/latest/api/docker_remote_api.html#images
- return $resource(DOCKER_ENDPOINT + '/images/:name/:action', {}, {
+ return $resource(DOCKER_ENDPOINT + '/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'}},
+ history :{method: 'GET', params: { action:'history'}, isArray: true},
create :{method: 'POST', params: {action:'create'}},
- insert :{method: 'POST', params: {action:'insert'}},
- push :{method: 'POST', params: {action:'push'}},
- tag :{method: 'POST', params: {action:'tag'}},
- delete :{method: 'DELETE'}
+ insert :{method: 'POST', params: {id: '@id', action:'insert'}},
+ push :{method: 'POST', params: {id: '@id', action:'push'}},
+ tag :{method: 'POST', params: {id: '@id', action:'tag'}},
+ delete :{id: '@id', method: 'DELETE'}
});
+ })
+ .factory('Docker', function($resource, DOCKER_ENDPOINT) {
+ // Information for docker
+ // http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
+ return $resource(DOCKER_ENDPOINT + '/version', {}, {
+ get: {method: 'GET'}
+ });
+ })
+ .factory('Auth', function($resource, DOCKER_ENDPOINT) {
+ // Auto Information for docker
+ // http://docs.docker.io/en/latest/api/docker_remote_api.html#set-auth-configuration
+ return $resource(DOCKER_ENDPOINT + '/auth', {}, {
+ get: {method: 'GET'},
+ update: {method: 'POST'}
+ });
+ })
+ .factory('System', function($resource, DOCKER_ENDPOINT) {
+ // System for docker
+ // http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
+ return $resource(DOCKER_ENDPOINT + '/info', {}, {
+ get: {method: 'GET'}
+ });
+ })
+ .factory('Settings', function() {
+ return {
+ displayAll: false
+ };
});
diff --git a/partials/container.html b/partials/container.html
index b72d3789e..df0d0e84d 100644
--- a/partials/container.html
+++ b/partials/container.html
@@ -1,10 +1,14 @@
-
+
+ {{ response }}
+
+
Container: {{ container.Id }}
+
diff --git a/partials/containers.html b/partials/containers.html
index bced94dd0..aaf8aaf4c 100644
--- a/partials/containers.html
+++ b/partials/containers.html
@@ -1,6 +1,9 @@
Containers:
+
+ Display All
+
@@ -12,11 +15,11 @@
-
+
{{ container.Id|truncate:10}} |
- {{ container.Image }} |
- {{ container.Command }} |
- {{ container.Created }} |
+ {{ container.Image }} |
+ {{ container.Command|truncate:40 }} |
+ {{ container.Created|getdate }} |
{{ container.Status }} |
diff --git a/partials/image.html b/partials/image.html
new file mode 100644
index 000000000..05f7b021a
--- /dev/null
+++ b/partials/image.html
@@ -0,0 +1,89 @@
+
+
+
+ {{ response }}
+
+
+
Image: {{ image.id }}
+
+
+
+
+ Created: |
+ {{ image.created }} |
+
+
+ Parent: |
+ {{ image.parent }} |
+
+
+ Container: |
+ {{ image.container }} |
+
+
+ Hostname: |
+ {{ image.container_config.Hostname }} |
+
+
+ User: |
+ {{ image.container_config.User }} |
+
+
+ Cmd: |
+ {{ image.container_config.Cmd }} |
+
+
+ Volumes: |
+ {{ image.container_config.Volumes }} |
+
+
+ Volumes from: |
+ {{ image.container_config.VolumesFrom }} |
+
+
+
+
+
+
+
+
+
+ -
+ {{ change.Id }}: Created: {{ change.Created|getdate }} Created by: {{ change.CreatedBy }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/partials/images.html b/partials/images.html
new file mode 100644
index 000000000..0840f3938
--- /dev/null
+++ b/partials/images.html
@@ -0,0 +1,21 @@
+
+Images:
+
+
+
+
+ Id |
+ Tag |
+ Repository |
+ Created |
+
+
+
+
+ {{ image.Id|truncate:10}} |
+ {{ image.Tag }} |
+ {{ image.Repository }} |
+ {{ image.Created|getdate }} |
+
+
+
diff --git a/partials/settings.html b/partials/settings.html
new file mode 100644
index 000000000..24bb92a37
--- /dev/null
+++ b/partials/settings.html
@@ -0,0 +1,67 @@
+
+
+ {{ response }}
+
+
+
Docker Information
+
+
+ Version{{ docker.Version }}
+ GitCommit{{ docker.GitCommit }}
+ GoVersion{{ docker.GoVersion }}
+
+
+
+
+
+
+ Containers: |
+ {{ info.Containers }} |
+
+
+ Images: |
+ {{ info.Images }} |
+
+
+ Debug: |
+ {{ info.Debug }} |
+
+
+ NFd: |
+ {{ info.NFd }} |
+
+
+ NGoroutines: |
+ {{ info.NGoroutines }} |
+
+
+ MemoryLimit: |
+ {{ info.MemoryLimit }} |
+
+
+ SwapLimit: |
+ {{ info.SwapLimit }} |
+
+
+ NFd: |
+ {{ info.NFd }} |
+
+
+
+
+
+
diff --git a/partials/startcontainer.html b/partials/startcontainer.html
new file mode 100644
index 000000000..98a81f608
--- /dev/null
+++ b/partials/startcontainer.html
@@ -0,0 +1,27 @@
+
+
+ {{ response }}
+
+
+
+