Merge branch 'release/1.10.2'

pull/455/head 1.10.2
Anthony Lapenna 2016-11-26 00:50:55 +13:00
commit 0e40bb13fc
33 changed files with 191 additions and 41 deletions

View File

@ -6,7 +6,7 @@ import (
// main is the entry point of the program
func main() {
kingpin.Version("1.10.1")
kingpin.Version("1.10.2")
var (
endpoint = kingpin.Flag("host", "Dockerd endpoint").Default("unix:///var/run/docker.sock").Short('H').String()
addr = kingpin.Flag("bind", "Address and port to serve Portainer").Default(":9000").Short('p').String()

View File

@ -5,6 +5,7 @@ angular.module('portainer', [
'ui.select',
'ngCookies',
'ngSanitize',
'angularUtils.directives.dirPagination',
'portainer.services',
'portainer.helpers',
'portainer.filters',
@ -188,4 +189,5 @@ angular.module('portainer', [
.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('CONFIG_ENDPOINT', 'settings')
.constant('TEMPLATES_ENDPOINT', 'templates')
.constant('UI_VERSION', 'v1.10.1');
.constant('PAGINATION_MAX_ITEMS', 10)
.constant('UI_VERSION', 'v1.10.2');

View File

@ -207,7 +207,6 @@
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-sitemap" title="Connected networks"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<thead>
@ -218,7 +217,7 @@
<th>Actions</th>
</thead>
<tbody>
<tr ng-repeat="(key, value) in container.NetworkSettings.Networks">
<tr dir-paginate="(key, value) in container.NetworkSettings.Networks | itemsPerPage: pagination_count">
<td><a ui-sref="network({id: value.NetworkID})">{{ key }}</a></td>
<td>{{ value.IPAddress || '-' }}</td>
<td>{{ value.Gateway || '-' }}</td>
@ -229,6 +228,9 @@
</tr>
</tbody>
</table>
<div class="pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</rd-widget-body>
</rd-widget>
</div>

View File

@ -1,12 +1,13 @@
angular.module('container', [])
.controller('ContainerController', ['$scope', '$state','$stateParams', '$filter', 'Container', 'ContainerCommit', 'ImageHelper', 'Network', 'Messages',
function ($scope, $state, $stateParams, $filter, Container, ContainerCommit, ImageHelper, Network, Messages) {
.controller('ContainerController', ['$scope', '$state','$stateParams', '$filter', 'Container', 'ContainerCommit', 'ImageHelper', 'Network', 'Messages', 'Settings',
function ($scope, $state, $stateParams, $filter, Container, ContainerCommit, ImageHelper, Network, Messages, Settings) {
$scope.activityTime = 0;
$scope.portBindings = [];
$scope.config = {
Image: '',
Registry: ''
};
$scope.pagination_count = Settings.pagination_count;
var update = function () {
$('#loadingViewSpinner').show();

View File

@ -83,7 +83,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="container in (state.filteredContainers = ( containers | filter:state.filter | orderBy:sortType:sortReverse))">
<tr dir-paginate="container in (state.filteredContainers = ( containers | filter:state.filter | orderBy:sortType:sortReverse | itemsPerPage: pagination_count))">
<td><input type="checkbox" ng-model="container.Checked" ng-change="selectItem(container)"/></td>
<td><span class="label label-{{ container.Status|containerstatusbadge }}">{{ container.Status|containerstatus }}</span></td>
<td ng-if="swarm && !swarm_mode"><a ui-sref="container({id: container.Id})">{{ container|swarmcontainername}}</a></td>
@ -106,6 +106,9 @@
</tr>
</tbody>
</table>
<div ng-if="containers" class="pull-left pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</div>
</rd-widget-body>
<rd-widget>

View File

@ -8,6 +8,7 @@ function ($scope, Container, ContainerHelper, Info, Settings, Messages, Config)
$scope.sortReverse = false;
$scope.state.selectedItemCount = 0;
$scope.swarm_mode = false;
$scope.pagination_count = Settings.pagination_count;
$scope.order = function (sortType) {
$scope.sortReverse = ($scope.sortType === sortType) ? !$scope.sortReverse : false;

View File

@ -13,6 +13,7 @@ function ($scope, $state, Service, Volume, Network, ImageHelper, Messages) {
User: '',
Env: [],
Labels: [],
ContainerLabels: [],
Volumes: [],
Network: '',
ExtraNetworks: [],
@ -59,6 +60,14 @@ function ($scope, $state, Service, Volume, Network, ImageHelper, Messages) {
$scope.formValues.Labels.splice(index, 1);
};
$scope.addContainerLabel = function() {
$scope.formValues.ContainerLabels.push({ name: '', value: ''});
};
$scope.removeContainerLabel = function(index) {
$scope.formValues.ContainerLabels.splice(index, 1);
};
function prepareImageConfig(config, input) {
var imageConfig = ImageHelper.createImageConfig(input.Image, input.Registry);
config.TaskTemplate.ContainerSpec.Image = imageConfig.repo + ':' + imageConfig.tag;
@ -113,7 +122,15 @@ function ($scope, $state, Service, Volume, Network, ImageHelper, Messages) {
labels[label.name] = label.value;
}
});
config.TaskTemplate.ContainerSpec.Labels = labels;
config.Labels = labels;
var containerLabels = {};
input.ContainerLabels.forEach(function (label) {
if (label.name && label.value) {
containerLabels[label.name] = label.value;
}
});
config.TaskTemplate.ContainerSpec.Labels = containerLabels;
}
function prepareVolumes(config, input) {

View File

@ -284,6 +284,35 @@
<!-- !labels-input-list -->
</div>
<!-- !labels-->
<!-- container-labels -->
<div class="form-group">
<label for="service_env" class="col-sm-1 control-label text-left">Container labels</label>
<div class="col-sm-11">
<span class="label label-default interactive" ng-click="addContainerLabel()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> container label
</span>
</div>
<!-- container-labels-input-list -->
<div class="col-sm-offset-1 col-sm-11 form-inline" style="margin-top: 10px;">
<div ng-repeat="label in formValues.ContainerLabels" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="label.name" placeholder="e.g. com.example.foo">
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="removeContainerLabel($index)">
<i class="fa fa-minus" aria-hidden="true"></i>
</button>
</span>
</div>
</div>
</div>
<!-- !container-labels-input-list -->
</div>
<!-- !container-labels-->
</form>
</div>
<!-- !tab-labels -->

View File

@ -49,13 +49,16 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="event in (events | filter:state.filter | orderBy:sortType:sortReverse)">
<tr dir-paginate="event in (events | filter:state.filter | orderBy:sortType:sortReverse | itemsPerPage: pagination_count)">
<td>{{ event.Time|getisodatefromtimestamp }}</td>
<td>{{ event.Type }}</td>
<td>{{ event.Details }}</td>
</tr>
</tbody>
</table>
<div ng-if="events" class="pull-left pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</div>
</rd-widget-body>
<rd-widget>

View File

@ -4,6 +4,7 @@ function ($scope, Settings, Messages, Events) {
$scope.state = {};
$scope.sortType = 'Time';
$scope.sortReverse = true;
$scope.pagination_count = Settings.pagination_count;
$scope.order = function(sortType) {
$scope.sortReverse = ($scope.sortType === sortType) ? !$scope.sortReverse : false;

View File

@ -98,7 +98,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="image in (state.filteredImages = (images | filter:state.filter | orderBy:sortType:sortReverse))">
<tr dir-paginate="image in (state.filteredImages = (images | filter:state.filter | orderBy:sortType:sortReverse | itemsPerPage: pagination_count))">
<td><input type="checkbox" ng-model="image.Checked" ng-change="selectItem(image)" /></td>
<td><a ui-sref="image({id: image.Id})">{{ image.Id|truncate:20}}</a></td>
<td>
@ -115,6 +115,9 @@
</tr>
</tbody>
</table>
<div ng-if="images" class="pull-left pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</div>
</rd-widget-body>
<rd-widget>

View File

@ -1,10 +1,11 @@
angular.module('images', [])
.controller('ImagesController', ['$scope', '$state', 'Config', 'Image', 'Messages',
function ($scope, $state, Config, Image, Messages) {
.controller('ImagesController', ['$scope', '$state', 'Config', 'Image', 'Messages', 'Settings',
function ($scope, $state, Config, Image, Messages, Settings) {
$scope.state = {};
$scope.sortType = 'RepoTags';
$scope.sortReverse = true;
$scope.state.selectedItemCount = 0;
$scope.pagination_count = Settings.pagination_count;
$scope.config = {
Image: '',

View File

@ -121,7 +121,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="network in ( state.filteredNetworks = (networks | filter:state.filter | orderBy:sortType:sortReverse))">
<tr dir-paginate="network in ( state.filteredNetworks = (networks | filter:state.filter | orderBy:sortType:sortReverse | itemsPerPage: pagination_count))">
<td><input type="checkbox" ng-model="network.Checked" ng-change="selectItem(network)"/></td>
<td><a ui-sref="network({id: network.Id})">{{ network.Name|truncate:40}}</a></td>
<td>{{ network.Id }}</td>
@ -139,6 +139,9 @@
</tr>
</tbody>
</table>
<div ng-if="networks" class="pull-left pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</div>
</rd-widget-body>
<rd-widget>

View File

@ -1,11 +1,12 @@
angular.module('networks', [])
.controller('NetworksController', ['$scope', '$state', 'Network', 'Config', 'Messages',
function ($scope, $state, Network, Config, Messages) {
.controller('NetworksController', ['$scope', '$state', 'Network', 'Config', 'Messages', 'Settings',
function ($scope, $state, Network, Config, Messages, Settings) {
$scope.state = {};
$scope.state.selectedItemCount = 0;
$scope.state.advancedSettings = false;
$scope.sortType = 'Name';
$scope.sortReverse = false;
$scope.pagination_count = Settings.pagination_count;
$scope.config = {
Name: ''
};

View File

@ -137,6 +137,37 @@
</div>
</td>
</tr>
<tr>
<td>Container labels</td>
<td>
<div class="form-group">
<div class="col-sm-11 nopadding">
<span class="label label-default interactive fit-text-size" ng-click="addContainerLabel(service)">
<i class="fa fa-plus-circle" aria-hidden="true"></i> container label
</span>
</div>
<!-- labels-input-list -->
<div class="col-sm-11 form-inline nopadding" style="margin-top: 10px;">
<div ng-repeat="label in service.ServiceContainerLabels" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon fit-text-size">name</span>
<input type="text" class="form-control" ng-model="label.key" placeholder="e.g. com.example.foo" ng-change="updateLabel(service, label)">
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon fit-text-size">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar" ng-change="updateLabel(service, label)">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="removeContainerLabel(service, $index)">
<i class="fa fa-minus" aria-hidden="true"></i>
</button>
</span>
</div>
</div>
</div>
<!-- !labels-input-list -->
</div>
</td>
</tr>
</tbody>
</table>
</rd-widget-body>
@ -190,7 +221,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="task in (filteredTasks = ( tasks | orderBy:sortType:sortReverse))">
<tr dir-paginate="task in (filteredTasks = ( tasks | orderBy:sortType:sortReverse | itemsPerPage: pagination_count))">
<td><a ui-sref="task({ id: task.Id })">{{ task.Id }}</a></td>
<td><span class="label label-{{ task.Status|taskstatusbadge }}">{{ task.Status }}</span></td>
<td>{{ task.Slot }}</td>
@ -199,6 +230,9 @@
</tr>
</tbody>
</table>
<div ng-if="tasks" class="pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</rd-widget-body>
</rd-widget>
</div>

View File

@ -1,12 +1,13 @@
angular.module('service', [])
.controller('ServiceController', ['$scope', '$stateParams', '$state', 'Service', 'ServiceHelper', 'Task', 'Node', 'Messages',
function ($scope, $stateParams, $state, Service, ServiceHelper, Task, Node, Messages) {
.controller('ServiceController', ['$scope', '$stateParams', '$state', 'Service', 'ServiceHelper', 'Task', 'Node', 'Messages', 'Settings',
function ($scope, $stateParams, $state, Service, ServiceHelper, Task, Node, Messages, Settings) {
$scope.service = {};
$scope.tasks = [];
$scope.displayNode = false;
$scope.sortType = 'Status';
$scope.sortReverse = false;
$scope.pagination_count = Settings.pagination_count;
var previousServiceValues = {};
@ -50,6 +51,14 @@ function ($scope, $stateParams, $state, Service, ServiceHelper, Task, Node, Mess
$scope.updateLabel = function updateLabel(service, label) {
service.hasChanges = service.hasChanges || label.value !== label.originalValue;
};
$scope.addContainerLabel = function addContainerLabel(service) {
service.hasChanges = true;
service.ServiceContainerLabels.push({ key: '', value: '', originalValue: '' });
};
$scope.removeContainerLabel = function removeContainerLabel(service, index) {
var removedElement = service.ServiceContainerLabels.splice(index, 1);
service.hasChanges = service.hasChanges || removedElement !== null;
};
$scope.cancelChanges = function changeServiceImage(service) {
Object.keys(previousServiceValues).forEach(function(attribute) {
@ -60,6 +69,7 @@ function ($scope, $stateParams, $state, Service, ServiceHelper, Task, Node, Mess
// clear out environment variable changes
service.EnvironmentVariables = translateEnvironmentVariables(service.Env);
service.ServiceLabels = translateLabelsToServiceLabels(service.Labels);
service.ServiceContainerLabels = translateLabelsToServiceLabels(service.ContainerLabels);
service.hasChanges = false;
};
@ -68,8 +78,9 @@ function ($scope, $stateParams, $state, Service, ServiceHelper, Task, Node, Mess
$('#loadServicesSpinner').show();
var config = ServiceHelper.serviceToConfig(service.Model);
config.Name = service.newServiceName;
config.Labels = translateServiceLabelsToLabels(service.ServiceLabels);
config.TaskTemplate.ContainerSpec.Env = translateEnvironmentVariablesToEnv(service.EnvironmentVariables);
config.TaskTemplate.ContainerSpec.Labels = translateServiceLabelsToLabels(service.ServiceLabels);
config.TaskTemplate.ContainerSpec.Labels = translateServiceLabelsToLabels(service.ServiceContainerLabels);
config.TaskTemplate.ContainerSpec.Image = service.newServiceImage;
if (service.Mode === 'replicated') {
config.Mode.Replicated.Replicas = service.Replicas;
@ -112,6 +123,7 @@ function ($scope, $stateParams, $state, Service, ServiceHelper, Task, Node, Mess
service.newServiceReplicas = service.Replicas;
service.EnvironmentVariables = translateEnvironmentVariables(service.Env);
service.ServiceLabels = translateLabelsToServiceLabels(service.Labels);
service.ServiceContainerLabels = translateLabelsToServiceLabels(service.ContainerLabels);
$scope.service = service;
Task.query({filters: {service: [service.Name]}}, function (tasks) {
@ -152,7 +164,8 @@ function ($scope, $stateParams, $state, Service, ServiceHelper, Task, Node, Mess
if (env) {
var variables = [];
env.forEach(function(variable) {
var keyValue = variable.split('=');
var idx = variable.indexOf('=');
var keyValue = [variable.slice(0,idx), variable.slice(idx+1)];
var originalValue = (keyValue.length > 1) ? keyValue[1] : '';
variables.push({ key: keyValue[0], value: originalValue, originalValue: originalValue, added: true});
});

View File

@ -52,7 +52,7 @@
</th>
</thead>
<tbody>
<tr ng-repeat="service in (state.filteredServices = ( services | filter:state.filter | orderBy:sortType:sortReverse))">
<tr dir-paginate="service in (state.filteredServices = ( services | filter:state.filter | orderBy:sortType:sortReverse | itemsPerPage: pagination_count))">
<td><input type="checkbox" ng-model="service.Checked" ng-change="selectItem(service)"/></td>
<td><a ui-sref="service({id: service.Id})">{{ service.Name }}</a></td>
<td>{{ service.Image }}</td>
@ -77,6 +77,9 @@
</tr>
</tbody>
</table>
<div ng-if="services" class="pull-left pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</div>
</rd-widget-body>
<rd-widget>

View File

@ -1,10 +1,11 @@
angular.module('services', [])
.controller('ServicesController', ['$scope', '$stateParams', '$state', 'Service', 'ServiceHelper', 'Messages',
function ($scope, $stateParams, $state, Service, ServiceHelper, Messages) {
.controller('ServicesController', ['$scope', '$stateParams', '$state', 'Service', 'ServiceHelper', 'Messages', 'Settings',
function ($scope, $stateParams, $state, Service, ServiceHelper, Messages, Settings) {
$scope.state = {};
$scope.state.selectedItemCount = 0;
$scope.sortType = 'Name';
$scope.sortReverse = false;
$scope.pagination_count = Settings.pagination_count;
$scope.scaleService = function scaleService(service) {
$('#loadServicesSpinner').show();

View File

@ -69,11 +69,14 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="processInfos in state.filteredProcesses = (containerTop.Processes | orderBy:sortType:sortReverse)">
<tr dir-paginate="processInfos in state.filteredProcesses = (containerTop.Processes | orderBy:sortType:sortReverse | itemsPerPage: pagination_count)">
<td ng-repeat="processInfo in processInfos track by $index">{{processInfo}}</td>
</tr>
</tbody>
</table>
<div ng-if="containerTop.Processes" class="pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</rd-widget-body>
</rd-widget>
</div>

View File

@ -7,6 +7,7 @@ function (Settings, $scope, Messages, $timeout, Container, ContainerTop, $stateP
$scope.state = {};
$scope.sortType = 'CMD';
$scope.sortReverse = false;
$scope.pagination_count = Settings.pagination_count;
$scope.order = function (sortType) {
$scope.sortReverse = ($scope.sortType === sortType) ? !$scope.sortReverse : false;
$scope.sortType = sortType;

View File

@ -117,7 +117,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="node in (state.filteredNodes = (swarm.Status | filter:state.filter | orderBy:sortType:sortReverse))">
<tr dir-paginate="node in (state.filteredNodes = (swarm.Status | filter:state.filter | orderBy:sortType:sortReverse | itemsPerPage: pagination_count))">
<td>{{ node.name }}</td>
<td>{{ node.cpu }}</td>
<td>{{ node.memory }}</td>
@ -127,6 +127,9 @@
</tr>
</tbody>
</table>
<div class="pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</rd-widget-body>
</rd-widget>
</div>
@ -182,7 +185,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="node in (state.filteredNodes = (nodes | filter:state.filter | orderBy:sortType:sortReverse))">
<tr dir-paginate="node in (state.filteredNodes = (nodes | filter:state.filter | orderBy:sortType:sortReverse | itemsPerPage: pagination_count))">
<td>{{ node.Description.Hostname }}</td>
<td>{{ node.Spec.Role }}</td>
<td>{{ node.Description.Resources.NanoCPUs / 1000000000 }}</td>
@ -192,6 +195,9 @@
</tr>
</tbody>
</table>
<div class="pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</rd-widget-body>
</rd-widget>
</div>

View File

@ -1,6 +1,6 @@
angular.module('swarm', [])
.controller('SwarmController', ['$scope', 'Info', 'Version', 'Node',
function ($scope, Info, Version, Node) {
.controller('SwarmController', ['$scope', 'Info', 'Version', 'Node', 'Settings',
function ($scope, Info, Version, Node, Settings) {
$scope.sortType = 'Name';
$scope.sortReverse = true;
@ -10,6 +10,7 @@ function ($scope, Info, Version, Node) {
$scope.swarm_mode = false;
$scope.totalCPU = 0;
$scope.totalMemory = 0;
$scope.pagination_count = Settings.pagination_count;
$scope.order = function(sortType) {
$scope.sortReverse = ($scope.sortType === sortType) ? !$scope.sortReverse : false;

View File

@ -121,7 +121,7 @@
</rd-widget-header>
<rd-widget-body classes="padding">
<div class="template-list">
<div ng-repeat="tpl in templates" class="container-template hvr-underline-from-center" id="template_{{ $index }}" ng-click="selectTemplate($index)">
<div dir-paginate="tpl in templates | itemsPerPage: pagination_count" class="container-template hvr-underline-from-center" id="template_{{ tpl.index }}" ng-click="selectTemplate(tpl.index)">
<img class="logo" ng-src="{{ tpl.logo }}" />
<div class="title">{{ tpl.title }}</div>
<div class="description">{{ tpl.description }}</div>
@ -133,6 +133,9 @@
No templates available.
</div>
</div>
<div ng-if="templates">
<dir-pagination-controls></dir-pagination-controls>
</div>
</rd-widget-body>
</rd-widget>
</div>

View File

@ -1,6 +1,6 @@
angular.module('templates', [])
.controller('TemplatesController', ['$scope', '$q', '$state', '$filter', 'Config', 'Info', 'Container', 'ContainerHelper', 'Image', 'Volume', 'Network', 'Templates', 'TemplateHelper', 'Messages',
function ($scope, $q, $state, $filter, Config, Info, Container, ContainerHelper, Image, Volume, Network, Templates, TemplateHelper, Messages) {
.controller('TemplatesController', ['$scope', '$q', '$state', '$filter', 'Config', 'Info', 'Container', 'ContainerHelper', 'Image', 'Volume', 'Network', 'Templates', 'TemplateHelper', 'Messages', 'Settings',
function ($scope, $q, $state, $filter, Config, Info, Container, ContainerHelper, Image, Volume, Network, Templates, TemplateHelper, Messages, Settings) {
$scope.state = {
selectedTemplate: null,
showAdvancedOptions: false
@ -10,6 +10,7 @@ function ($scope, $q, $state, $filter, Config, Info, Container, ContainerHelper,
name: "",
ports: []
};
$scope.pagination_count = Settings.pagination_count;
var selectedItem = -1;
@ -183,7 +184,10 @@ function ($scope, $q, $state, $filter, Config, Info, Container, ContainerHelper,
function initTemplates() {
Templates.get(function (data) {
$scope.templates = data;
$scope.templates = data.map(function(tpl,index){
tpl.index = index;
return tpl;
});
$('#loadTemplatesSpinner').hide();
}, function (e) {
$('#loadTemplatesSpinner').hide();

View File

@ -53,7 +53,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="volume in (state.filteredVolumes = (volumes | filter:state.filter | orderBy:sortType:sortReverse))">
<tr dir-paginate="volume in (state.filteredVolumes = (volumes | filter:state.filter | orderBy:sortType:sortReverse | itemsPerPage: pagination_count))">
<td><input type="checkbox" ng-model="volume.Checked" ng-change="selectItem(volume)"/></td>
<td>{{ volume.Name|truncate:50 }}</td>
<td>{{ volume.Driver }}</td>
@ -67,6 +67,9 @@
</tr>
</tbody>
</table>
<div ng-if="volumes" class="pull-left pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</div>
</rd-widget-body>
<rd-widget>

View File

@ -1,6 +1,6 @@
angular.module('volumes', [])
.controller('VolumesController', ['$scope', '$state', 'Volume', 'Messages',
function ($scope, $state, Volume, Messages) {
.controller('VolumesController', ['$scope', '$state', 'Volume', 'Messages', 'Settings',
function ($scope, $state, Volume, Messages, Settings) {
$scope.state = {};
$scope.state.selectedItemCount = 0;
$scope.sortType = 'Name';
@ -8,6 +8,7 @@ function ($scope, $state, Volume, Messages) {
$scope.config = {
Name: ''
};
$scope.pagination_count = Settings.pagination_count;
$scope.order = function(sortType) {
$scope.sortReverse = ($scope.sortType === sortType) ? !$scope.sortReverse : false;
@ -54,7 +55,7 @@ function ($scope, $state, Volume, Messages) {
function fetchVolumes() {
$('#loadVolumesSpinner').show();
Volume.query({}, function (d) {
$scope.volumes = d.Volumes;
$scope.volumes = d.Volumes || [];
$('#loadVolumesSpinner').hide();
}, function (e) {
$('#loadVolumesSpinner').hide();

View File

@ -41,8 +41,10 @@ angular.module('portainer.helpers', [])
serviceToConfig: function(service) {
return {
Name: service.Spec.Name,
Labels: service.Spec.Labels,
TaskTemplate: service.Spec.TaskTemplate,
Mode: service.Spec.Mode,
UpdateConfig: service.Spec.UpdateConfig,
Networks: service.Spec.Networks,
EndpointSpec: service.Spec.EndpointSpec
};

View File

@ -213,7 +213,7 @@ angular.module('portainer.services', ['ngResource', 'ngSanitize'])
get: {method: 'GET', isArray: true}
});
}])
.factory('Settings', ['DOCKER_ENDPOINT', 'DOCKER_PORT', 'UI_VERSION', function SettingsFactory(DOCKER_ENDPOINT, DOCKER_PORT, UI_VERSION) {
.factory('Settings', ['DOCKER_ENDPOINT', 'DOCKER_PORT', 'UI_VERSION', 'PAGINATION_MAX_ITEMS', function SettingsFactory(DOCKER_ENDPOINT, DOCKER_PORT, UI_VERSION, PAGINATION_MAX_ITEMS) {
'use strict';
var url = DOCKER_ENDPOINT;
if (DOCKER_PORT) {
@ -225,7 +225,8 @@ angular.module('portainer.services', ['ngResource', 'ngSanitize'])
endpoint: DOCKER_ENDPOINT,
uiVersion: UI_VERSION,
url: url,
firstLoad: firstLoad
firstLoad: firstLoad,
pagination_count: PAGINATION_MAX_ITEMS
};
}])
.factory('Messages', ['$rootScope', '$sanitize', function MessagesFactory($rootScope, $sanitize) {

View File

@ -35,8 +35,9 @@ function ServiceViewModel(data) {
} else {
this.Mode = 'global';
}
this.Labels = data.Spec.Labels;
if (data.Spec.TaskTemplate.ContainerSpec) {
this.Labels = data.Spec.TaskTemplate.ContainerSpec.Labels;
this.ContainerLabels = data.Spec.TaskTemplate.ContainerSpec.Labels;
}
if (data.Spec.TaskTemplate.ContainerSpec.Env) {
this.Env = data.Spec.TaskTemplate.ContainerSpec.Env;

View File

@ -202,3 +202,7 @@ input[type="radio"] {
font-size: 0.8em;
margin-bottom: 5px;
}
.pagination-controls {
margin-left: 10px;
}

View File

@ -1,6 +1,6 @@
{
"name": "portainer",
"version": "1.10.1",
"version": "1.10.2",
"homepage": "https://github.com/portainer/portainer",
"authors": [
"Anthony Lapenna <anthony.lapenna at gmail dot com>"
@ -32,6 +32,7 @@
"angular-mocks": "~1.5.0",
"angular-resource": "~1.5.0",
"angular-ui-select": "~0.17.1",
"angular-utils-pagination": "~0.11.1",
"bootstrap": "~3.3.6",
"font-awesome": "~4.6.3",
"filesize": "~3.3.0",

View File

@ -196,6 +196,7 @@ 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-utils-pagination/dirPagination.js',
'bower_components/angular-ui-select/dist/select.min.js'],
dest: '<%= distdir %>/js/angular.js'
}

View File

@ -2,7 +2,7 @@
"author": "Portainer.io",
"name": "portainer",
"homepage": "http://portainer.io",
"version": "1.10.1",
"version": "1.10.2",
"repository": {
"type": "git",
"url": "git@github.com:portainer/portainer.git"