1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-09 07:45:22 +02:00

feat(endpoints): add the ability to browse offline endpoints (#2253)

* feat(back): saved data in snapshot

* feat(endpoints): adding interceptors to retrieve saved data on offline endpoints

* feat(endpoints): offline dashboard working - need tests on offline views

* refactor(endpoints): interceptors cleaning and saving/loading offline endpoints data in/from localstorage

* feat(endpoints): browsing offline endpoints

* feat(endpoints): removing all the link in offline mode - sidebar not working when switching between off and on modes w/ stateManager logic

* feat(endpoints): endpoint status detection in real time

* fix(endpoints): offline swarm endpoint are not accessible anymore

* fix(endpoints): refactor message + disable offline browsing for an endpoint when no snapshot is available for it

* fix(endpoints): adding timeout and enabling loading bar for offline requests

* fix(endpoints): trying to access a down endpoint wont remove sidebar items if it fails

* feat(endpoints): disable checkboxes on offline views for offline mode

* feat(endpoints): updating endpoint status when detecting a change

* refactor(host): moved offline status panel from engine view to new host view

* fix(endpoints): missing endpoint update on ping from home view

* fix(api): rework EndpointUpdate operation

* refactor(offline): moved endpoint status to EndpointProvider and refactor the status-changed detection

* fix(offline): moved status detection to callback on views -> prevent displaying the offline message when endpoint is back online on view change

* fix(offline): offline message is now displayed online when browsing an offline endpoint

* fix(offline): sidebar updates correctly on endpoint status change

* fix(offline): offline panel not displayed and hidden on online mode

* refactor(offline): rework of OfflineMode management

* refactor(offline): extract information-panel for offlineMode into a component

* refactor(offline): remove redundant binding of informationPanel + endpointStatusInterceptor patter as service

* refactor(interceptors): moved interceptors pattern to service pattern

* feat(stacks): prevent inspection of a stack in offline mode

* feat(host): hide devices/disk panels in offline mode

* feat(host): disable browse action in offline mode

* refactor(home): remove comments
This commit is contained in:
baron_l 2018-10-28 10:27:06 +01:00 committed by Anthony Lapenna
parent 354fda31f1
commit a61654a35d
59 changed files with 637 additions and 212 deletions

View file

@ -6,7 +6,7 @@
</rd-header-title>
<rd-header-content>Containers</rd-header-content>
</rd-header>
<information-panel-offline ng-if="offlineMode"></information-panel-offline>
<div class="row">
<div class="col-sm-12" ng-if="containers">
<containers-datatable
@ -16,6 +16,7 @@
show-ownership-column="applicationState.application.authentication"
show-host-column="applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'"
show-add-action="true"
offline-mode="offlineMode"
></containers-datatable>
</div>
</div>

View file

@ -1,11 +1,14 @@
angular.module('portainer.docker')
.controller('ContainersController', ['$scope', 'ContainerService', 'Notifications',
function ($scope, ContainerService, Notifications) {
.controller('ContainersController', ['$scope', 'ContainerService', 'Notifications', 'EndpointProvider',
function ($scope, ContainerService, Notifications, EndpointProvider) {
$scope.offlineMode = false;
function initView() {
ContainerService.containers(1)
.then(function success(data) {
$scope.containers = data;
$scope.offlineMode = EndpointProvider.offlineMode();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve containers');

View file

@ -8,7 +8,7 @@
<dashboard-cluster-agent-info></dashboard-cluster-agent-info>
</div>
</div>
<information-panel-offline ng-if="offlineMode"></information-panel-offline>
<information-panel
ng-if="!applicationState.UI.dismissedInfoPanels['docker-dashboard-info-01'] && !applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'"
title-text="Information"

View file

@ -6,6 +6,8 @@ function ($scope, $q, ContainerService, ImageService, NetworkService, VolumeServ
StateManager.dismissInformationPanel(id);
};
$scope.offlineMode = false;
function initView() {
var endpointMode = $scope.applicationState.endpoint.mode;
var endpointId = EndpointProvider.endpointID();
@ -29,6 +31,7 @@ function ($scope, $q, ContainerService, ImageService, NetworkService, VolumeServ
$scope.stackCount = data.stacks.length;
$scope.info = data.info;
$scope.endpoint = data.endpoint;
$scope.offlineMode = EndpointProvider.offlineMode();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to load dashboard data');

View file

@ -1,13 +1,14 @@
angular.module('portainer.docker').controller('HostViewController', [
'$q', 'SystemService', 'Notifications', 'StateManager', 'AgentService', 'ContainerService', 'Authentication',
function HostViewController($q, SystemService, Notifications, StateManager, AgentService, ContainerService, Authentication) {
'$q', 'SystemService', 'Notifications', 'StateManager', 'AgentService', 'ContainerService', 'Authentication', 'EndpointProvider',
function HostViewController($q, SystemService, Notifications, StateManager, AgentService, ContainerService, Authentication, EndpointProvider) {
var ctrl = this;
this.$onInit = initView;
ctrl.state = {
isAgent: false,
isAdmin : false
isAdmin : false,
offlineMode: false
};
this.engineDetails = {};
@ -30,6 +31,7 @@ angular.module('portainer.docker').controller('HostViewController', [
.then(function success(data) {
ctrl.engineDetails = buildEngineDetails(data);
ctrl.hostDetails = buildHostDetails(data.info);
ctrl.state.offlineMode = EndpointProvider.offlineMode();
ctrl.jobs = data.jobs;
if (ctrl.state.isAgent && agentApiVersion > 1) {

View file

@ -7,7 +7,8 @@
devices="$ctrl.devices"
refresh-url="docker.host"
browse-url="docker.host.browser"
is-job-enabled="$ctrl.state.isAdmin"
offline-mode="$ctrl.state.offlineMode"
is-job-enabled="$ctrl.state.isAdmin && !$ctrl.state.offlineMode"
job-url="docker.host.job"
jobs="$ctrl.jobs"
></host-overview>

View file

@ -7,7 +7,7 @@
<rd-header-content>Images</rd-header-content>
</rd-header>
<div class="row">
<div class="row" ng-if="!offlineMode">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-download" title-text="Pull image ">
@ -51,7 +51,7 @@
</rd-widget>
</div>
</div>
<information-panel-offline ng-if="offlineMode"></information-panel-offline>
<div class="row">
<div class="col-sm-12">
<images-datatable
@ -63,6 +63,7 @@
remove-action="removeAction"
force-remove-action="confirmRemovalAction"
export-in-progress="state.exportInProgress"
offline-mode="offlineMode"
></images-datatable>
</div>
</div>

View file

@ -1,6 +1,6 @@
angular.module('portainer.docker')
.controller('ImagesController', ['$scope', '$state', 'ImageService', 'Notifications', 'ModalService', 'HttpRequestHelper', 'FileSaver', 'Blob',
function ($scope, $state, ImageService, Notifications, ModalService, HttpRequestHelper, FileSaver, Blob) {
.controller('ImagesController', ['$scope', '$state', 'ImageService', 'Notifications', 'ModalService', 'HttpRequestHelper', 'FileSaver', 'Blob', 'EndpointProvider',
function ($scope, $state, ImageService, Notifications, ModalService, HttpRequestHelper, FileSaver, Blob, EndpointProvider) {
$scope.state = {
actionInProgress: false,
exportInProgress: false
@ -113,10 +113,13 @@ function ($scope, $state, ImageService, Notifications, ModalService, HttpRequest
});
};
$scope.offlineMode = false;
function initView() {
ImageService.images(true)
.then(function success(data) {
$scope.images = data;
$scope.offlineMode = EndpointProvider.offlineMode();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve images');

View file

@ -6,7 +6,7 @@
</rd-header-title>
<rd-header-content>Networks</rd-header-content>
</rd-header>
<information-panel-offline ng-if="offlineMode"></information-panel-offline>
<div class="row">
<div class="col-sm-12">
<networks-datatable
@ -16,6 +16,7 @@
remove-action="removeAction"
show-ownership-column="applicationState.application.authentication"
show-host-column="applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'"
offline-mode="offlineMode"
></networks-datatable>
</div>
</div>

View file

@ -1,6 +1,6 @@
angular.module('portainer.docker')
.controller('NetworksController', ['$scope', '$state', 'NetworkService', 'Notifications', 'HttpRequestHelper',
function ($scope, $state, NetworkService, Notifications, HttpRequestHelper) {
.controller('NetworksController', ['$scope', '$state', 'NetworkService', 'Notifications', 'HttpRequestHelper', 'EndpointProvider',
function ($scope, $state, NetworkService, Notifications, HttpRequestHelper, EndpointProvider) {
$scope.removeAction = function (selectedItems) {
var actionCount = selectedItems.length;
@ -24,10 +24,13 @@ function ($scope, $state, NetworkService, Notifications, HttpRequestHelper) {
});
};
$scope.offlineMode = false;
function initView() {
NetworkService.networks(true, true, true)
.then(function success(data) {
$scope.networks = data;
$scope.offlineMode = EndpointProvider.offlineMode();
})
.catch(function error(err) {
$scope.networks = [];

View file

@ -6,7 +6,7 @@
</rd-header-title>
<rd-header-content>Volumes</rd-header-content>
</rd-header>
<information-panel-offline ng-if="offlineMode"></information-panel-offline>
<div class="row">
<div class="col-sm-12">
<volumes-datatable
@ -17,6 +17,7 @@
show-ownership-column="applicationState.application.authentication"
show-host-column="applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'"
show-browse-action="applicationState.endpoint.mode.agentProxy"
offline-mode="offlineMode"
></volumes-datatable>
</div>
</div>

View file

@ -1,6 +1,6 @@
angular.module('portainer.docker')
.controller('VolumesController', ['$q', '$scope', '$state', 'VolumeService', 'ServiceService', 'VolumeHelper', 'Notifications', 'HttpRequestHelper',
function ($q, $scope, $state, VolumeService, ServiceService, VolumeHelper, Notifications, HttpRequestHelper) {
.controller('VolumesController', ['$q', '$scope', '$state', 'VolumeService', 'ServiceService', 'VolumeHelper', 'Notifications', 'HttpRequestHelper', 'EndpointProvider',
function ($q, $scope, $state, VolumeService, ServiceService, VolumeHelper, Notifications, HttpRequestHelper, EndpointProvider) {
$scope.removeAction = function (selectedItems) {
var actionCount = selectedItems.length;
@ -24,6 +24,8 @@ function ($q, $scope, $state, VolumeService, ServiceService, VolumeHelper, Notif
});
};
$scope.offlineMode = false;
function initView() {
var endpointProvider = $scope.applicationState.endpoint.mode.provider;
var endpointRole = $scope.applicationState.endpoint.mode.role;
@ -35,6 +37,7 @@ function ($q, $scope, $state, VolumeService, ServiceService, VolumeHelper, Notif
})
.then(function success(data) {
var services = data.services;
$scope.offlineMode = EndpointProvider.offlineMode();
$scope.volumes = data.attached.map(function(volume) {
volume.dangling = false;
return volume;