mirror of https://github.com/portainer/portainer
feat(containers): add column visibility dropdown in containers view (#1977)
parent
863d917acc
commit
50020dae89
|
@ -9,6 +9,57 @@
|
|||
<span class="setting" ng-class="{ 'setting-active': $ctrl.state.displayTextFilter }" ng-click="$ctrl.updateDisplayTextFilter()" ng-if="$ctrl.showTextFilter">
|
||||
<i class="fa fa-search" aria-hidden="true"></i> Search
|
||||
</span>
|
||||
<span class="setting" ng-class="{ 'setting-active': $ctrl.columnVisibility.state.open }" uib-dropdown dropdown-append-to-body auto-close="disabled" is-open="$ctrl.columnVisibility.state.open">
|
||||
<span uib-dropdown-toggle ><i class="fa fa-columns space-right" aria-hidden="true"></i>Columns</span>
|
||||
<div class="dropdown-menu dropdown-menu-right" uib-dropdown-menu>
|
||||
<div class="tableMenu">
|
||||
<div class="menuHeader">
|
||||
Show / Hide Columns
|
||||
</div>
|
||||
<div class="menuContent">
|
||||
<div class="md-checkbox">
|
||||
<input id="col_vis_state" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.state.display"/>
|
||||
<label for="col_vis_state" ng-bind="$ctrl.columnVisibility.columns.state.label"></label>
|
||||
</div>
|
||||
<div class="md-checkbox">
|
||||
<input id="col_vis_actions" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.actions.display"/>
|
||||
<label for="col_vis_actions" ng-bind="$ctrl.columnVisibility.columns.actions.label"></label>
|
||||
</div>
|
||||
<div class="md-checkbox">
|
||||
<input id="col_vis_stack" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.stack.display"/>
|
||||
<label for="col_vis_stack" ng-bind="$ctrl.columnVisibility.columns.stack.label"></label>
|
||||
</div>
|
||||
<div class="md-checkbox">
|
||||
<input id="col_vis_image" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.image.display"/>
|
||||
<label for="col_vis_image" ng-bind="$ctrl.columnVisibility.columns.image.label"></label>
|
||||
</div>
|
||||
<div class="md-checkbox">
|
||||
<input id="col_vis_created" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.created.display"/>
|
||||
<label for="col_vis_created" ng-bind="$ctrl.columnVisibility.columns.created.label"></label>
|
||||
</div>
|
||||
<div class="md-checkbox">
|
||||
<input id="col_vis_ip" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.ip.display"/>
|
||||
<label for="col_vis_ip" ng-bind="$ctrl.columnVisibility.columns.ip.label"></label>
|
||||
</div>
|
||||
<div class="md-checkbox" ng-if="$ctrl.showHostColumn">
|
||||
<input id="col_vis_host" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.host.display"/>
|
||||
<label for="col_vis_host" ng-bind="$ctrl.columnVisibility.columns.host.label"></label>
|
||||
</div>
|
||||
<div class="md-checkbox">
|
||||
<input id="col_vis_ports" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.ports.display"/>
|
||||
<label for="col_vis_ports" ng-bind="$ctrl.columnVisibility.columns.ports.label"></label>
|
||||
</div>
|
||||
<div class="md-checkbox">
|
||||
<input id="col_vis_ownership" ng-click="$ctrl.onColumnVisibilityChange()" type="checkbox" ng-model="$ctrl.columnVisibility.columns.ownership.display"/>
|
||||
<label for="col_vis_ownership" ng-bind="$ctrl.columnVisibility.columns.ownership.label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a type="button" class="btn btn-default btn-sm" ng-click="$ctrl.columnVisibility.state.open = false;">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<span class="setting" ng-class="{ 'setting-active': $ctrl.settings.open }" uib-dropdown dropdown-append-to-body auto-close="disabled" is-open="$ctrl.settings.open">
|
||||
<span uib-dropdown-toggle><i class="fa fa-cog" aria-hidden="true"></i> Settings</span>
|
||||
<div class="dropdown-menu dropdown-menu-right" uib-dropdown-menu>
|
||||
|
@ -78,7 +129,7 @@
|
|||
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Names' && $ctrl.state.reverseOrder"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th uib-dropdown dropdown-append-to-body auto-close="disabled" is-open="$ctrl.filters.state.open">
|
||||
<th uib-dropdown dropdown-append-to-body auto-close="disabled" is-open="$ctrl.filters.state.open" ng-show="$ctrl.columnVisibility.columns.state.display">
|
||||
<a ng-click="$ctrl.changeOrderBy('Status')">
|
||||
State
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Status' && !$ctrl.state.reverseOrder"></i>
|
||||
|
@ -105,45 +156,52 @@
|
|||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th ng-if="$ctrl.settings.showQuickActionStats || $ctrl.settings.showQuickActionLogs || $ctrl.settings.showQuickActionConsole || $ctrl.settings.showQuickActionInspect">
|
||||
<th ng-if="$ctrl.settings.showQuickActionStats || $ctrl.settings.showQuickActionLogs || $ctrl.settings.showQuickActionConsole || $ctrl.settings.showQuickActionInspect" ng-show="$ctrl.columnVisibility.columns.actions.display">
|
||||
Quick actions
|
||||
</th>
|
||||
<th>
|
||||
<th ng-show="$ctrl.columnVisibility.columns.stack.display">
|
||||
<a ng-click="$ctrl.changeOrderBy('StackName')">
|
||||
Stack
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'StackName' && !$ctrl.state.reverseOrder"></i>
|
||||
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'StackName' && $ctrl.state.reverseOrder"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<th ng-show="$ctrl.columnVisibility.columns.image.display">
|
||||
<a ng-click="$ctrl.changeOrderBy('Image')">
|
||||
Image
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Image' && !$ctrl.state.reverseOrder"></i>
|
||||
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Image' && $ctrl.state.reverseOrder"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<th ng-show="$ctrl.columnVisibility.columns.created.display">
|
||||
<a ng-click="$ctrl.changeOrderBy('Created')">
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Created' && !$ctrl.state.reverseOrder"></i>
|
||||
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Created' && $ctrl.state.reverseOrder"></i>
|
||||
Created
|
||||
</a>
|
||||
</th>
|
||||
<th ng-show="$ctrl.columnVisibility.columns.ip.display">
|
||||
<a ng-click="$ctrl.changeOrderBy('IP')">
|
||||
IP Address
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'IP' && !$ctrl.state.reverseOrder"></i>
|
||||
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'IP' && $ctrl.state.reverseOrder"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th ng-if="$ctrl.showHostColumn">
|
||||
<th ng-if="$ctrl.showHostColumn" ng-show="$ctrl.columnVisibility.columns.host.display">
|
||||
<a ng-click="$ctrl.changeOrderBy('NodeName')">
|
||||
Host
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'NodeName' && !$ctrl.state.reverseOrder"></i>
|
||||
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'NodeName' && $ctrl.state.reverseOrder"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<th ng-show="$ctrl.columnVisibility.columns.ports.display">
|
||||
<a ng-click="$ctrl.changeOrderBy('Ports')">
|
||||
Published Ports
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Ports' && !$ctrl.state.reverseOrder"></i>
|
||||
<i class="fa fa-sort-alpha-up" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Ports' && $ctrl.state.reverseOrder"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th ng-if="$ctrl.showOwnershipColumn">
|
||||
<th ng-if="$ctrl.showOwnershipColumn" ng-show="$ctrl.columnVisibility.columns.ownership.display">
|
||||
<a ng-click="$ctrl.changeOrderBy('ResourceControl.Ownership')">
|
||||
Ownership
|
||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'ResourceControl.Ownership' && !$ctrl.state.reverseOrder"></i>
|
||||
|
@ -161,11 +219,11 @@
|
|||
</span>
|
||||
<a ui-sref="docker.containers.container({ id: item.Id, nodeName: item.NodeName })" title="{{ item | containername }}">{{ item | containername | truncate: $ctrl.settings.containerNameTruncateSize }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<td ng-show="$ctrl.columnVisibility.columns.state.display">
|
||||
<span ng-if="['starting','healthy','unhealthy'].indexOf(item.Status) !== -1" class="label label-{{ item.Status|containerstatusbadge }} interactive" uib-tooltip="This container has a health check">{{ item.Status }}</span>
|
||||
<span ng-if="['starting','healthy','unhealthy'].indexOf(item.Status) === -1" class="label label-{{ item.Status|containerstatusbadge }}">{{ item.Status }}</span>
|
||||
</td>
|
||||
<td ng-if="$ctrl.settings.showQuickActionStats || $ctrl.settings.showQuickActionLogs || $ctrl.settings.showQuickActionConsole || $ctrl.settings.showQuickActionInspect">
|
||||
<td ng-if="$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>
|
||||
|
@ -173,17 +231,20 @@
|
|||
<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>
|
||||
</td>
|
||||
<td>{{ item.StackName ? item.StackName : '-' }}</td>
|
||||
<td><a ui-sref="docker.images.image({ id: item.Image })">{{ item.Image | trimshasum }}</a></td>
|
||||
<td>{{ item.IP ? item.IP : '-' }}</td>
|
||||
<td ng-if="$ctrl.showHostColumn">{{ item.NodeName ? item.NodeName : '-' }}</td>
|
||||
<td>
|
||||
<td ng-show="$ctrl.columnVisibility.columns.stack.display">{{ item.StackName ? item.StackName : '-' }}</td>
|
||||
<td ng-show="$ctrl.columnVisibility.columns.image.display"><a ui-sref="docker.images.image({ id: item.Image })">{{ item.Image | trimshasum }}</a></td>
|
||||
<td ng-show="$ctrl.columnVisibility.columns.created.display">
|
||||
{{item.Created | getisodatefromtimestamp}}
|
||||
</td>
|
||||
<td ng-show="$ctrl.columnVisibility.columns.ip.display">{{ item.IP ? item.IP : '-' }}</td>
|
||||
<td ng-if="$ctrl.showHostColumn" ng-show="$ctrl.columnVisibility.columns.host.display">{{ item.NodeName ? item.NodeName : '-' }}</td>
|
||||
<td ng-show="$ctrl.columnVisibility.columns.ports.display">
|
||||
<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>
|
||||
</td>
|
||||
<td ng-if="$ctrl.showOwnershipColumn">
|
||||
<td ng-if="$ctrl.showOwnershipColumn" ng-show="$ctrl.columnVisibility.columns.ownership.display">
|
||||
<span>
|
||||
<i ng-class="item.ResourceControl.Ownership | ownershipicon" aria-hidden="true"></i>
|
||||
{{ item.ResourceControl.Ownership ? item.ResourceControl.Ownership : item.ResourceControl.Ownership = 'public' }}
|
||||
|
|
|
@ -34,6 +34,54 @@ function (PaginationService, DatatableService, EndpointProvider) {
|
|||
}
|
||||
};
|
||||
|
||||
this.columnVisibility = {
|
||||
state: {
|
||||
open: false
|
||||
},
|
||||
columns: {
|
||||
state: {
|
||||
label: 'State',
|
||||
display: true
|
||||
},
|
||||
actions: {
|
||||
label: 'Quick Actions',
|
||||
display: true
|
||||
},
|
||||
stack: {
|
||||
label: 'Stack',
|
||||
display: true
|
||||
},
|
||||
image: {
|
||||
label: 'Image',
|
||||
display: true
|
||||
},
|
||||
created: {
|
||||
label: 'Created',
|
||||
display: true
|
||||
},
|
||||
ip: {
|
||||
label: 'IP Address',
|
||||
display: true
|
||||
},
|
||||
host: {
|
||||
label: 'Host',
|
||||
display: true
|
||||
},
|
||||
ports: {
|
||||
label: 'Published Ports',
|
||||
display: true
|
||||
},
|
||||
ownership: {
|
||||
label: 'Ownership',
|
||||
display: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.onColumnVisibilityChange = function() {
|
||||
DatatableService.setColumnVisibilitySettings(this.tableKey, this.columnVisibility);
|
||||
};
|
||||
|
||||
this.changeOrderBy = function(orderField) {
|
||||
this.state.reverseOrder = this.state.orderBy === orderField ? !this.state.reverseOrder : false;
|
||||
this.state.orderBy = orderField;
|
||||
|
@ -181,6 +229,12 @@ function (PaginationService, DatatableService, EndpointProvider) {
|
|||
this.settings = storedSettings;
|
||||
}
|
||||
this.settings.open = false;
|
||||
|
||||
var storedColumnVisibility = DatatableService.getColumnVisibilitySettings(this.tableKey);
|
||||
if (storedColumnVisibility !== null) {
|
||||
this.columnVisibility = storedColumnVisibility;
|
||||
}
|
||||
this.columnVisibility.state.open = false;
|
||||
};
|
||||
|
||||
function setDefaults(ctrl) {
|
||||
|
|
|
@ -23,6 +23,7 @@ function ContainerViewModel(data) {
|
|||
this.Id = data.Id;
|
||||
this.Status = createStatus(data.Status);
|
||||
this.State = data.State;
|
||||
this.Created = data.Created;
|
||||
this.Names = data.Names;
|
||||
// Unavailable in Docker < 1.10
|
||||
if (data.NetworkSettings && !_.isEmpty(data.NetworkSettings.Networks)) {
|
||||
|
|
|
@ -37,6 +37,10 @@ function DatatableServiceFactory(LocalStorage) {
|
|||
LocalStorage.storeDataTableExpandedItems(key, expandedItems);
|
||||
};
|
||||
|
||||
service.setColumnVisibilitySettings = function(key, columnVisibility) {
|
||||
LocalStorage.storeColumnVisibilitySettings(key, columnVisibility);
|
||||
};
|
||||
|
||||
service.getDataTableExpandedItems = function(key) {
|
||||
return LocalStorage.getDataTableExpandedItems(key);
|
||||
};
|
||||
|
@ -49,5 +53,9 @@ function DatatableServiceFactory(LocalStorage) {
|
|||
return LocalStorage.getDataTableSelectedItems(key);
|
||||
};
|
||||
|
||||
service.getColumnVisibilitySettings = function(key) {
|
||||
return LocalStorage.getColumnVisibilitySettings(key);
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
||||
|
|
|
@ -77,6 +77,12 @@ angular.module('portainer.app')
|
|||
getSwarmVisualizerSettings: function(key) {
|
||||
return localStorageService.get('swarmvisualizer_' + key);
|
||||
},
|
||||
storeColumnVisibilitySettings: function(key, data) {
|
||||
localStorageService.set('col_visibility_' + key, data);
|
||||
},
|
||||
getColumnVisibilitySettings: function(key) {
|
||||
return localStorageService.get('col_visibility_' + key);
|
||||
},
|
||||
clean: function() {
|
||||
localStorageService.clearAll();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue