Commit 22332d94 authored by Pedro Eduardo Trujillo's avatar Pedro Eduardo Trujillo
Browse files

Amplía diseño de mapa y simplifica su uso

Integra 2 nuevas extensiones del diseño, una para añadir un listado
configurable y otra para añadir una capa de mapa configurable,
comunicada con eventos procedentes del listado para reaccionar. Su
lógica se ha extraído de los "main" de antiguos diseños, optimizando y
simplificando su código.

Retoca extensión de añadir atlas para que conviva con la de añadir
listado, ya que ambas necesitan de un contenedor de pestañas, pero
ninguna puede depender de que la otra esté presente.

Implementa método genérico de diseño para mezclar valores de atributos
de manera simplificada, ahorrando asignaciones redundantes que ensucian
la lógica. Además, se ha dado la vuelta al orden de mezcla, ya que era
incorrecto (lo que venga nuevo debe pisar a lo que había).
parent 0cdc2094
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -25,6 +25,16 @@ define([
			return declare(baseDefinitionArray);
		},

		_mergeComponentAttribute: function(/*String*/ attrName, /*Object*/ objToMerge, /*Object?*/ mergeOpts) {
			// summary:
			//   Recibe un nombre de atributo, un objeto para mezclar con el valor actual del atributo y un objeto
			//   opcional para configurar parámetros de la mezcla.
			//   Asigna al atributo indicado el valor resultante entre la mezcla de su valor actual con el valor
			//   recibido por parámetro, siguiendo las opciones de mezcla establecidas.

			this[attrName] = this._merge([this[attrName] || {}, objToMerge], mergeOpts);
		},

		_initialize: function() {
			// Método perteneciente al ciclo de vida de un componente.

+19 −13
Original line number Diff line number Diff line
@@ -25,17 +25,17 @@ define([

			const parentChannel = this.getChannel();

			this.tabsDisplayerConfig = this._merge([{
			this._mergeComponentAttribute('tabsDisplayerConfig', {
				parentChannel
			}, this.tabsDisplayerConfig || {}]);
			});

			this.atlasConfig = this._merge([{
			this._mergeComponentAttribute('atlasConfig', {
				parentChannel
			}, this.atlasConfig || {}]);
			});

			this.queryOnMapConfig = this._merge([{
			this._mergeComponentAttribute('queryOnMapConfig', {
				parentChannel
			}, this.queryOnMapConfig || {}]);
			});
		},

		_createDesignControllerComponents: function() {
@@ -45,15 +45,21 @@ define([
			const mapInstance = inheritedComponents.map,
				getMapChannel = lang.hitch(mapInstance, mapInstance.getChannel);

			const tabsDisplayer = this._createDesignTabDisplayerComponent(),
				tabsDisplayerChannel = tabsDisplayer.getChannel(),
			let tabsDisplayer = inheritedComponents.tabsDisplayer;

			if (!tabsDisplayer) {
				tabsDisplayer = this._createDesignTabDisplayerComponent();
				lang.mixin(inheritedComponents, {tabsDisplayer});
			}

			const tabsDisplayerChannel = tabsDisplayer.getChannel(),
				addTabChannel = tabsDisplayer.getChannel('ADD_TAB');

			const atlas = this._createDesignAtlasComponent(getMapChannel, addTabChannel);

			const queryOnMap = this._createDesignQueryOnMapComponent(getMapChannel, tabsDisplayerChannel);

			return lang.mixin(inheritedComponents, {tabsDisplayer, atlas, queryOnMap});
			return lang.mixin(inheritedComponents, {atlas, queryOnMap});
		},

		_createDesignTabDisplayerComponent: function() {
@@ -63,18 +69,18 @@ define([

		_createDesignAtlasComponent: function(getMapChannel, addTabChannel) {

			this.atlasConfig = this._merge([{
			this._mergeComponentAttribute('atlasConfig', {
				getMapChannel, addTabChannel
			}, this.atlasConfig || {}]);
			});

			return new Atlas(this.atlasConfig);
		},

		_createDesignQueryOnMapComponent: function(getMapChannel, tabsDisplayerChannel) {

			this.queryOnMapConfig = this._merge([{
			this._mergeComponentAttribute('queryOnMapConfig', {
				getMapChannel, tabsDisplayerChannel
			}, this.queryOnMapConfig || {}]);
			});

			return new QueryOnMap(this.queryOnMapConfig);
		},
+197 −0
Original line number Diff line number Diff line
define([
	'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'src/component/browser/_ButtonsInRow'
	, 'src/component/browser/_DragAndDrop'
	, 'src/component/browser/_Framework'
	, 'src/component/browser/_GeoJsonParser'
	, 'src/component/browser/_HierarchicalSelect'
	, 'src/component/browser/_Select'
	, 'src/component/browser/bars/Total'
	, 'src/component/browser/ListImpl'
	, 'src/component/layout/genericDisplayer/GenericWithTopbarDisplayerImpl'
	, 'src/component/layout/TabsDisplayer'
	, 'src/component/search/TextImpl'
	, 'templates/DefaultList'
], function (
	declare
	, lang
	, _ButtonsInRow
	, _DragAndDrop
	, _Framework
	, _GeoJsonParser
	, _HierarchicalSelect
	, _Select
	, Total
	, ListImpl
	, GenericWithTopbarDisplayerImpl
	, TabsDisplayer
	, TextImpl
	, TemplateDefaultList
) {

	const browserComponentExtensionDefinitions = {
		dragAndDrop: _DragAndDrop,
		hierarchicalSelect: _HierarchicalSelect,
		select: _Select
	};

	return declare(null, {
		// summary:
		//   Lógica de diseño para añadir un componente Browser, junto con otros para mostrarlo y filtrar contenido.
		//   Debe asociarse como mixin a un componente al instanciarlo, junto con la parte de controlador y alguna
		//   maquetación de este diseño.

		constructor: function(args) {

			const defaultConfig = {
				enabledBrowserExtensions: {
					dragAndDrop: false,
					hierarchicalSelect: false,
					select: false
				}
			};

			lang.mixin(this, this._merge([this, defaultConfig, args]));
		},

		_setConfigurations: function() {

			this.inherited(arguments);

			const parentChannel = this.getChannel(),
				target = this._getTarget?.();

			this._mergeComponentAttribute('tabsDisplayerConfig', {
				parentChannel
			});

			this._mergeComponentAttribute('searchConfig', {
				parentChannel,
				target,
				itemLabel: null
			});

			this._mergeComponentAttribute('browserConfig', {
				parentChannel,
				selectorChannel: parentChannel,
				target,
				template: TemplateDefaultList,
				rowConfig: {
					buttonsConfig: {
						listButton: [{
							icon: "fa-map-marker",
							title: 'mapCentering',
							btnId: "mapCentering",
							returnItem: true
						}]
					}
				},
				bars: [{
					instance: Total
				}]
			}, {
				arrayMergingStrategy: 'concatenate'
			});

			this._BrowserComponentDefinition = this._prepareComponentDefinition(
				[ListImpl, _Framework, _ButtonsInRow, _GeoJsonParser], this.enabledBrowserExtensions,
				browserComponentExtensionDefinitions);
		},

		_createDesignControllerComponents: function() {

			let inheritedComponents = this.inherited(arguments);

			let tabsDisplayer = inheritedComponents.tabsDisplayer;

			if (!tabsDisplayer) {
				tabsDisplayer = this._createDesignTabDisplayerComponent();
				lang.mixin(inheritedComponents, {tabsDisplayer});
			}

			const browser = this._createDesignBrowserComponent(),
				browserWrapper = this._createDesignBrowserWrapperComponent(browser),
				search = this._createDesignSearchComponent(browserWrapper);

			return lang.mixin(inheritedComponents, {browserWrapper, browser, search});
		},

		_createDesignTabDisplayerComponent: function() {

			return new TabsDisplayer(this.tabsDisplayerConfig);
		},

		_createDesignBrowserComponent: function() {

			return new this._BrowserComponentDefinition(this.browserConfig);
		},

		_createDesignBrowserWrapperComponent: function(browserInstance) {

			return new GenericWithTopbarDisplayerImpl({
				parentChannel: this.getChannel(),
				content: browserInstance,
				title: this.browserConfig.title || this.i18n.geographicData
			});
		},

		_createDesignSearchComponent: function() {

			return new TextImpl(this.searchConfig);
		},

		_populateDesignLayoutNodes: function() {

			this.inherited(arguments);

			const browserWrapperInstance = this.getComponentInstance('browserWrapper'),
				browserWrapperChannel = browserWrapperInstance.getChannel();

			const searchInstance = this.getComponentInstance('search');

			this._publish(browserWrapperInstance.getChannel('ADD_TOPBAR_CONTENT'), {
				content: searchInstance
			});

			const tabsDisplayerInstance = this.getComponentInstance('tabsDisplayer'),
				additionalContentNode = this.getLayoutNode('additionalContent');

			this._publish(tabsDisplayerInstance.getChannel('ADD_TAB'), {
				title: this.browserConfig.title || this.i18n.geographicData,
				iconClass: 'fa fa-table',
				channel: browserWrapperChannel,
				prepend: true
			});

			this._publish(tabsDisplayerInstance.getChannel('SHOW_TAB'), {
				channel: browserWrapperChannel
			});

			this._publish(tabsDisplayerInstance.getChannel('SHOW'), {
				node: additionalContentNode
			});
		},

		_defineSubscriptions: function () {

			this.inherited(arguments);

			const browserInstance = this.getComponentInstance('browser');

			this.subscriptionsConfig.push({
				channel : browserInstance.getChannel('BUTTON_EVENT'),
				callback: '_subDesignBrowserComponentButtonEvent'
			});
		},

		_subDesignBrowserComponentButtonEvent: function(evt) {

			var publicCallback = `${evt.btnId}Callback`,
				privateCallback = `_${evt.btnId}Callback`;

			this[publicCallback]?.(evt);
			this[privateCallback]?.(evt);
		}
	});
});
+153 −0
Original line number Diff line number Diff line
define([
	'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'src/component/gateway/MapCenteringGatewayImpl'
	, 'src/component/map/layer/_RadiusOnClick'
	, 'src/component/map/layer/GeoJsonLayerImpl'
	, 'src/component/map/layer/PruneClusterLayerImpl'
], function (
	declare
	, lang
	, MapCenteringGatewayImpl
	, _RadiusOnClick
	, GeoJsonLayerImpl
	, PruneClusterLayerImpl
) {

	const mapLayerComponentDefinitions = {
		geojson: GeoJsonLayerImpl,
		cluster: PruneClusterLayerImpl
	};

	const mapLayerComponentExtensionDefinitions = {
		radius: _RadiusOnClick
	};

	return declare(null, {
		// summary:
		//   Lógica de diseño para añadir un componente MapLayer, junto con otros para comunicarlo y mostrar información
		//   en el mapa.
		//   Debe asociarse como mixin a un componente al instanciarlo, junto con la parte de controlador y alguna
		//   maquetación de este diseño.

		constructor: function(args) {

			const defaultConfig = {
				mapLayerDefinition: 'cluster',
				enabledMapLayerExtensions: {
					radius: false
				},
				mapLayerPopupTemplate: null
			};

			lang.mixin(this, this._merge([this, defaultConfig, args]));
		},

		_setConfigurations: function() {

			this.inherited(arguments);

			const parentChannel = this.getChannel();

			this._mergeComponentAttribute('mapLayerConfig', {
				parentChannel,
				selectorChannel: parentChannel,
				idProperty: 'uuid',
				categoryStyle: 'bubbles',
				simpleSelection: true,
				getMarkerCategory: lang.hitch(this, this._getMarkerCategory),
				getPopupContent: lang.hitch(this, this._getPopupContent)
			});

			this._mergeComponentAttribute('mapCenteringConfig', {
				parentChannel
			});

			const mapLayerComponentBaseDefinition = mapLayerComponentDefinitions[this.mapLayerDefinition];

			this._MapLayerComponentDefinition = this._prepareComponentDefinition([mapLayerComponentBaseDefinition],
				this.enabledMapLayerExtensions, mapLayerComponentExtensionDefinitions);
		},

		_createDesignControllerComponents: function() {

			let inheritedComponents = this.inherited(arguments);

			const mapLayer = this._createDesignMapLayerComponent(inheritedComponents.map),
				mapCentering = this._createDesignMapCenteringComponent();

			return lang.mixin(inheritedComponents, {mapLayer, mapCentering});
		},

		_createDesignMapLayerComponent: function(mapInstance) {

			const mapChannel = mapInstance.getChannel();

			this._mergeComponentAttribute('mapLayerConfig', {
				mapChannel
			});

			return new this._MapLayerComponentDefinition(this.mapLayerConfig);
		},

		_createDesignMapCenteringComponent: function() {

			return new MapCenteringGatewayImpl(this.mapCenteringConfig);
		},

		_populateDesignLayoutNodes: function() {

			this.inherited(arguments);

			this._addMapLayerToMap();
			this._linkBrowserActionWithMapLayer();
		},

		_addMapLayerToMap: function() {

			const mapInstance = this.getComponentInstance('map'),
				mapLayerInstance = this.getComponentInstance('mapLayer');

			this._publish(mapInstance.getChannel('ADD_LAYER'), mapLayerInstance);
		},

		_linkBrowserActionWithMapLayer: function() {

			const mapCenteringInstance = this.getComponentInstance('mapCentering');

			const mapLayerInstance = this.getComponentInstance('mapLayer');

			const browserInstance = this.getComponentInstance('browser'),
				browserButtonEventActionChannel = browserInstance?.getChannel('BUTTON_EVENT');

			if (!browserButtonEventActionChannel) {
				return;
			}

			this._publish(mapCenteringInstance.getChannel('ADD_CHANNELS_DEFINITION'), {
				channelsDefinition: [{
					input: browserButtonEventActionChannel,
					output: mapLayerInstance.getChannel('SET_CENTER'),
					subMethod: 'setCenter'
				},{
					input: browserButtonEventActionChannel,
					output: mapLayerInstance.getChannel('ANIMATE_MARKER'),
					subMethod: 'animateMarker'
				}]
			});
		},

		_getMarkerCategory: function(feature) {

			return feature.properties?.infrastructureType?.id - 1 || 0;
		},

		_getPopupContent: function(data) {

			return this.mapLayerPopupTemplate?.({
				i18n: this.i18n,
				feature: data.feature
			});
		}
	});
});
+2 −2
Original line number Diff line number Diff line
@@ -44,9 +44,9 @@ define([

			this.inherited(arguments);

			this.mapConfig = this._merge([{
			this._mergeComponentAttribute('mapConfig', {
				parentChannel: this.getChannel()
			}, this.mapConfig || {}]);
			});

			this._MapComponentDefinition = this._prepareComponentDefinition(
				[LeafletImpl], this.enabledMapExtensions, mapComponentExtensionDefinitions);