1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-23 15:29:42 +02:00

feat(stacks): support compose v2.0 stack (#1963)

This commit is contained in:
Anthony Lapenna 2018-06-11 15:13:19 +02:00 committed by GitHub
parent ef15cd30eb
commit e3d564325b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
174 changed files with 7898 additions and 5849 deletions

View file

@ -0,0 +1,35 @@
<div class="actionBar">
<div class="btn-group" role="group" aria-label="...">
<button type="button" class="btn btn-sm btn-success" ng-click="$ctrl.startAction($ctrl.selectedItems)"
ng-disabled="$ctrl.selectedItemCount === 0 || $ctrl.noStoppedItemsSelected">
<i class="fa fa-play space-right" aria-hidden="true"></i>Start
</button>
<button type="button" class="btn btn-sm btn-danger" ng-click="$ctrl.stopAction($ctrl.selectedItems)"
ng-disabled="$ctrl.selectedItemCount === 0 || $ctrl.noRunningItemsSelected">
<i class="fa fa-stop space-right" aria-hidden="true"></i>Stop
</button>
<button type="button" class="btn btn-sm btn-danger" ng-click="$ctrl.killAction($ctrl.selectedItems)"
ng-disabled="$ctrl.selectedItemCount === 0">
<i class="fa fa-bomb space-right" aria-hidden="true"></i>Kill
</button>
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.restartAction($ctrl.selectedItems)"
ng-disabled="$ctrl.selectedItemCount === 0">
<i class="fa fa-sync space-right" aria-hidden="true"></i>Restart
</button>
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.pauseAction($ctrl.selectedItems)"
ng-disabled="$ctrl.selectedItemCount === 0 || $ctrl.noRunningItemsSelected">
<i class="fa fa-pause space-right" aria-hidden="true"></i>Pause
</button>
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.resumeAction($ctrl.selectedItems)"
ng-disabled="$ctrl.selectedItemCount === 0 || $ctrl.noPausedItemsSelected">
<i class="fa fa-play space-right" aria-hidden="true"></i>Resume
</button>
<button type="button" class="btn btn-sm btn-danger"
ng-disabled="$ctrl.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.selectedItems)">
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
</button>
</div>
<button type="button" class="btn btn-sm btn-primary" ui-sref="docker.containers.new" ng-if="$ctrl.showAddAction">
<i class="fa fa-plus space-right" aria-hidden="true"></i>Add container
</button>
</div>

View file

@ -0,0 +1,12 @@
angular.module('portainer.docker').component('containersDatatableActions', {
templateUrl: 'app/docker/components/datatables/containers-datatable/actions/containersDatatableActions.html',
controller: 'ContainersDatatableActionsController',
bindings: {
selectedItems: '=',
selectedItemCount: '=',
noStoppedItemsSelected: '=',
noRunningItemsSelected: '=',
noPausedItemsSelected: '=',
showAddAction: '<'
}
});

View file

@ -0,0 +1,104 @@
angular.module('portainer.docker')
.controller('ContainersDatatableActionsController', ['$state', 'ContainerService', 'ModalService', 'Notifications', 'HttpRequestHelper',
function ($state, ContainerService, ModalService, Notifications, HttpRequestHelper) {
this.startAction = function(selectedItems) {
var successMessage = 'Container successfully started';
var errorMessage = 'Unable to start container';
executeActionOnContainerList(selectedItems, ContainerService.startContainer, successMessage, errorMessage);
};
this.stopAction = function(selectedItems) {
var successMessage = 'Container successfully stopped';
var errorMessage = 'Unable to stop container';
executeActionOnContainerList(selectedItems, ContainerService.stopContainer, successMessage, errorMessage);
};
this.restartAction = function(selectedItems) {
var successMessage = 'Container successfully restarted';
var errorMessage = 'Unable to restart container';
executeActionOnContainerList(selectedItems, ContainerService.restartContainer, successMessage, errorMessage);
};
this.killAction = function(selectedItems) {
var successMessage = 'Container successfully killed';
var errorMessage = 'Unable to kill container';
executeActionOnContainerList(selectedItems, ContainerService.killContainer, successMessage, errorMessage);
};
this.pauseAction = function(selectedItems) {
var successMessage = 'Container successfully paused';
var errorMessage = 'Unable to pause container';
executeActionOnContainerList(selectedItems, ContainerService.pauseContainer, successMessage, errorMessage);
};
this.resumeAction = function(selectedItems) {
var successMessage = 'Container successfully resumed';
var errorMessage = 'Unable to resume container';
executeActionOnContainerList(selectedItems, ContainerService.resumeContainer, successMessage, errorMessage);
};
this.removeAction = function(selectedItems) {
var isOneContainerRunning = false;
for (var i = 0; i < selectedItems.length; i++) {
var container = selectedItems[i];
if (container.State === 'running') {
isOneContainerRunning = true;
break;
}
}
var title = 'You are about to remove one or more container.';
if (isOneContainerRunning) {
title = 'You are about to remove one or more running container.';
}
ModalService.confirmContainerDeletion(title, function (result) {
if(!result) { return; }
var cleanVolumes = false;
if (result[0]) {
cleanVolumes = true;
}
removeSelectedContainers(selectedItems, cleanVolumes);
}
);
};
function executeActionOnContainerList(containers, action, successMessage, errorMessage) {
var actionCount = containers.length;
angular.forEach(containers, function (container) {
HttpRequestHelper.setPortainerAgentTargetHeader(container.NodeName);
action(container.Id)
.then(function success() {
Notifications.success(successMessage, container.Names[0]);
})
.catch(function error(err) {
Notifications.error('Failure', err, errorMessage);
})
.finally(function final() {
--actionCount;
if (actionCount === 0) {
$state.reload();
}
});
});
}
function removeSelectedContainers(containers, cleanVolumes) {
var actionCount = containers.length;
angular.forEach(containers, function (container) {
ContainerService.remove(container, cleanVolumes)
.then(function success() {
Notifications.success('Container successfully removed', container.Names[0]);
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove container');
})
.finally(function final() {
--actionCount;
if (actionCount === 0) {
$state.reload();
}
});
});
}
}]);

View file

@ -51,41 +51,14 @@
</span>
</div>
</div>
<div class="actionBar">
<div class="btn-group" role="group" aria-label="...">
<button type="button" class="btn btn-sm btn-success" ng-click="$ctrl.startAction($ctrl.state.selectedItems)"
ng-disabled="$ctrl.state.selectedItemCount === 0 || $ctrl.state.noStoppedItemsSelected">
<i class="fa fa-play space-right" aria-hidden="true"></i>Start
</button>
<button type="button" class="btn btn-sm btn-danger" ng-click="$ctrl.stopAction($ctrl.state.selectedItems)"
ng-disabled="$ctrl.state.selectedItemCount === 0 || $ctrl.state.noRunningItemsSelected">
<i class="fa fa-stop space-right" aria-hidden="true"></i>Stop
</button>
<button type="button" class="btn btn-sm btn-danger" ng-click="$ctrl.killAction($ctrl.state.selectedItems)"
ng-disabled="$ctrl.state.selectedItemCount === 0">
<i class="fa fa-bomb space-right" aria-hidden="true"></i>Kill
</button>
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.restartAction($ctrl.state.selectedItems)"
ng-disabled="$ctrl.state.selectedItemCount === 0">
<i class="fa fa-sync space-right" aria-hidden="true"></i>Restart
</button>
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.pauseAction($ctrl.state.selectedItems)"
ng-disabled="$ctrl.state.selectedItemCount === 0 || $ctrl.state.noRunningItemsSelected">
<i class="fa fa-pause space-right" aria-hidden="true"></i>Pause
</button>
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.resumeAction($ctrl.state.selectedItems)"
ng-disabled="$ctrl.state.selectedItemCount === 0 || $ctrl.state.noPausedItemsSelected">
<i class="fa fa-play space-right" aria-hidden="true"></i>Resume
</button>
<button type="button" class="btn btn-sm btn-danger"
ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.state.selectedItems)">
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
</button>
</div>
<button type="button" class="btn btn-sm btn-primary" ui-sref="docker.containers.new">
<i class="fa fa-plus space-right" aria-hidden="true"></i>Add container
</button>
</div>
<containers-datatable-actions
selected-items="$ctrl.state.selectedItems"
selected-item-count="$ctrl.state.selectedItemCount"
no-stopped-items-selected="$ctrl.state.noStoppedItemsSelected"
no-running-items-selected="$ctrl.state.noRunningItemsSelected"
no-paused-items-selected="$ctrl.state.noPausedItemsSelected"
show-add-action="$ctrl.showAddAction"
></containers-datatable-actions>
<div class="searchBar" ng-if="$ctrl.state.displayTextFilter">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input type="text" class="searchInput" ng-model="$ctrl.state.textFilter" placeholder="Search..." auto-focus>
@ -205,7 +178,7 @@
<td>{{ item.IP ? item.IP : '-' }}</td>
<td ng-if="$ctrl.showHostColumn">{{ item.NodeName ? item.NodeName : '-' }}</td>
<td>
<a ng-if="item.Ports.length > 0" ng-repeat="p in item.Ports" class="image-tag" ng-href="http://{{ $ctrl.publicUrl || p.host }}:{{p.public}}" target="_blank">
<a ng-if="item.Ports.length > 0" ng-repeat="p in item.Ports" class="image-tag" ng-href="http://{{ $ctrl.state.publicUrl || p.host }}:{{p.public}}" target="_blank">
<i class="fa fa-external-link-alt" aria-hidden="true"></i> {{ p.public }}:{{ p.private }}
</a>
<span ng-if="item.Ports.length == 0" >-</span>

View file

@ -11,14 +11,6 @@ angular.module('portainer.docker').component('containersDatatable', {
showTextFilter: '<',
showOwnershipColumn: '<',
showHostColumn: '<',
publicUrl: '<',
containerNameTruncateSize: '<',
startAction: '<',
stopAction: '<',
killAction: '<',
restartAction: '<',
pauseAction: '<',
resumeAction: '<',
removeAction: '<'
showAddAction: '<'
}
});

View file

@ -1,6 +1,6 @@
angular.module('portainer.docker')
.controller('ContainersDatatableController', ['PaginationService', 'DatatableService',
function (PaginationService, DatatableService) {
.controller('ContainersDatatableController', ['PaginationService', 'DatatableService', 'EndpointProvider',
function (PaginationService, DatatableService, EndpointProvider) {
var ctrl = this;
@ -10,7 +10,11 @@ function (PaginationService, DatatableService) {
paginatedItemLimit: PaginationService.getPaginationLimit(this.tableKey),
displayTextFilter: false,
selectedItemCount: 0,
selectedItems: []
selectedItems: [],
noStoppedItemsSelected: true,
noRunningItemsSelected: true,
noPausedItemsSelected: true,
publicURL: EndpointProvider.endpointPublicURL()
};
this.settings = {
@ -45,6 +49,7 @@ function (PaginationService, DatatableService) {
this.state.selectedItems.splice(this.state.selectedItems.indexOf(item), 1);
this.state.selectedItemCount--;
}
DatatableService.setDataTableSelectedItems(this.tableKey + '_' + EndpointProvider.endpointID(), this.state.selectedItems);
};
this.selectItem = function(item) {
@ -139,12 +144,9 @@ function (PaginationService, DatatableService) {
var availableStateFilters = [];
for (var i = 0; i < this.dataset.length; i++) {
var item = this.dataset[i];
if (item.Checked) {
this.selectItem(item);
}
availableStateFilters.push({ label: item.Status, display: true });
}
this.filters.state.values = _.uniqBy(availableStateFilters, 'label');
this.filters.state.values = _.uniqBy(availableStateFilters, 'label');
};
this.updateStoredFilters = function(storedFilters) {
@ -160,6 +162,30 @@ function (PaginationService, DatatableService) {
}
};
function selectPreviouslySelectedItem(item, storedSelectedItems) {
var selectedItem = _.find(storedSelectedItems, function(container) {
return item.Id === container.Id;
});
if (selectedItem) {
item.Checked = true;
ctrl.state.selectedItemCount++;
ctrl.state.selectedItems.push(item);
}
}
this.selectItems = function(storedSelectedItems) {
for (var i = 0; i < this.dataset.length; i++) {
var item = this.dataset[i];
selectPreviouslySelectedItem(item, storedSelectedItems);
}
if (this.state.selectedItemCount > 0 && this.state.selectedItemCount === this.dataset.length) {
this.state.selectAll = true;
}
this.updateSelectionState();
};
this.$onInit = function() {
setDefaults(this);
this.prepareTableFromDataset();
@ -170,6 +196,11 @@ function (PaginationService, DatatableService) {
this.state.orderBy = storedOrder.orderBy;
}
var storedSelectedItems = DatatableService.getDataTableSelectedItems(this.tableKey + '_' + EndpointProvider.endpointID());
if (storedSelectedItems !== null) {
this.selectItems(storedSelectedItems);
}
var storedFilters = DatatableService.getDataTableFilters(this.tableKey);
if (storedFilters !== null) {
this.updateStoredFilters(storedFilters.state.values);