Commit 05e4a477 authored by Pedro Eduardo Trujillo's avatar Pedro Eduardo Trujillo
Browse files

Implementa consultas sobre mapa como módulo

Extrae la funcionalidad existente como extensiones de vistas para
consultar puntos de capas sobre el mapa, pedir la información y listarla
en un popup para implementar un nuevo módulo dedicado.

Aplica mejoras y divide el código original en extensiones del módulo.

Actualiza submódulo de estilos con nueva clase.

Aplica el nuevo módulo a la vista de atlas.
parent d0ad4e07
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
define([
	"app/base/views/extensions/_QueryOnMap"
	, "app/base/views/extensions/_ShowInPopupResultsFromQueryOnMap"
	, "app/designs/mapWithSideContent/Controller"
	"app/designs/mapWithSideContent/Controller"
	, "app/designs/mapWithSideContent/layout/MapAndContent"
	, "app/redmicConfig"
	, "dojo/_base/declare"
	, "dojo/_base/lang"
	, "redmic/modules/atlas/Atlas"
	, "redmic/modules/base/_ShowInPopup"
	, "redmic/modules/mapQuery/QueryOnMap"
], function(
	_QueryOnMap
	, _ShowInPopupResultsFromQueryOnMap
	, Controller
	Controller
	, Layout
	, redmicConfig
	, declare
	, lang
	, Atlas
	, _ShowInPopup
	, QueryOnMap
) {

	return declare([Layout, Controller], {
@@ -47,13 +47,25 @@ define([
				terms: this.terms,
				perms: this.perms
			}, this.atlasConfig || {}]);

			this.queryOnMapConfig = this._merge([{
				parentChannel: this.getChannel(),
				title: 'a',
				width: 5,
				height: "md"
			}, this.queryOnMapConfig || {}]);
		},

		_initialize: function() {

			this.atlasConfig.getMapChannel = lang.hitch(this.map, this.map.getChannel);
			var getMapChannel = lang.hitch(this.map, this.map.getChannel);
			this.atlasConfig.getMapChannel = getMapChannel;
			this.queryOnMapConfig.getMapChannel = getMapChannel;

			this.atlas = new Atlas(this.atlasConfig);

			this.atlas = new declare([Atlas, _QueryOnMap, _ShowInPopupResultsFromQueryOnMap])(this.atlasConfig);
			var QueryOnMapPopup = declare(QueryOnMap).extend(_ShowInPopup);
			this._queryOnMap = new QueryOnMapPopup(this.queryOnMapConfig);
		},

		postCreate: function() {
+174 −0
Original line number Diff line number Diff line
define([
	'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'redmic/modules/base/_Module'
	, './_ContentManagement'
	, './_ResultsBrowser'
], function(
	declare
	, lang
	, _Module
	, _ContentManagement
	, _ResultsBrowser
) {

	return declare([_Module, _ContentManagement, _ResultsBrowser], {
		//	summary:
		//		Módulo para gestionar las consultas sobre el mapa.
		//	description:
		//		Escucha las publicaciones de pulsación sobre el mapa, lanza peticiones de información sobre ese punto
		//		para las capas presentes y recibe los resultados.

		constructor: function(args) {

			this.config = {
				ownChannel: 'queryOnMap',
				events: {
					HIDE_LAYERS_INFO: 'hideLayersInfo',
					ADD_INFO_DATA: 'addInfoData',
					ADD_NEW_TEMPLATES: 'addNewTemplates',
					SHOW_LAYERS_INFO: 'showLayersInfo',
					SET_MAP_QUERYABLE_CURSOR: 'setMapQueryableCursor'
				},
				actions: {
					HIDE_LAYERS_INFO: 'hideLayersInfo',
					ADD_INFO_DATA: 'addInfoData',
					ADD_NEW_TEMPLATES: 'addNewTemplates',
					SHOW_LAYERS_INFO: 'showLayersInfo'
				},

				getMapChannel: null,

				_queryableLayersLoaded: 0,
				_layersWaiting: 0
			};

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

			if (!this.getMapChannel) {
				console.error('Map channel not defined for QueryOnMap "%s"', this.getChannel());
			}
		},

		_defineSubscriptions: function() {

			var options = {
				predicate: lang.hitch(this, this._chkLayerIsQueryable)
			};

			this.subscriptionsConfig.push({
				channel : this.getMapChannel('MAP_CLICKED'),
				callback: '_subMapClickedQueryOnMap'
			},{
				channel: this.getMapChannel('LAYER_ADDED_CONFIRMED'),
				callback: '_subLayerAddedQueryOnMap',
				options: options
			},{
				channel: this.getMapChannel('LAYER_REMOVED_CONFIRMED'),
				callback: '_subLayerRemovedQueryOnMap',
				options: options
			},{
				channel: this.getMapChannel('LAYER_QUERYING'),
				callback: '_subLayerQueryingQueryOnMap'
			},{
				channel: this.getMapChannel('LAYER_INFO'),
				callback: '_subLayerInfoQueryOnMap'
			});
		},

		_definePublications: function() {

			this.publicationsConfig.push({
				event: 'HIDE_LAYERS_INFO',
				channel: this.getChannel('HIDE_LAYERS_INFO')
			},{
				event: 'ADD_INFO_DATA',
				channel: this.getChannel('ADD_INFO_DATA')
			},{
				event: 'ADD_NEW_TEMPLATES',
				channel: this.getChannel('ADD_NEW_TEMPLATES')
			},{
				event: 'SHOW_LAYERS_INFO',
				channel: this.getChannel('SHOW_LAYERS_INFO')
			},{
				event: 'SET_MAP_QUERYABLE_CURSOR',
				channel: this.getMapChannel('SET_QUERYABLE_CURSOR')
			});
		},

		_setOwnCallbacksForEvents: function() {

			this.on([
				this.events.HIDE,
				this.events.ANCESTOR_HIDE
			], lang.hitch(this, this.emit, this.events.HIDE_LAYERS_INFO));
		},

		_chkLayerIsQueryable: function(res) {

			return !!res.queryable;
		},

		_subMapClickedQueryOnMap: function(response) {

			this._emitEvt('HIDE_LAYERS_INFO');

			if (this._queryableLayersLoaded) {
				this._emitEvt('LOADING', {
					global: true
				});
			}
		},

		_subLayerAddedQueryOnMap: function(res) {

			this._queryableLayersLoaded++;

			this._emitEvt('SET_MAP_QUERYABLE_CURSOR', { enable: true });

			this._emitEvt('ADD_NEW_TEMPLATES', this._getLayerTemplatesDefinition(res.layerId));
		},

		_subLayerRemovedQueryOnMap: function(res) {

			this._queryableLayersLoaded--;

			if (!this._queryableLayersLoaded) {
				this._emitEvt('SET_MAP_QUERYABLE_CURSOR', { enable: false });
			}
		},

		_subLayerQueryingQueryOnMap: function(res) {

			this._layersWaiting++;

			clearTimeout(this._showInfoTimeoutHandler);
		},

		_subLayerInfoQueryOnMap: function(res) {

			this._layersWaiting--;

			this._processLayerInfo(res);

			if (!this._layersWaiting) {
				this._showInfoTimeoutHandler = setTimeout(lang.hitch(this, this._showWhenNoLayersWaiting), 0);
			}
		},

		_showWhenNoLayersWaiting: function() {

			this._emitEvt('LOADED');

			if (this._hadValidInfo) {
				this._emitEvt('SHOW_LAYERS_INFO');
			} else {
				this._emitEvt('COMMUNICATION', {
					description: this.i18n.noLayerInfo
				});
			}

			this._hadValidInfo = false;
		}
	});
});
+195 −0
Original line number Diff line number Diff line
define([
	'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'templates/AtlasPrimaryList'
	, 'templates/AtlasSecondaryList'
	, 'templates/AtlasRedpromarSecondaryList'
	, 'templates/TrackingPrimaryList'
	, 'templates/TrackingSecondaryList'
	, 'templates/SpeciesDistributionPrimaryList'
	, 'templates/SpeciesDistributionCitation'
], function(
	declare
	, lang
	, AtlasPrimaryList
	, AtlasSecondaryList
	, AtlasRedpromarSecondaryList
	, TrackingPrimaryList
	, TrackingSecondaryList
	, SpeciesDistributionPrimaryList
	, SpeciesDistributionCitation
) {

	return declare(null, {
		//	summary:
		//		Extensión del módulo para las tareas de identificar tipos de datos y correspondencia de capas con
		//		plantillas específicas.

		constructor: function(args) {

			this.config = {
				layerIdSeparator: '_',
				layerIdPrefix: 'layer-',
				layerThemeSeparator: '-',
				typeGroupProperty: 'dataType',
				parentTemplateSuffix: 'Parent',
				childrenTemplateSuffix: 'Children',

				_templatesByTypeGroup: {
					//	Podemos sobreescribir las plantillas genéricas de las capas
					//	de atlas especificando el nombre de la capa completo
					//'el-batimetriaIslasParent': AtlasPrimaryList',
					//'el-batimetriaIslasChildren': AtlasBathymetry',

					'defaultParent': AtlasPrimaryList,
					'defaultChildren': AtlasSecondaryList,

					'trackingParent': TrackingPrimaryList,
					'trackingChildren': TrackingSecondaryList,

					'taxonDistributionParent': SpeciesDistributionPrimaryList,
					'taxonDistributionChildren': {
						'ci': SpeciesDistributionCitation,
						'at': TrackingSecondaryList
					},

					'sd-full_sighting_taxon_yearChildren': AtlasRedpromarSecondaryList,
					'sd-exotic-species-sightingChildren': AtlasRedpromarSecondaryList
				}
			};

			lang.mixin(this, this.config, args);
		},

		_getLayerTemplatesDefinition: function(layerId) {

			var layerName = this._getLayerName(layerId),
				parentTemplateDefinition = this._getTemplateForLayer(layerName, this.parentTemplateSuffix),
				childrenTemplateDefinition = this._getTemplateForLayer(layerName, this.childrenTemplateSuffix);

			return {
				typeGroup: layerName,
				parentTemplate: parentTemplateDefinition,
				childrenTemplate: childrenTemplateDefinition
			};
		},

		_getLayerName: function(layerId) {

			var layerIdSplit = layerId.split(this.layerIdSeparator + this.layerIdPrefix);

			if (layerIdSplit.length > 1) {
				return layerIdSplit[0];
			}

			return layerId.split(this.layerIdSeparator)[0];
		},

		_getTemplateForLayer: function(layerName, suffix) {

			var specificTemplate = this._templatesByTypeGroup[layerName + suffix],
				typeGroup = layerName.split(this.layerThemeSeparator)[0],
				genericTemplate = this._templatesByTypeGroup[typeGroup + suffix] ||
					this._templatesByTypeGroup['default' + suffix],

				templateDefinition = specificTemplate ? specificTemplate : genericTemplate;

			if (!templateDefinition) {
				console.error('Layer templates definition is wrong, default template was not found.');
			}

			return templateDefinition;
		},

		_processLayerInfo: function(res) {

			var layerId = res.layerId,
				layerLabel = res.layerLabel,
				layerInfo = res.info,
				isGeoJson = !!(layerInfo && layerInfo.features),
				hasFeatures = !!(isGeoJson && layerInfo.features.length),
				hasValidInfo = !!((!isGeoJson && layerInfo) || hasFeatures);

			if (!hasValidInfo) {
				return;
			}

			this._hadValidInfo = true;

			if (layerInfo instanceof Array) {
				for (var i = 0; i < layerInfo.length; i++) {
					this._loadInfo(layerId, layerLabel, layerInfo[i]);
				}
			} else {
				this._loadInfo(layerId, layerLabel, layerInfo);
			}
		},

		_loadInfo: function(layerId, layerLabel, layerInfo) {

			var infoData = this._getDataForAddInfo(layerId, layerLabel, layerInfo),
				typeGroup = this._getLayerName(layerId);

			infoData[this.typeGroupProperty] = typeGroup;

			this._emitEvt('ADD_INFO_DATA', infoData);
		},

		_getDataForAddInfo: function(layerId, layerLabel, data) {

			var layerIdPrefix = this._getLayerName(layerId),
				method;

			if (layerIdPrefix === 'tracking') {
				method = '_getTrackingSpecificData';
			} else if (layerIdPrefix === 'taxonDistribution') {
				method = '_getTaxonDistributionSpecificData';
			} else if (layerIdPrefix.indexOf(this.layerThemeSeparator) !== -1) {
				method = '_getThemeSpecificData';
			} else {
				method = '_showErrorOnGettingSpecificData';
			}
			return this[method](layerIdPrefix, layerLabel, data);
		},

		_getTrackingSpecificData: function(layerIdPrefix, layerLabel, data) {

			return {
				parent: lang.getObject('properties.element', false, data.features[0]),
				parentName: 'name',
				children: data.features
			};
		},

		_getTaxonDistributionSpecificData: function(layerIdPrefix, layerLabel, data) {

			return {
				parent: data,
				parentName: function(parentData) {

					return '<i>' + parentData.scientificName + '</i> ' + parentData.authorship;
				},
				children: data.citations.concat(data.animalTrackings)
			};
		},

		_getThemeSpecificData: function(layerIdPrefix, layerLabel, data) {

			return {
				parent: {
					name: layerLabel,
					id: layerIdPrefix
				},
				parentName: 'name',
				children: data.features
			};
		},

		_showErrorOnGettingSpecificData: function(layerIdPrefix, layerLabel, data) {

			console.error('Received data with unknown type', layerIdPrefix, layerLabel, data);

			return {};
		}
	});
});
+81 −0
Original line number Diff line number Diff line
define([
	'app/designs/primaryAndSecondaryContent/main/HierarchicalLists'
	, 'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'dojo/aspect'
	, 'put-selector/put'
	, 'redmic/modules/base/_Show'
], function(
	HierarchicalLists
	, declare
	, lang
	, aspect
	, put
	, _Show
) {

	return declare(_Show, {
		//	summary:
		//		Extensión del módulo para mostrar los resultados de consulta en listados jerárquicos dinámicos.

		constructor: function(args) {

			this.config = {
				containerClass: 'queryOnMapContainer'
			};

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

			aspect.after(this, '_beforeInitialize', lang.hitch(this, this._initializeResultsBrowser));
			aspect.after(this, '_definePublications', lang.hitch(this, this._defineResultsBrowserPublications));
		},

		_initializeResultsBrowser: function() {

			this._layersInfo = new HierarchicalLists({
				parentChannel: this.getChannel(),
				typeGroupProperty: this.typeGroupProperty,
				primaryTitle: this.i18n.presentElements,
				primaryListButtons: this.primaryListButtons,
				secondaryListButtons: this.secondaryListButtons
			});
		},

		_defineResultsBrowserPublications: function() {

			this.publicationsConfig.push({
				event: 'SHOW_LAYERS_INFO',
				channel: this.getChannel('SHOW')
			},{
				event: 'HIDE_LAYERS_INFO',
				channel: this.getChannel('HIDE')
			},{
				event: 'HIDE_LAYERS_INFO',
				channel: this._layersInfo.getChannel('CLEAR')
			},{
				event: 'ADD_INFO_DATA',
				channel: this._layersInfo.getChannel('NEW_DATA')
			},{
				event: 'ADD_NEW_TEMPLATES',
				channel: this._layersInfo.getChannel('ADD_NEW_TEMPLATES')
			});
		},

		postCreate: function() {

			this._layersInfoContainer = put('div.' + this.containerClass);
		},

		_getNodeToShow: function() {

			return this._layersInfoContainer;
		},

		_beforeShow: function() {

			this._publish(this._layersInfo.getChannel('SHOW'), {
				node: this._layersInfoContainer
			});
		}
	});
});
Compare aa7810bf to 4f3ae762
Original line number Diff line number Diff line
Subproject commit aa7810bfeb1df5376bfeb9db2c220001d8b1b5b6
Subproject commit 4f3ae762e61f5a93ef638e0edfd9b5e5e44a4638