feat(ux): normalize quick actions buttons (#2389)

* feat(ux): normalize quick actions buttons

Fixes #2013

* fix(ux): fix wrong naming of variable
pull/2421/head
Jan Jansen 2018-10-31 03:50:38 +01:00 committed by Anthony Lapenna
parent 8df64031e8
commit 78bf374548
8 changed files with 137 additions and 27 deletions

View File

@ -0,0 +1,44 @@
<div class="btn-group btn-group-xs" role="group" aria-label="..." style="display:inline-flex;">
<a
ng-if="$ctrl.state.showQuickActionLogs && $ctrl.taskId === undefined"
style="margin: 0 2.5px;"
ui-sref="docker.containers.container.logs({id: $ctrl.containerId, nodeName: $ctrl.nodeName})"
title="Logs">
<i class="fa fa-file-alt space-right" aria-hidden="true"></i>
</a>
<a
ng-if="$ctrl.state.showQuickActionLogs && $ctrl.taskId !== undefined"
style="margin: 0 2.5px;"
ui-sref="docker.tasks.task.logs({id: $ctrl.taskId})"
title="Logs">
<i class="fa fa-file-alt space-right" aria-hidden="true"></i>
</a>
<a
ng-if="$ctrl.state.showQuickActionInspect && $ctrl.taskId === undefined"
style="margin: 0 2.5px;"
ui-sref="docker.containers.container.inspect({id: $ctrl.containerId, nodeName: $ctrl.nodeName})"
title="Inspect">
<i class="fa fa-info-circle space-right" aria-hidden="true"></i>
</a>
<a
ng-if="$ctrl.state.showQuickActionInspect && $ctrl.taskId !== undefined"
style="margin: 0 2.5px;"
ui-sref="docker.tasks.task({id: $ctrl.taskId})"
title="Inspect">
<i class="fa fa-info-circle space-right" aria-hidden="true"></i>
</a>
<a
ng-if="$ctrl.state.showQuickActionStats && ['starting', 'running', 'healthy', 'unhealthy'].indexOf($ctrl.status) !== -1"
style="margin: 0 2.5px;"
ui-sref="docker.containers.container.stats({id: $ctrl.containerId, nodeName: $ctrl.nodeName})"
title="Stats">
<i class="fa fa-chart-area space-right" aria-hidden="true"></i>
</a>
<a
ng-if="$ctrl.state.showQuickActionConsole && ['starting', 'running', 'healthy', 'unhealthy'].indexOf($ctrl.status) !== -1"
style="margin: 0 2.5px;"
ui-sref="docker.containers.container.console({id: $ctrl.containerId, nodeName: $ctrl.nodeName})"
title="Console">
<i class="fa fa-terminal space-right" aria-hidden="true"></i>
</a>
</div>

View File

@ -0,0 +1,10 @@
angular.module('portainer.docker').component('containerQuickActions', {
templateUrl: 'app/docker/components/container-quick-actions/containerQuickActions.html',
bindings: {
containerId: '<',
nodeName: '<',
status: '<',
state: '<',
taskId: '<'
}
});

View File

@ -222,12 +222,7 @@
<span ng-if="['starting','healthy','unhealthy'].indexOf(item.Status) === -1" class="label label-{{ item.Status|containerstatusbadge }}">{{ item.Status }}</span>
</td>
<td ng-if="!$ctrl.offlineMode && ($ctrl.settings.showQuickActionStats || $ctrl.settings.showQuickActionLogs || $ctrl.settings.showQuickActionConsole || $ctrl.settings.showQuickActionInspect)" ng-show="$ctrl.columnVisibility.columns.actions.display">
<div class="btn-group btn-group-xs" role="group" aria-label="..." style="display:inline-flex;">
<a ng-if="$ctrl.settings.showQuickActionStats" style="margin: 0 2.5px;" ui-sref="docker.containers.container.stats({id: item.Id, nodeName: item.NodeName})" title="Stats"><i class="fa fa-chart-area space-right" aria-hidden="true"></i></a>
<a ng-if="$ctrl.settings.showQuickActionLogs" style="margin: 0 2.5px;" ui-sref="docker.containers.container.logs({id: item.Id, nodeName: item.NodeName})" title="Logs"><i class="fa fa-file-alt space-right" aria-hidden="true"></i></a>
<a ng-if="$ctrl.settings.showQuickActionConsole" style="margin: 0 2.5px;" ui-sref="docker.containers.container.console({id: item.Id, nodeName: item.NodeName})" title="Console"><i class="fa fa-terminal space-right" aria-hidden="true"></i></a>
<a ng-if="$ctrl.settings.showQuickActionInspect" style="margin: 0 2.5px;" ui-sref="docker.containers.container.inspect({id: item.Id, nodeName: item.NodeName})" title="Inspect"><i class="fa fa-info-circle space-right" aria-hidden="true"></i></a>
</div>
<container-quick-actions container-id="item.Id" node-name="item.NodeName" status="item.Status" state="$ctrl.settings"></container-quick-actions>
</td>
<td ng-if="$ctrl.offlineMode">
</td>

View File

@ -64,11 +64,8 @@
<a ng-if="$ctrl.agentProxy && item.Container" ui-sref="docker.containers.container({ id: item.Container.Id, nodeName: item.Container.NodeName })" class="monospaced">{{ item.Id }}Doz</a>
</td>
<td>
<div class="btn-group btn-group-xs" role="group" aria-label="..." >
<a style="margin: 0 2.5px;" ui-sref="docker.containers.container.logs({ id: item.Container.Id, nodeName: item.Container.NodeName })" title="Logs" ng-if="$ctrl.agentProxy && item.Container.Id"><i class="fa fa-file-alt space-right" aria-hidden="true"></i></a>
<a style="margin: 0 2.5px;" ui-sref="docker.tasks.task.logs({ id: item.Id })" title="Logs" ng-if="!$ctrl.agentProxy && $ctrl.showTaskLogsButton && item.Status.State|taskhaslogs"><i class="fa fa-file-alt space-right" aria-hidden="true"></i></a>
<a style="margin: 0 2.5px;" ui-sref="docker.containers.container.console({ id: item.Container.Id, nodeName: item.Container.NodeName })" title="Console" ng-if="$ctrl.agentProxy && item.Status.State === 'running'"><i class="fa fa-terminal space-right" aria-hidden="true"></i></a>
</div>
<container-quick-actions ng-if="!$ctrl.agentProxy || !item.Container" container-id="item.ContainerId" task-id="item.Id" status="item.Status.State" state="$ctrl.state"></container-quick-actions>
<container-quick-actions ng-if="$ctrl.agentProxy && item.Container" container-id="item.Container.Id" node-name="item.Container.NodeName" status="item.Status.State" state="$ctrl.state"></container-quick-actions>
</td>
<td>{{ item.Slot ? item.Slot : '-' }}</td>
<td>{{ item.NodeId | tasknodename: $ctrl.nodes }}</td>

View File

@ -4,7 +4,11 @@ function (DatatableService) {
var ctrl = this;
this.state = {
orderBy: this.orderBy
orderBy: this.orderBy,
showQuickActionStats: true,
showQuickActionLogs: true,
showQuickActionConsole: true,
showQuickActionInspect: true
};
this.filters = {

View File

@ -14,13 +14,6 @@
<table class="table table-hover nowrap-cells">
<thead>
<tr>
<th>
<a ng-click="$ctrl.changeOrderBy('Id')">
Id
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Id' && !$ctrl.state.reverseOrder"></i>
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Id' && $ctrl.state.reverseOrder"></i>
</a>
</th>
<th>
<a ng-click="$ctrl.changeOrderBy('Status')">
Status
@ -28,6 +21,14 @@
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Status' && $ctrl.state.reverseOrder"></i>
</a>
</th>
<th>
<a ng-click="$ctrl.changeOrderBy('Id')">
Id
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Id' && !$ctrl.state.reverseOrder"></i>
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Id' && $ctrl.state.reverseOrder"></i>
</a>
</th>
<th>Actions</th>
<th ng-if="$ctrl.showSlotColumn">
<a ng-click="$ctrl.changeOrderBy('Slot')">
Slot
@ -49,24 +50,22 @@
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Updated' && $ctrl.state.reverseOrder"></i>
</a>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" ng-class="{active: item.Checked}">
<td><span class="label label-{{ item.Status.State | taskstatusbadge }}">{{ item.Status.State }}</span></td>
<td>
<a ng-if="!$ctrl.agentProxy || !item.Container" ui-sref="docker.tasks.task({id: item.Id})" class="monospaced">{{ item.ServiceName }}{{ item.Slot ? '.' + item.Slot : '' }}{{ '.' + item.Id }}</a>
<a ng-if="$ctrl.agentProxy && item.Container" ui-sref="docker.containers.container({ id: item.Container.Id, nodeName: item.Container.NodeName })" class="monospaced">{{ item.ServiceName }}{{ item.Slot ? '.' + item.Slot : '' }}{{ '.' + item.Id }}</a>
</td>
<td><span class="label label-{{ item.Status.State | taskstatusbadge }}">{{ item.Status.State }}</span></td>
<td>
<container-quick-actions ng-if="!$ctrl.agentProxy || !item.Container" container-id="item.ContainerId" task-id="item.Id" status="item.Status.State" state="$ctrl.state"></container-quick-actions>
<container-quick-actions ng-if="$ctrl.agentProxy && item.Container" container-id="item.Container.Id" node-name="item.Container.NodeName" status="item.Status.State" state="$ctrl.state"></container-quick-actions>
</td>
<td ng-if="$ctrl.showSlotColumn">{{ item.Slot ? item.Slot : '-' }}</td>
<td>{{ item.NodeId | tasknodename: $ctrl.nodes }}</td>
<td>{{ item.Updated | getisodate }}</td>
<td>
<a ui-sref="docker.tasks.task.logs({ id: item.Id })" ng-if="!$ctrl.agentProxy && $ctrl.showLogsButton && item.Status.State|taskhaslogs"><i class="fa fa-file-alt" aria-hidden="true"></i> View logs</a>
<a ui-sref="docker.containers.container.logs({ id: item.Container.Id, nodeName: item.Container.NodeName })" ng-if="$ctrl.agentProxy && item.Status.State === 'running'"><i class="fa fa-file-alt" aria-hidden="true"></i> View logs</a>
<a ui-sref="docker.containers.container.console({ id: item.Container.Id, nodeName: item.Container.NodeName })" title="Console" ng-if="$ctrl.agentProxy"><i class="fa fa-terminal" aria-hidden="true"></i> Console</a>
</td>
</tr>
<tr ng-if="!$ctrl.dataset">
<td colspan="6" class="text-center text-muted">Loading...</td>

View File

@ -1,6 +1,6 @@
angular.module('portainer.docker').component('tasksDatatable', {
templateUrl: 'app/docker/components/datatables/tasks-datatable/tasksDatatable.html',
controller: 'GenericDatatableController',
controller: 'TasksDatatableController',
bindings: {
titleText: '@',
titleIcon: '@',

View File

@ -0,0 +1,61 @@
angular.module('portainer.docker')
.controller('TasksDatatableController', ['PaginationService', 'DatatableService',
function (PaginationService, DatatableService) {
this.state = {
showQuickActionStats: true,
showQuickActionLogs: true,
showQuickActionConsole: true,
showQuickActionInspect: true,
selectAll: false,
orderBy: this.orderBy,
paginatedItemLimit: PaginationService.getPaginationLimit(this.tableKey),
displayTextFilter: false,
selectedItemCount: 0,
selectedItems: []
};
this.changeOrderBy = function(orderField) {
this.state.reverseOrder = this.state.orderBy === orderField ? !this.state.reverseOrder : false;
this.state.orderBy = orderField;
DatatableService.setDataTableOrder(this.tableKey, orderField, this.state.reverseOrder);
};
this.selectItem = function(item) {
if (item.Checked) {
this.state.selectedItemCount++;
this.state.selectedItems.push(item);
} else {
this.state.selectedItems.splice(this.state.selectedItems.indexOf(item), 1);
this.state.selectedItemCount--;
}
};
this.selectAll = function() {
for (var i = 0; i < this.state.filteredDataSet.length; i++) {
var item = this.state.filteredDataSet[i];
if (item.Checked !== this.state.selectAll) {
item.Checked = this.state.selectAll;
this.selectItem(item);
}
}
};
this.changePaginationLimit = function() {
PaginationService.setPaginationLimit(this.tableKey, this.state.paginatedItemLimit);
};
this.$onInit = function() {
setDefaults(this);
var storedOrder = DatatableService.getDataTableOrder(this.tableKey);
if (storedOrder !== null) {
this.state.reverseOrder = storedOrder.reverse;
this.state.orderBy = storedOrder.orderBy;
}
};
function setDefaults(ctrl) {
ctrl.showTextFilter = ctrl.showTextFilter ? ctrl.showTextFilter : false;
ctrl.state.reverseOrder = ctrl.reverseOrder ? ctrl.reverseOrder : false;
}
}]);