UNPKG

gethue

Version:

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

350 lines (322 loc) 11.6 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 nv from '../../../../ext/nv.d3.1.1.15b.custom'; import Datamap from './datamap'; import huePubSub from '../../../../utils/huePubSub'; import HueColors from '../../../../utils/hueColors'; import HueGeo from '../../../../utils/hueGeo'; ko.bindingHandlers.mapChart = { render: function (element, valueAccessor) { const _options = valueAccessor(); const $element = $(element); window.clearTimeout($element.data('drawThrottle')); const timeout = window.setTimeout(() => { $element.empty(); $element.css('position', 'relative'); $element.css('marginLeft', 'auto'); $element.css('marginRight', 'auto'); if (typeof _options.maxWidth != 'undefined') { const _max = _options.maxWidth * 1; $element.width(Math.min($element.parent().width(), _max)); } else { $element.width($element.parent().width() - 10); } $element.height($element.width() / 2.23); const scopeObservable = _options.data.scope || _options.data.chartScope; const _scope = scopeObservable ? String(ko.unwrap(scopeObservable)) : 'world'; const _data = _options.transformer(_options.data); let _is2d = false; const _pivotCategories = []; let _maxWeight = 0; function comparePivotValues(a, b) { if (a.count < b.count) { return 1; } if (a.count > b.count) { return -1; } return 0; } $(_data).each((cnt, item) => { if (item.value > _maxWeight) { _maxWeight = item.value; } if (item.obj.is2d) { _is2d = true; } if (item.obj.pivot && item.obj.pivot.length > 0) { item.obj.pivot.forEach(piv => { let _category = null; _pivotCategories.forEach(category => { if (category.value === piv.value) { _category = category; if (piv.count > _category.count) { _category.count = piv.count; } } }); if (_category == null) { _category = { value: piv.value, count: -1 }; _pivotCategories.push(_category); } }); } }); _pivotCategories.sort(comparePivotValues); const _chunk = _maxWeight / _data.length; const _mapdata = {}; const _maphovers = {}; const _fills = {}; const _legend = []; const _noncountries = []; if (_options.isScale) { _fills['defaultFill'] = HueColors.WHITE; const _colors = _is2d ? HueColors.d3Scale() : HueColors.scale(HueColors.LIGHT_BLUE, HueColors.DARK_BLUE, _data.length); $(_colors).each((cnt, item) => { _fills['fill_' + cnt] = item; }); const getHighestCategoryValue = (cnt, item) => { let _cat = ''; let _max = -1; if (item.obj.pivot && item.obj.pivot.length > 0) { item.obj.pivot.forEach(piv => { if (piv.count > _max) { _max = piv.count; _cat = piv.value; } }); } let _found = cnt; if (_cat !== '') { _pivotCategories.forEach((cat, i) => { if (cat.value === _cat) { _found = i; } }); } return { idx: _found, cat: _cat }; }; const addToLegend = category => { let _found = false; _legend.forEach(lg => { if (lg.cat === category.cat) { _found = true; } }); if (!_found) { _legend.push(category); } }; $(_data).each((cnt, item) => { addToLegend(getHighestCategoryValue(cnt, item)); let _place = typeof item.label == 'string' ? item.label.toUpperCase() : item.label; if (_place != null) { if ( _scope !== 'world' && _scope !== 'usa' && _scope !== 'europe' && _place.indexOf('.') === -1 ) { _place = HueGeo.getISOAlpha2(_scope) + '.' + _place; } if ((_scope === 'world' || _scope === 'europe') && _place.length === 2) { _place = HueGeo.getISOAlpha3(_place); } _mapdata[_place] = { fillKey: 'fill_' + (_is2d ? getHighestCategoryValue(cnt, item).idx : Math.ceil(item.value / _chunk) - 1), id: _place, cat: item.obj.cat, value: item.obj.values ? item.obj.values : item.obj.value, pivot: _is2d ? item.obj.pivot : [], selected: item.obj.selected, fields: item.obj.fields ? item.obj.fields : null }; _maphovers[_place] = item.value; } else { _noncountries.push(item); } }); } else { _fills['defaultFill'] = HueColors.LIGHT_BLUE; _fills['selected'] = HueColors.DARK_BLUE; $(_data).each((cnt, item) => { let _place = item.label.toUpperCase(); if (_place != null) { if ( _scope !== 'world' && _scope !== 'usa' && _scope !== 'europe' && _place.indexOf('.') === -1 ) { _place = HueGeo.getISOAlpha2(_scope) + '.' + _place; } if ((_scope === 'world' || _scope === 'europe') && _place.length === 2) { _place = HueGeo.getISOAlpha3(_place); } _mapdata[_place] = { fillKey: 'selected', id: _place, cat: item.obj.cat, value: item.obj.values ? item.obj.values : item.obj.value, pivot: [], selected: item.obj.selected, fields: item.obj.fields ? item.obj.fields : null }; _maphovers[_place] = item.value; } else { _noncountries.push(item); } }); } let _map = null; function createDatamap(element, options, fills, mapData, nonCountries, mapHovers) { _map = new Datamap({ element: element, fills: fills, scope: _scope, data: mapData, legendData: _legend, onClick: function (data) { if (typeof options.onClick != 'undefined') { huePubSub.publish('charts.state', { updating: true }); options.onClick(data); } }, done: function () { const _bubbles = []; if (options.enableGeocoding) { $(nonCountries).each((cnt, item) => { HueGeo.getCityCoordinates(item.label, (lat, lng) => { _bubbles.push({ fillKey: 'selected', label: item.label, value: item.value, radius: 4, latitude: lat, longitude: lng }); _map.bubbles(_bubbles, { popupTemplate: function (geo, data) { return ( '<div class="hoverinfo" style="text-align: center"><strong>' + data.label + '</strong><br/>' + item.value + '</div>' ); } }); }); }); } }, geographyConfig: { hideAntarctica: true, borderWidth: 1, borderColor: HueColors.DARK_BLUE, highlightOnHover: true, highlightFillColor: HueColors.DARK_BLUE, highlightBorderColor: HueColors.BLUE, selectedFillColor: HueColors.DARKER_BLUE, selectedBorderColor: HueColors.DARKER_BLUE, popupTemplate: function (geography, data) { let _hover = ''; if (data != null) { _hover = '<br/>'; if (data.pivot && data.pivot.length > 0) { data.pivot.sort(comparePivotValues); data.pivot.forEach((piv, cnt) => { _hover += (cnt === 0 ? '<strong>' : '') + piv.value + ': ' + piv.count + (cnt === 0 ? '</strong>' : '') + '<br/>'; }); } else { _hover += mapHovers[data.id]; } } return ( '<div class="hoverinfo" style="text-align: center"><strong>' + geography.properties.name + '</strong>' + _hover + '</div>' ); } } }); if (options.onComplete != null) { options.onComplete(); } if (_is2d) { _map.legend(); } } createDatamap(element, _options, _fills, _mapdata, _noncountries, _maphovers); const _parentSelector = typeof _options.parentSelector != 'undefined' ? _options.parentSelector : '.card-widget'; $element.parents(_parentSelector).one('resize', () => { ko.bindingHandlers.mapChart.render(element, valueAccessor); }); let _resizeTimeout = -1; nv.utils.windowResize(() => { window.clearTimeout(_resizeTimeout); _resizeTimeout = window.setTimeout(() => { ko.bindingHandlers.mapChart.render(element, valueAccessor); }, 200); }); huePubSub.publish('charts.state'); }, 50); $element.data('drawThrottle', timeout); }, init: function (element, valueAccessor) { ko.bindingHandlers.mapChart.render(element, valueAccessor); }, update: function (element, valueAccessor, allBindingsAccessor) { if (typeof allBindingsAccessor().mapChart.visible != 'undefined') { if ( (typeof allBindingsAccessor().mapChart.visible == 'boolean' && allBindingsAccessor().mapChart.visible) || (typeof allBindingsAccessor().mapChart.visible == 'function' && allBindingsAccessor().mapChart.visible()) ) { $(element).show(); ko.bindingHandlers.mapChart.render(element, valueAccessor); } else { $(element).hide(); } } else { ko.bindingHandlers.mapChart.render(element, valueAccessor); } } };