mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 05:45:22 +02:00
feat(motd): add the ability to display motd and dimiss information panels (#2191)
* feat(api): add motd handler * feat(app): add the motd api layer * feat(motd): display motd and add the ability to dismiss information messages * style(home): relocate important message before info01 * feat(api): silently fail when an error occurs during motd retrieval
This commit is contained in:
parent
74ca908759
commit
6ab6cfafb7
20 changed files with 269 additions and 108 deletions
|
@ -3,6 +3,7 @@ angular.module('portainer')
|
|||
.constant('API_ENDPOINT_DOCKERHUB', 'api/dockerhub')
|
||||
.constant('API_ENDPOINT_ENDPOINTS', 'api/endpoints')
|
||||
.constant('API_ENDPOINT_ENDPOINT_GROUPS', 'api/endpoint_groups')
|
||||
.constant('API_ENDPOINT_MOTD', 'api/motd')
|
||||
.constant('API_ENDPOINT_REGISTRIES', 'api/registries')
|
||||
.constant('API_ENDPOINT_RESOURCE_CONTROLS', 'api/resource_controls')
|
||||
.constant('API_ENDPOINT_SETTINGS', 'api/settings')
|
||||
|
|
|
@ -9,30 +9,22 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-if="!applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'">
|
||||
<div class="col-sm-12">
|
||||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Information
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="small">
|
||||
<p class="text-muted" ng-if="applicationState.endpoint.mode.role === 'MANAGER'">
|
||||
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Portainer is connected to a node that is part of a Swarm cluster. Some resources located on other nodes in the cluster might not be available for management, have a look
|
||||
at <a href="http://portainer.readthedocs.io/en/stable/agent.html" target="_blank">our agent setup</a> for more details.
|
||||
</p>
|
||||
<p class="text-muted" ng-if="applicationState.endpoint.mode.role === 'WORKER'">
|
||||
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Portainer is connected to a worker node. Swarm management features will not be available.
|
||||
</p>
|
||||
</span>
|
||||
</div>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
</div>
|
||||
</div>
|
||||
<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"
|
||||
dismiss-action="dismissInformationPanel('docker-dashboard-info-01')">
|
||||
<span class="small">
|
||||
<p class="text-muted" ng-if="applicationState.endpoint.mode.role === 'MANAGER'">
|
||||
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Portainer is connected to a node that is part of a Swarm cluster. Some resources located on other nodes in the cluster might not be available for management, have a look
|
||||
at <a href="http://portainer.readthedocs.io/en/stable/agent.html" target="_blank">our agent setup</a> for more details.
|
||||
</p>
|
||||
<p class="text-muted" ng-if="applicationState.endpoint.mode.role === 'WORKER'">
|
||||
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Portainer is connected to a worker node. Swarm management features will not be available.
|
||||
</p>
|
||||
</span>
|
||||
</information-panel>
|
||||
|
||||
<div class="row" ng-if="(!applicationState.endpoint.mode.agentProxy || applicationState.endpoint.mode.provider !== 'DOCKER_SWARM_MODE') && info && endpoint">
|
||||
<div class="col-sm-12">
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
angular.module('portainer.docker')
|
||||
.controller('DashboardController', ['$scope', '$q', 'ContainerService', 'ImageService', 'NetworkService', 'VolumeService', 'SystemService', 'ServiceService', 'StackService', 'EndpointService', 'Notifications', 'EndpointProvider',
|
||||
function ($scope, $q, ContainerService, ImageService, NetworkService, VolumeService, SystemService, ServiceService, StackService, EndpointService, Notifications, EndpointProvider) {
|
||||
.controller('DashboardController', ['$scope', '$q', 'ContainerService', 'ImageService', 'NetworkService', 'VolumeService', 'SystemService', 'ServiceService', 'StackService', 'EndpointService', 'Notifications', 'EndpointProvider', 'StateManager',
|
||||
function ($scope, $q, ContainerService, ImageService, NetworkService, VolumeService, SystemService, ServiceService, StackService, EndpointService, Notifications, EndpointProvider, StateManager) {
|
||||
|
||||
$scope.dismissInformationPanel = function(id) {
|
||||
StateManager.dismissInformationPanel(id);
|
||||
};
|
||||
|
||||
function initView() {
|
||||
var endpointMode = $scope.applicationState.endpoint.mode;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
angular.module('portainer.app').component('informationPanel', {
|
||||
templateUrl: 'app/portainer/components/information-panel/informationPanel.html',
|
||||
bindings: {
|
||||
titleText: '@'
|
||||
titleText: '@',
|
||||
dismissAction: '&'
|
||||
},
|
||||
transclude: true
|
||||
});
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
<div class="col-sm-12 form-section-title">
|
||||
{{ $ctrl.titleText }}
|
||||
<span style="float: left;">
|
||||
{{ $ctrl.titleText }}
|
||||
</span>
|
||||
<span class="small" style="float: right;">
|
||||
<a ng-click="$ctrl.dismissAction()"><i class="fa fa-times"></i> dismiss</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<ng-transclude></ng-transclude>
|
||||
|
|
4
app/portainer/models/motd.js
Normal file
4
app/portainer/models/motd.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
function MotdViewModel(data) {
|
||||
this.Message = data.Message;
|
||||
this.Hash = data.Hash;
|
||||
}
|
7
app/portainer/rest/motd.js
Normal file
7
app/portainer/rest/motd.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
angular.module('portainer.app')
|
||||
.factory('Motd', ['$resource', 'API_ENDPOINT_MOTD', function MotdFactory($resource, API_ENDPOINT_MOTD) {
|
||||
'use strict';
|
||||
return $resource(API_ENDPOINT_MOTD, {}, {
|
||||
get: { method: 'GET' }
|
||||
});
|
||||
}]);
|
22
app/portainer/services/api/motdService.js
Normal file
22
app/portainer/services/api/motdService.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
angular.module('portainer.app')
|
||||
.factory('MotdService', ['$q', 'Motd', function MotdServiceFactory($q, Motd) {
|
||||
'use strict';
|
||||
var service = {};
|
||||
|
||||
service.motd = function() {
|
||||
var deferred = $q.defer();
|
||||
|
||||
Motd.get().$promise
|
||||
.then(function success(data) {
|
||||
var motd = new MotdViewModel(data);
|
||||
deferred.resolve(motd);
|
||||
})
|
||||
.catch(function error(err) {
|
||||
deferred.reject({msg: 'Unable to retrieve information message', err: err});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
|
@ -26,6 +26,12 @@ angular.module('portainer.app')
|
|||
getApplicationState: function() {
|
||||
return localStorageService.get('APPLICATION_STATE');
|
||||
},
|
||||
storeUIState: function(state) {
|
||||
localStorageService.cookie.set('UI_STATE', state);
|
||||
},
|
||||
getUIState: function() {
|
||||
return localStorageService.cookie.get('UI_STATE');
|
||||
},
|
||||
storeJWT: function(jwt) {
|
||||
localStorageService.set('JWT', jwt);
|
||||
},
|
||||
|
|
|
@ -9,7 +9,20 @@ function StateManagerFactory($q, SystemService, InfoHelper, LocalStorage, Settin
|
|||
loading: true,
|
||||
application: {},
|
||||
endpoint: {},
|
||||
UI: {}
|
||||
UI: {
|
||||
dismissedInfoPanels: {},
|
||||
dismissedInfoHash: ''
|
||||
}
|
||||
};
|
||||
|
||||
manager.dismissInformationPanel = function(id) {
|
||||
state.UI.dismissedInfoPanels[id] = true;
|
||||
LocalStorage.storeUIState(state.UI);
|
||||
};
|
||||
|
||||
manager.dismissImportantInformation = function(hash) {
|
||||
state.UI.dismissedInfoHash = hash;
|
||||
LocalStorage.storeUIState(state.UI);
|
||||
};
|
||||
|
||||
manager.getState = function() {
|
||||
|
@ -68,6 +81,11 @@ function StateManagerFactory($q, SystemService, InfoHelper, LocalStorage, Settin
|
|||
manager.initialize = function () {
|
||||
var deferred = $q.defer();
|
||||
|
||||
var UIState = LocalStorage.getUIState();
|
||||
if (UIState) {
|
||||
state.UI = UIState;
|
||||
}
|
||||
|
||||
var endpointState = LocalStorage.getEndpointState();
|
||||
if (endpointState) {
|
||||
state.endpoint = endpointState;
|
||||
|
|
|
@ -7,7 +7,19 @@
|
|||
<rd-header-content>Endpoints</rd-header-content>
|
||||
</rd-header>
|
||||
|
||||
<information-panel title-text="Information">
|
||||
<information-panel
|
||||
ng-if="motd && applicationState.UI.dismissedInfoHash !== motd.Hash"
|
||||
title-text="Important message"
|
||||
dismiss-action="dismissImportantInformation(motd.Hash)">
|
||||
<span class="text-muted">
|
||||
<p ng-bind-html="motd.Message"></p>
|
||||
</span>
|
||||
</information-panel>
|
||||
|
||||
<information-panel
|
||||
ng-if="!applicationState.UI.dismissedInfoPanels['home-info-01']"
|
||||
title-text="Information"
|
||||
dismiss-action="dismissInformationPanel('home-info-01')">
|
||||
<span class="small text-muted">
|
||||
<p ng-if="endpoints.length > 0">
|
||||
Welcome to Portainer ! Click on any endpoint in the list below to access management features.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('HomeController', ['$q', '$scope', '$state', 'Authentication', 'EndpointService', 'EndpointHelper', 'GroupService', 'Notifications', 'EndpointProvider', 'StateManager', 'ExtensionManager', 'ModalService',
|
||||
function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, GroupService, Notifications, EndpointProvider, StateManager, ExtensionManager, ModalService) {
|
||||
.controller('HomeController', ['$q', '$scope', '$state', 'Authentication', 'EndpointService', 'EndpointHelper', 'GroupService', 'Notifications', 'EndpointProvider', 'StateManager', 'ExtensionManager', 'ModalService', 'MotdService',
|
||||
function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, GroupService, Notifications, EndpointProvider, StateManager, ExtensionManager, ModalService, MotdService) {
|
||||
|
||||
$scope.goToDashboard = function(endpoint) {
|
||||
EndpointProvider.setEndpointID(endpoint.Id);
|
||||
|
@ -12,6 +12,14 @@ function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, G
|
|||
}
|
||||
};
|
||||
|
||||
$scope.dismissImportantInformation = function(hash) {
|
||||
StateManager.dismissImportantInformation(hash);
|
||||
};
|
||||
|
||||
$scope.dismissInformationPanel = function(id) {
|
||||
StateManager.dismissInformationPanel(id);
|
||||
};
|
||||
|
||||
function triggerSnapshot() {
|
||||
EndpointService.snapshot()
|
||||
.then(function success(data) {
|
||||
|
@ -57,6 +65,11 @@ function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, G
|
|||
function initView() {
|
||||
$scope.isAdmin = Authentication.getUserDetails().role === 1;
|
||||
|
||||
MotdService.motd()
|
||||
.then(function success(data) {
|
||||
$scope.motd = data;
|
||||
});
|
||||
|
||||
$q.all({
|
||||
endpoints: EndpointService.endpoints(),
|
||||
groups: GroupService.groups()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue