UNPKG

gethue

Version:

Hue is an Open source SQL Query Editor for Databases/Warehouses

327 lines (295 loc) 11.2 kB
// Licensed to Cloudera, Inc. under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. Cloudera, Inc. licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import $ from 'jquery'; import * as ko from 'knockout'; import 'ext/leaflet/leaflet'; import 'ext/leaflet/leaflet.markercluster'; import 'ext/leaflet/leaflet.heat'; import 'ext/leaflet/leaflet.zoombox'; import huePubSub from '../../../utils/huePubSub'; ko.bindingHandlers.leafletMapChart = { update: function (element, valueAccessor) { const L = window.L; const _options = valueAccessor(); const _data = _options.transformer(valueAccessor().datum); function toggleVisibility() { if ( !_data.message && ((_options.visible != null && _options.visible) || _options.visible == null || typeof _options == 'undefined') ) { $(element).show(); $(element).siblings('.leaflet-nodata').remove(); } else { $(element).hide(); if ( (_data.message || (_options.visible != null && _options.visible)) && !_options.isLoading ) { $(element).siblings('.leaflet-nodata').remove(); $(element).before( $('<div>') .addClass('leaflet-nodata') .css({ textAlign: 'center', fontSize: '18px', fontWeight: 700, marginTop: '20px' }) .text(_data.message || window.I18n('No Data Available.')) ); } } } if ( $(element).data('mapData') == null || $(element).data('mapData') !== ko.toJSON(_data) || _options.forceRedraw ) { $(element).data('mapData', ko.toJSON(_data)); let _hasAtLeastOneLat = false; _data.forEach(item => { if (item.lat != null && $.isNumeric(item.lat)) { _hasAtLeastOneLat = true; } }); let _hasAtLeastOneLng = false; _data.forEach(item => { if (item.lng != null && $.isNumeric(item.lng)) { _hasAtLeastOneLng = true; } }); if (_options.height != null) { $(element).height(_options.height * 1); } else if ($(element).parents('.tab-pane').length > 0) { $(element).height($(element).parents('.tab-pane').height() - 100); } else { $(element).height(300); } toggleVisibility(); let _map = null; if ($(element).data('_map') != null) { _map = $(element).data('_map'); _map.removeLayer($(element).data('_markerLayer')); if ($(element).data('_heatLayer')) { _map.removeLayer($(element).data('_heatLayer')); $(element).data('_heatLayer', null); } } const _clusterGroup = L.markerClusterGroup({ maxClusterRadius: 10, polygonOptions: { weight: 1.5 } }); let heat; if (_hasAtLeastOneLat && _hasAtLeastOneLng) { try { if (_map == null) { if (window.LEAFLET_DEFAULTS.mapOptions.crs) { window.LEAFLET_DEFAULTS.mapOptions.crs = L.CRS[window.LEAFLET_DEFAULTS.mapOptions.crs]; } _map = L.map(element, window.LEAFLET_DEFAULTS.mapOptions); let tileLayerOptions = { layer: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }; if (window.LEAFLET_DEFAULTS.layer) { tileLayerOptions.layer = window.LEAFLET_DEFAULTS.layer; } if (window.LEAFLET_DEFAULTS.attribution) { tileLayerOptions.attribution = window.LEAFLET_DEFAULTS.attribution; } if (window.LEAFLET_DEFAULTS.layerOptions) { tileLayerOptions = $.extend(tileLayerOptions, window.LEAFLET_DEFAULTS.layerOptions); } L.tileLayer(tileLayerOptions.layer, tileLayerOptions).addTo(_map); if (L.control.zoomBox) { const _zoomBox = L.control.zoomBox({ modal: true }); _map.addControl(_zoomBox); } if (_options.showMoveCheckbox) { const _command = L.control({ position: $(element).width() > 300 ? 'topright' : 'bottomleft' }); _command.onAdd = function (map) { const div = L.DomUtil.create( 'div', 'leaflet-search-command leaflet-bar leaflet-move-label' ); div.innerHTML = '<button id="command' + $(element).parents('.card-widget').attr('id') + '" type="button" class="btn btn-mini disable-feedback"><i class="fa fa-fw fa-square-o"></i> ' + (_options.moveCheckboxLabel ? _options.moveCheckboxLabel : 'Search as I move the map') + '</button>'; return div; }; _command.addTo(_map); if (_options.onRegionChange == null) { _options.onRegionChange = function () {}; } let _onRegionChange = function () {}; $('#command' + $(element).parents('.card-widget').attr('id')).on( 'click', function (e) { $(this).toggleClass('btn-primary'); $(this).find('.fa-fw').toggleClass('fa-check-square'); if ($(this).hasClass('btn-primary')) { if (_options.onRegionChange != null) { _onRegionChange = _options.onRegionChange; } } else { _onRegionChange = function () {}; } } ); ko.utils.domNodeDisposal.addDisposeCallback(element, () => { $('#command' + $(element).parents('.card-widget').attr('id')).off('click'); }); _map.on('boxzoomend', e => { _onRegionChange(e.boxZoomBounds); }); _map.on('dragend', () => { _onRegionChange(_map.getBounds()); }); _map.on('zoomend', () => { _onRegionChange(_map.getBounds()); }); _map.on('viewreset', () => { huePubSub.publish('leaflet.afterplot', element); }); } } let heatData = []; const sumHeatData = data => { const sumData = []; data.forEach(d => { let found = false; if (d.length === 3) { sumData.forEach(s => { if (d[0] === s[0] && d[1] === s[1]) { found = true; s[2] += d[2]; } }); } if (!found) { sumData.push(d); } }); return sumData; }; const getMaxIntensity = data => { let maxIntensity = 0; data.forEach(d => { if (d[2] > maxIntensity) { maxIntensity = d[2]; } }); return maxIntensity; }; _data.forEach(item => { if (item && item.lng != null && item.lat != null) { let _addMarker = false; try { const _latLngObj = L.latLng(item.lat, item.lng); _addMarker = true; } catch (e) { if (typeof console != 'undefined') { console.error(e); } } if (_addMarker) { const _marker = L.marker([item.lat, item.lng]); if (item.isHeat) { if (item.intensity != null) { heatData.push([item.lat, item.lng, item.intensity]); } else { heatData.push([item.lat, item.lng]); } } else if (item.label != null) { _marker.bindPopup($.isArray(item.label) ? item.label.join('') : item.label); } _clusterGroup.addLayer(_marker); } } }); if (heatData.length > 0) { heatData = sumHeatData(heatData); heat = L.heatLayer(heatData); if (heatData[0].length === 3) { // it has intensity heat.setOptions(getMaxIntensity(heatData)); } } window.setTimeout(() => { if (!$('#command' + $(element).parents('.card-widget').attr('id')).is(':checked')) { _map.fitBounds(_clusterGroup.getBounds()); } if ($(element).find('.leaflet-tile-pane').children().length > 0) { if (heatData.length == 0) { _map.addLayer(_clusterGroup); $('.leaflet-heatmap-layer').remove(); } else { try { $('.leaflet-heatmap-layer').remove(); heat.addTo(_map); } catch (e) {} // context2D not initialized yet } } if (_options.onComplete != null) { _options.onComplete(); } }, 0); const resizeSubscription = huePubSub.subscribe('resize.leaflet.map', () => { if ($(element).data('_map')) { $(element).data('_map').invalidateSize(); if ($(element).data('_markerLayer')) { try { $(element).data('_map').fitBounds($(element).data('_markerLayer').getBounds()); } catch (e) {} } } }); ko.utils.domNodeDisposal.addDisposeCallback(element, () => { resizeSubscription.remove(); }); } catch (err) { $.jHueNotify.error(err.message); } } const previousMarkerLayer = $(element).data('_markerLayer'); if (previousMarkerLayer) { window.setTimeout(() => { try { previousMarkerLayer.removeLayers(previousMarkerLayer.getLayers()); } catch (e) {} }, 0); } $(element).data('_map', _map); $(element).data('_markerLayer', _clusterGroup); $(element).data('_heatLayer', heat); if (_options.onComplete != null) { _options.onComplete(); } } else { toggleVisibility(); } } };