Commit ab97c7e3 authored by Pedro Eduardo Trujillo's avatar Pedro Eduardo Trujillo
Browse files

Mejora getProps, refactoriza ExternalConfig

Implementa obtención de propiedades asíncrona para los componentes
(usando el canal getProps), manteniendo retrocompatibilidad con el
funcionamiento síncrono anterior.

Convierte el canal hacia el componente global ExternalConfig en
compartido por cualquier componente.

Refactoriza lógica de ExternalConfig para aprovechar los canales
getProps/gotProps a la hora de recibir petición de config externa y
devolverla a los otros componentes, incluyendo su obtención asíncrona en
caso de que aún no esté resuelta.
parent 30fbb324
Loading
Loading
Loading
Loading
+57 −60
Original line number Diff line number Diff line
define([
	'src/redmicConfig'
	, 'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'dojo/Deferred'
	, 'src/component/base/_Module'
	, 'src/component/base/_Store'
	, 'src/util/Credentials'
], function(
	redmicConfig
	, declare
	, lang
	, Deferred
	, _Module
	, _Store
	, Credentials
@@ -18,53 +18,47 @@ define([
		//	Summary:
		//		Módulo para manejar las variables de configuración externas, procedentes del servidor.

		constructor: function(args) {
		postMixInProperties: function() {

			this.config = {
			const defaultConfig = {
				ownChannel: 'externalConfig',
				events: {
					GOT_CONFIG: 'gotConfig',
					REMOVE: 'remove',
					REQUEST_FAILED: 'requestFailed'
				},
				actions: {
					GET_CONFIG: 'getConfig',
					GOT_CONFIG: 'gotConfig',
					REMOVED: 'removed',
					REQUEST_FAILED: 'requestFailed'
				},

				target: redmicConfig.services.getExternalConfig,
				externalConfigExpirationMs: 3600000,
				_gettingExternalConfig: false
				localConfigExpirationMs: 3600000,
				remoteForceRefresh: true
			};

			lang.mixin(this, this.config, args);
			this._mergeOwnAttributes(defaultConfig);

			this.inherited(arguments);
		},

		_initialize: function() {

			if (!Credentials.get('externalConfig')) {
				this._setEmptyExternalConfig();
				this._deleteExternalConfig();
			}

			this._listenLocalStorage();
		},

		_defineSubscriptions: function() {
		_listenLocalStorage: function() {

			this.subscriptionsConfig.push({
				channel : this.getChannel('GET_CONFIG'),
				callback: '_subGetConfig'
			});
			Credentials.on('changed:externalConfig', evt => this._onExternalConfigChanged(evt));
			Credentials.on('removed:externalConfig', () => this._onExternalConfigRemoved());
		},

		_definePublications: function() {

			this.publicationsConfig.push({
				event: 'GOT_CONFIG',
				channel: this.getChannel('GOT_CONFIG')
			},{
				event: 'REMOVE',
				channel: this.getChannel('REMOVED')
			},{
@@ -73,66 +67,63 @@ define([
			});
		},

		_listenLocalStorage: function() {

			Credentials.on('changed:externalConfig', lang.hitch(this, this._onExternalConfigChanged));
			Credentials.on('removed:externalConfig', lang.hitch(this, this._onExternalConfigRemoved));
		},

		postCreate: function() {

			this._getExternalConfig();
		},

		_subGetConfig: function(req) {
			this.inherited(arguments);

			this._getExternalConfig(req);
			this._getExternalConfig();
		},

		_getExternalConfig: function(req) {
		_getExternalConfig: function() {

			var currentExternalConfig = Credentials.get('externalConfig'),
				currentExternalConfigTimestamp = Credentials.get('externalConfigTimestamp'),
				forceLocalRefresh = req && req.forceLocalRefresh;
			const currentExternalConfig = Credentials.get('externalConfig'),
				currentExternalConfigTimestamp = Credentials.get('externalConfigTimestamp');

			if (currentExternalConfig && currentExternalConfigTimestamp) {
				var configNotExpired = currentExternalConfigTimestamp >= Date.now() - this.externalConfigExpirationMs;
				if (configNotExpired && !forceLocalRefresh) {
					this._emitGotConfig(currentExternalConfig);
				const configNotExpired = currentExternalConfigTimestamp >= Date.now() - this.localConfigExpirationMs;
				if (configNotExpired) {
					this._setExternalConfig(currentExternalConfig);
					return;
				}
			}

			if (this._gettingExternalConfig) {
				return;
			}
			this._requestExternalConfig();
		},

			this._gettingExternalConfig = true;
		_requestExternalConfig: function() {

			var forceRemoteRefresh = req && req.forceRemoteRefresh,
				query = {};
			this._externalConfigDfd = new Deferred();

			if (forceRemoteRefresh) {
				query.forceRefresh = true;
			}
			const forceRefresh = this.remoteForceRefresh,
				query = { forceRefresh };

			this._emitEvt('GET', {
				target: this.target,
				query: query,
				params: { query },
				requesterId: this.getOwnChannel()
			});
		},

		_emitGotConfig: function(data) {
		_externalConfigGetProp: function(dfd, _propName) {

			this._emitEvt('GOT_CONFIG', {
				config: data
			});
			if (this.externalConfig) {
				dfd.resolve(this.externalConfig);
				return;
			}

			if (!this._externalConfigDfd) {
				this._requestExternalConfig();
			}

			this._externalConfigDfd.then(
				config => dfd.resolve(config),
				() => dfd.resolve()
			);
		},

		_onExternalConfigChanged: function(evt) {

			var value = evt.value;
			const value = evt.value;

			if (!value) {
				this._onExternalConfigRemoved();
@@ -144,36 +135,42 @@ define([
			this._emitEvt('REMOVE');
		},

		_setEmptyExternalConfig: function() {
		_setExternalConfig: function(config) {

			this.externalConfig = config;
		},

		_deleteExternalConfig: function() {

			Credentials.remove('externalConfig');
			Credentials.remove('externalConfigTimestamp');

			delete this.externalConfig;
		},

		_itemAvailable: function(res) {

			this._gettingExternalConfig = false;

			var data = res.data;
			const data = res.data;

			if (!data) {
				this._onExternalConfigRemoved();
				this._externalConfigDfd.reject();
				return;
			}

			var timestamp = Date.now();
			const timestamp = Date.now();

			Credentials.set('externalConfig', data);
			Credentials.set('externalConfigTimestamp', timestamp);

			this._emitGotConfig(data);
			this._setExternalConfig(data);
			this._externalConfigDfd.resolve(data);
		},

		_errorAvailable: function(err) {

			this._gettingExternalConfig = false;

			this._emitEvt('REQUEST_FAILED', err);
			this._externalConfigDfd.reject(err);
		}
	});
});
+16 −20
Original line number Diff line number Diff line
@@ -24,14 +24,8 @@ define([

				externalConfigActions: {
					GOT_EXTERNAL_CONFIG: 'gotExternalConfig',
					GET_CONFIG: 'getConfig',
					GOT_CONFIG: 'gotConfig',
					REQUEST_FAILED: 'requestFailed'
				},

				externalConfigChannel: this._buildChannel(this.rootChannel, this.globalOwnChannels.EXTERNAL_CONFIG),

				_requestedExternalConfigProperty: null
				}
			};

			lang.mixin(this, this.config, args);
@@ -58,9 +52,6 @@ define([
		_defineExternalConfigSubscriptions: function() {

			this.subscriptionsConfig.push({
				channel: this._buildChannel(this.externalConfigChannel, this.actions.GOT_CONFIG),
				callback: '_subGotExternalConfig'
			},{
				channel: this._buildChannel(this.externalConfigChannel, this.actions.REQUEST_FAILED),
				callback: '_subExternalConfigRequestFailed'
			});
@@ -71,9 +62,6 @@ define([
		_defineExternalConfigPublications: function() {

			this.publicationsConfig.push({
				event: 'GET_EXTERNAL_CONFIG',
				channel: this._buildChannel(this.externalConfigChannel, this.actions.GET_CONFIG)
			},{
				event: 'GOT_EXTERNAL_CONFIG',
				channel: this.getChannel('GOT_EXTERNAL_CONFIG')
			});
@@ -88,18 +76,26 @@ define([

		_onGetExternalConfigEvt: function(evt) {

			this._requestedExternalConfigProperty = evt.propertyName;
			const requestedConfigPropName = evt.propertyName,
				propName = 'externalConfig';

			const gotPropsChannel = this._buildChannel(this.externalConfigChannel, 'GOT_PROPS');
			this._once(gotPropsChannel, res => {
				this._onceGotPropsFromExternalConfig(res[propName], requestedConfigPropName)
			});

			const getPropsChannel = this._buildChannel(this.externalConfigChannel, 'GET_PROPS');
			this._publish(getPropsChannel, { [propName]: true });
		},

		_subGotExternalConfig: function(res) {
		_onceGotPropsFromExternalConfig: function(config, configProp) {

			var config = res.config,
				configProp = this._requestedExternalConfigProperty,
				configToEmit;
			let configToEmit;

			if (configProp) {
				configToEmit = {};
				configToEmit[configProp] = Utilities.getDeepProp(config, configProp);
				configToEmit = {
					[configProp]: Utilities.getDeepProp(config, configProp)
				};
			} else {
				configToEmit = config;
			}
+31 −8
Original line number Diff line number Diff line
@@ -118,6 +118,8 @@ define([
		//		Nombre del canal por donde se van a publicar las notificaciones.
		//	authChannel: String
		//		Nombre del canal por donde se gestiona la sesión del usuario autenticado.
		//	externalConfigChannel: String
		//		Nombre del canal por donde se comunican las configuraciones externas.
		//	i18n: Object
		//		Traducciones globales

@@ -216,6 +218,7 @@ define([
			this.alertChannel = this._buildChannel(this.rootChannel, this.globalOwnChannels.ALERT);
			this.communicationChannel = this._buildChannel(this.rootChannel, this.globalOwnChannels.COMMUNICATION);
			this.authChannel = this._buildChannel(this.rootChannel, this.globalOwnChannels.AUTH);
			this.externalConfigChannel = this._buildChannel(this.rootChannel, this.globalOwnChannels.EXTERNAL_CONFIG),

			this.outerAppChannel = this._buildChannel(this.rootChannel, this.outerAppOwnChannel);
			this.innerAppChannel = this._buildChannel(this.rootChannel, this.innerAppOwnChannel);
@@ -899,17 +902,37 @@ define([

		_subGetProps: function(req) {

			var props = {};
			const props = {};

			for (var prop in req) {
				if (this._checkPropIsShareable(prop)) {
					props[prop] = this[prop];
				} else {
			for (let prop in req) {
				props[prop] = this._getProp(prop);
			}

			all(props).then(propValues => this._emitEvt('GOT_PROPS', propValues));
		},

		_getProp: function(/*String*/ propName) {

			const dfd = new Deferred();

			if (!this._checkPropIsShareable(propName)) {
				console.error("Tried to get not gettable property '%s' at module '%s'", prop, this.getChannel());
				dfd.resolve();
				return dfd;
			}

			const getPropCustomMethod = this[`_${propName}GetProp`];
			if (getPropCustomMethod) {
				getPropCustomMethod.call(this, dfd, propName);
				return dfd;
			}

			this._emitEvt("GOT_PROPS", props);
			const propValue = this[propName];
			if (propValue === undefined) {
				console.error(`Tried to get undefined property "${propName}" at module "${this.getChannel()}"`);
			}
			dfd.resolve(propValue);
			return dfd;
		},

		_subChildActionDone: function(res, channelInfo) {