mirror of https://github.com/portainer/portainer
fix(app): wrapper for UI refresh trigger with async/await (#2945)
* fix(app): wrapper for UI refresh trigger with async/await * fix(async): $async wrapper now accepts functions with params * fix(async): $async should return a promise to be chained with ES5 .then() style * fix(async): $async with multiple params was not working * refactor(app): wrap all async functions with $async * docs(async): add link to async wrapper documentationpull/2942/head
parent
09cf55a7dc
commit
71b1da8d32
|
@ -3,12 +3,14 @@ import angular from 'angular';
|
|||
class ConfigsController {
|
||||
|
||||
/* @ngInject */
|
||||
constructor($state, ConfigService, Notifications) {
|
||||
constructor($state, ConfigService, Notifications, $async) {
|
||||
this.$state = $state;
|
||||
this.ConfigService = ConfigService;
|
||||
this.Notifications = Notifications;
|
||||
this.$async = $async;
|
||||
|
||||
this.removeAction = this.removeAction.bind(this);
|
||||
this.removeActionAsync = this.removeActionAsync.bind(this);
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
|
@ -20,7 +22,11 @@ class ConfigsController {
|
|||
}
|
||||
}
|
||||
|
||||
async removeAction(selectedItems) {
|
||||
removeAction(selectedItems) {
|
||||
return this.$async(this.removeActionAsync, selectedItems);
|
||||
}
|
||||
|
||||
async removeActionAsync(selectedItems) {
|
||||
let actionCount = selectedItems.length;
|
||||
for (const config of selectedItems) {
|
||||
try {
|
||||
|
|
|
@ -5,7 +5,7 @@ import angular from "angular";
|
|||
|
||||
class CreateConfigController {
|
||||
/* @ngInject */
|
||||
constructor($state, $transition$, Notifications, ConfigService, Authentication, FormValidator, ResourceControlService) {
|
||||
constructor($async, $state, $transition$, Notifications, ConfigService, Authentication, FormValidator, ResourceControlService) {
|
||||
this.$state = $state;
|
||||
this.$transition$ = $transition$;
|
||||
this.Notifications = Notifications;
|
||||
|
@ -13,6 +13,7 @@ class CreateConfigController {
|
|||
this.Authentication = Authentication;
|
||||
this.FormValidator = FormValidator;
|
||||
this.ResourceControlService = ResourceControlService;
|
||||
this.$async = $async;
|
||||
|
||||
this.formValues = {
|
||||
Name: "",
|
||||
|
@ -26,6 +27,30 @@ class CreateConfigController {
|
|||
};
|
||||
|
||||
this.editorUpdate = this.editorUpdate.bind(this);
|
||||
this.createAsync = this.createAsync.bind(this);
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
if (!this.$transition$.params().id) {
|
||||
this.formValues.displayCodeEditor = true;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let data = await this.ConfigService.config(this.$transition$.params().id);
|
||||
this.formValues.Name = data.Name + "_copy";
|
||||
this.formValues.Data = data.Data;
|
||||
let labels = _.keys(data.Labels);
|
||||
for (let i = 0; i < labels.length; i++) {
|
||||
let labelName = labels[i];
|
||||
let labelValue = data.Labels[labelName];
|
||||
this.formValues.Labels.push({ name: labelName, value: labelValue });
|
||||
}
|
||||
this.formValues.displayCodeEditor = true;
|
||||
} catch (err) {
|
||||
this.formValues.displayCodeEditor = true;
|
||||
this.Notifications.error("Failure", err, "Unable to clone config");
|
||||
}
|
||||
}
|
||||
|
||||
addLabel() {
|
||||
|
@ -74,7 +99,11 @@ class CreateConfigController {
|
|||
return true;
|
||||
}
|
||||
|
||||
async create() {
|
||||
create() {
|
||||
return this.$async(this.createAsync);
|
||||
}
|
||||
|
||||
async createAsync() {
|
||||
let accessControlData = this.formValues.AccessControlData;
|
||||
let userDetails = this.Authentication.getUserDetails();
|
||||
let isAdmin = this.Authentication.isAdmin();
|
||||
|
@ -111,29 +140,6 @@ class CreateConfigController {
|
|||
editorUpdate(cm) {
|
||||
this.formValues.ConfigContent = cm.getValue();
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
if (!this.$transition$.params().id) {
|
||||
this.formValues.displayCodeEditor = true;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let data = await this.ConfigService.config(this.$transition$.params().id);
|
||||
this.formValues.Name = data.Name + "_copy";
|
||||
this.formValues.Data = data.Data;
|
||||
let labels = _.keys(data.Labels);
|
||||
for (let i = 0; i < labels.length; i++) {
|
||||
let labelName = labels[i];
|
||||
let labelValue = data.Labels[labelName];
|
||||
this.formValues.Labels.push({ name: labelName, value: labelValue });
|
||||
}
|
||||
this.formValues.displayCodeEditor = true;
|
||||
} catch (err) {
|
||||
this.formValues.displayCodeEditor = true;
|
||||
this.Notifications.error("Failure", err, "Unable to clone config");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default CreateConfigController;
|
||||
|
|
|
@ -1,33 +1,37 @@
|
|||
angular.module('portainer.extensions.rbac').directive('authorization', ['Authentication', 'ExtensionService',
|
||||
function(Authentication, ExtensionService) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: async function(scope, elem, attrs) {
|
||||
elem.hide();
|
||||
try {
|
||||
const rbacEnabled = await ExtensionService.extensionEnabled(ExtensionService.EXTENSIONS.RBAC);
|
||||
if (!rbacEnabled) {
|
||||
elem.show();
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
angular.module('portainer.extensions.rbac').directive('authorization', ['Authentication', 'ExtensionService', '$async',
|
||||
function(Authentication, ExtensionService, $async) {
|
||||
|
||||
async function linkAsync(scope, elem, attrs) {
|
||||
elem.hide();
|
||||
try {
|
||||
const rbacEnabled = await ExtensionService.extensionEnabled(ExtensionService.EXTENSIONS.RBAC);
|
||||
if (!rbacEnabled) {
|
||||
elem.show();
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
elem.show();
|
||||
return;
|
||||
}
|
||||
var authorizations = attrs.authorization.split(",");
|
||||
for (var i = 0; i < authorizations.length; i++) {
|
||||
authorizations[i] = authorizations[i].trim();
|
||||
}
|
||||
|
||||
var authorizations = attrs.authorization.split(",");
|
||||
for (var i = 0; i < authorizations.length; i++) {
|
||||
authorizations[i] = authorizations[i].trim();
|
||||
}
|
||||
var hasAuthorizations = Authentication.hasAuthorizations(authorizations);
|
||||
|
||||
var hasAuthorizations = Authentication.hasAuthorizations(authorizations);
|
||||
if (hasAuthorizations) {
|
||||
elem.show();
|
||||
} else if (!hasAuthorizations && elem[0].tagName === 'A') {
|
||||
elem.show();
|
||||
elem.addClass('portainer-disabled-link');
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAuthorizations) {
|
||||
elem.show();
|
||||
} else if (!hasAuthorizations && elem[0].tagName === 'A') {
|
||||
elem.show();
|
||||
elem.addClass('portainer-disabled-link');
|
||||
}
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
return $async(linkAsync, scope, elem, attrs);
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
|
|
@ -1,27 +1,32 @@
|
|||
angular.module('portainer.extensions.rbac')
|
||||
.directive('disableAuthorization', ['Authentication', 'ExtensionService', function(Authentication, ExtensionService) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: async function (scope, elem, attrs) {
|
||||
try {
|
||||
const rbacEnabled = await ExtensionService.extensionEnabled(ExtensionService.EXTENSIONS.RBAC);
|
||||
if (!rbacEnabled) {
|
||||
elem.show();
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
.directive('disableAuthorization', ['Authentication', 'ExtensionService', '$async', function(Authentication, ExtensionService, $async) {
|
||||
|
||||
async function linkAsync(scope, elem, attrs) {
|
||||
try {
|
||||
const rbacEnabled = await ExtensionService.extensionEnabled(ExtensionService.EXTENSIONS.RBAC);
|
||||
if (!rbacEnabled) {
|
||||
elem.show();
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
elem.show();
|
||||
return;
|
||||
}
|
||||
|
||||
var authorizations = attrs.disableAuthorization.split(",");
|
||||
for (var i = 0; i < authorizations.length; i++) {
|
||||
authorizations[i] = authorizations[i].trim();
|
||||
}
|
||||
var authorizations = attrs.disableAuthorization.split(",");
|
||||
for (var i = 0; i < authorizations.length; i++) {
|
||||
authorizations[i] = authorizations[i].trim();
|
||||
}
|
||||
|
||||
if (!Authentication.hasAuthorizations(authorizations)) {
|
||||
elem.attr('disabled', true);
|
||||
}
|
||||
if (!Authentication.hasAuthorizations(authorizations)) {
|
||||
elem.attr('disabled', true);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function (scope, elem, attrs) {
|
||||
return $async(linkAsync, scope, elem, attrs);
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
|
|
@ -2,7 +2,7 @@ import _ from 'lodash-es';
|
|||
import { ExtensionViewModel } from '../../models/extension';
|
||||
|
||||
angular.module('portainer.app')
|
||||
.factory('ExtensionService', ['$q', 'Extension', 'StateManager', function ExtensionServiceFactory($q, Extension, StateManager) {
|
||||
.factory('ExtensionService', ['$q', 'Extension', 'StateManager', '$async', function ExtensionServiceFactory($q, Extension, StateManager, $async) {
|
||||
'use strict';
|
||||
var service = {};
|
||||
|
||||
|
@ -12,19 +12,27 @@ angular.module('portainer.app')
|
|||
RBAC: 3
|
||||
});
|
||||
|
||||
service.enable = function(license) {
|
||||
service.enable = enable;
|
||||
service.update = update;
|
||||
service.delete = _delete;
|
||||
service.extensions = extensions;
|
||||
service.extension = extension;
|
||||
service.extensionEnabled = extensionEnabled;
|
||||
service.retrieveAndSaveEnabledExtensions = retrieveAndSaveEnabledExtensions;
|
||||
|
||||
function enable(license) {
|
||||
return Extension.create({ license: license }).$promise;
|
||||
};
|
||||
}
|
||||
|
||||
service.update = function(id, version) {
|
||||
function update(id, version) {
|
||||
return Extension.update({ id: id, version: version }).$promise;
|
||||
};
|
||||
}
|
||||
|
||||
service.delete = function(id) {
|
||||
function _delete(id) {
|
||||
return Extension.delete({ id: id }).$promise;
|
||||
};
|
||||
}
|
||||
|
||||
service.extensions = function(store) {
|
||||
function extensions(store) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
Extension.query({ store: store }).$promise
|
||||
|
@ -39,9 +47,9 @@ angular.module('portainer.app')
|
|||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
}
|
||||
|
||||
service.extension = function(id) {
|
||||
function extension(id) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
Extension.get({ id: id }).$promise
|
||||
|
@ -54,9 +62,13 @@ angular.module('portainer.app')
|
|||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
}
|
||||
|
||||
service.extensionEnabled = async function(extensionId) {
|
||||
function extensionEnabled(extensionId) {
|
||||
return $async(extensionsEnabledAsync, extensionId)
|
||||
}
|
||||
|
||||
async function extensionsEnabledAsync(extensionId) {
|
||||
if (extensionId === service.EXTENSIONS.RBAC) {
|
||||
return StateManager.getExtension(extensionId) ? true : false;
|
||||
} else {
|
||||
|
@ -64,13 +76,17 @@ angular.module('portainer.app')
|
|||
const extension = _.find(extensions, (ext) => ext.Id === extensionId);
|
||||
return extension ? extension.Enabled : false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
service.retrieveAndSaveEnabledExtensions = async function() {
|
||||
function retrieveAndSaveEnabledExtensions() {
|
||||
return $async(retrieveAndSaveEnabledExtensionsAsync)
|
||||
}
|
||||
|
||||
async function retrieveAndSaveEnabledExtensionsAsync() {
|
||||
const extensions = await service.extensions(false);
|
||||
_.forEach(extensions, (ext) => delete ext.License);
|
||||
StateManager.saveExtensions(extensions);
|
||||
};
|
||||
}
|
||||
|
||||
return service;
|
||||
}]);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Look a the following PR for how to use the wrapper
|
||||
* and documentation about it
|
||||
* https://github.com/portainer/portainer/pull/2945
|
||||
*/
|
||||
|
||||
angular.module('portainer').factory('$async', ['$q',
|
||||
function($q) {
|
||||
return function(asyncFunc, ...args) {
|
||||
const def = $q.defer();
|
||||
const wrapper = function(params) {
|
||||
const deferred = $q.defer();
|
||||
asyncFunc(...params)
|
||||
.then(deferred.resolve)
|
||||
.catch(deferred.reject);
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
wrapper(args).then(def.resolve).catch(def.reject)
|
||||
return def.promise;
|
||||
};
|
||||
}
|
||||
]);
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('AuthenticationController', ['$q', '$scope', '$state', '$stateParams', '$sanitize', 'Authentication', 'UserService', 'EndpointService', 'ExtensionService', 'StateManager', 'Notifications', 'SettingsService', 'URLHelper',
|
||||
function($q, $scope, $state, $stateParams, $sanitize, Authentication, UserService, EndpointService, ExtensionService, StateManager, Notifications, SettingsService, URLHelper) {
|
||||
.controller('AuthenticationController', ['$async', '$q', '$scope', '$state', '$stateParams', '$sanitize', 'Authentication', 'UserService', 'EndpointService', 'ExtensionService', 'StateManager', 'Notifications', 'SettingsService', 'URLHelper',
|
||||
function($async, $q, $scope, $state, $stateParams, $sanitize, Authentication, UserService, EndpointService, ExtensionService, StateManager, Notifications, SettingsService, URLHelper) {
|
||||
$scope.logo = StateManager.getState().application.logo;
|
||||
|
||||
$scope.formValues = {
|
||||
|
@ -14,7 +14,11 @@ function($q, $scope, $state, $stateParams, $sanitize, Authentication, UserServic
|
|||
OAuthProvider: ''
|
||||
};
|
||||
|
||||
async function retrieveAndSaveEnabledExtensions() {
|
||||
function retrieveAndSaveEnabledExtensions() {
|
||||
return $async(retrieveAndSaveEnabledExtensionsAsync);
|
||||
}
|
||||
|
||||
async function retrieveAndSaveEnabledExtensionsAsync() {
|
||||
try {
|
||||
await ExtensionService.retrieveAndSaveEnabledExtensions();
|
||||
} catch (err) {
|
||||
|
|
|
@ -2,13 +2,16 @@ import angular from "angular";
|
|||
|
||||
class EndpointAccessController {
|
||||
/* @ngInject */
|
||||
constructor($state, $transition$, Notifications, EndpointService, GroupService) {
|
||||
constructor($state, $transition$, Notifications, EndpointService, GroupService, $async) {
|
||||
this.$state = $state;
|
||||
this.$transition$ = $transition$;
|
||||
this.Notifications = Notifications;
|
||||
this.EndpointService = EndpointService;
|
||||
this.GroupService = GroupService;
|
||||
this.$async = $async;
|
||||
|
||||
this.updateAccess = this.updateAccess.bind(this);
|
||||
this.updateAccessAsync = this.updateAccessAsync.bind(this);
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
|
@ -23,7 +26,11 @@ class EndpointAccessController {
|
|||
}
|
||||
}
|
||||
|
||||
async updateAccess() {
|
||||
updateAccess() {
|
||||
return this.$async(this.updateAccessAsync);
|
||||
}
|
||||
|
||||
async updateAccessAsync() {
|
||||
try {
|
||||
this.state.actionInProgress = true;
|
||||
await this.EndpointService.updateEndpoint(this.$transition$.params().id, this.endpoint);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('InitAdminController', ['$scope', '$state', 'Notifications', 'Authentication', 'StateManager', 'UserService', 'EndpointService', 'ExtensionService',
|
||||
function ($scope, $state, Notifications, Authentication, StateManager, UserService, EndpointService, ExtensionService) {
|
||||
.controller('InitAdminController', ['$async', '$scope', '$state', 'Notifications', 'Authentication', 'StateManager', 'UserService', 'EndpointService', 'ExtensionService',
|
||||
function ($async, $scope, $state, Notifications, Authentication, StateManager, UserService, EndpointService, ExtensionService) {
|
||||
|
||||
$scope.logo = StateManager.getState().application.logo;
|
||||
|
||||
|
@ -14,7 +14,11 @@ function ($scope, $state, Notifications, Authentication, StateManager, UserServi
|
|||
actionInProgress: false
|
||||
};
|
||||
|
||||
async function retrieveAndSaveEnabledExtensions() {
|
||||
function retrieveAndSaveEnabledExtensions() {
|
||||
return $async(retrieveAndSaveEnabledExtensionsAsync)
|
||||
}
|
||||
|
||||
async function retrieveAndSaveEnabledExtensionsAsync() {
|
||||
try {
|
||||
await ExtensionService.retrieveAndSaveEnabledExtensions();
|
||||
} catch (err) {
|
||||
|
|
Loading…
Reference in New Issue