Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Maps] symbolize points with maki icons #37822

Merged
merged 26 commits into from
Jun 14, 2019
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6ca43e5
[Maps] sybmolize points with maki icons
nreese May 28, 2019
6d6e556
add from for selecting symbol
nreese May 29, 2019
127f86a
add from for selecting symbol
nreese May 29, 2019
1cd5983
get icons working for static colors
nreese May 29, 2019
2f7a78e
static icon sizing
nreese May 29, 2019
062e881
refacto symbol_utils
nreese May 29, 2019
68b6bb5
merge with master
nreese May 30, 2019
29dc407
timing issue
nreese May 30, 2019
cd0dd03
use SDF icons
nreese May 30, 2019
b49d6a0
dynamic iconSize
nreese May 31, 2019
4cbc59d
set icon-anchor
nreese May 31, 2019
254805e
Merge branch 'master' of github.com:elastic/kibana into symbols_sdf
nreese May 31, 2019
5003180
display symbol icon in map legend
nreese May 31, 2019
37f3095
add unit tests for VectorIcon
nreese Jun 1, 2019
cad5228
Merge branch 'master' of github.com:elastic/kibana into symbols_sdf
nreese Jun 2, 2019
fdad667
set icon fill based on dark mode
nreese Jun 2, 2019
f8314d0
remove unused file
nreese Jun 2, 2019
97e8cf4
fix jest tests
nreese Jun 2, 2019
59c0e77
set icon-opacity
nreese Jun 2, 2019
d368e49
merge with master
nreese Jun 7, 2019
e292750
use size style to configure icon-image small or large
nreese Jun 7, 2019
974e482
fix queryRadius error by just hiding other point layer instead of rem…
nreese Jun 7, 2019
4dd7374
remove console statement on error
nreese Jun 12, 2019
a231d4a
use maki icon size constants
nreese Jun 14, 2019
91a30a8
Merge branch 'master' of github.com:elastic/kibana into symbols_sdf
nreese Jun 14, 2019
97f5abf
add retry around opening set view popover for flaky test
nreese Jun 14, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
378 changes: 378 additions & 0 deletions packages/kbn-maki/index.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions packages/kbn-maki/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@kbn/maki",
"version": "6.1.0",
"description": "browser friendly version of @mapbox/maki",
"license": "Apache-2.0",
"main": "index.js",
"devDependencies": {},
"dependencies": {},
"peerDependencies": {}
}
6 changes: 6 additions & 0 deletions packages/kbn-maki/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# @kbn/maki

[@mapbox/maki](https://www.npmjs.com/package/@mapbox/maki) only works in node.js.
See https://github.com/mapbox/maki/issues/462 for details.

@kbn/maki is a browser friendly version of @mapbox/maki
1 change: 1 addition & 0 deletions x-pack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
"@kbn/es-query": "1.0.0",
"@kbn/i18n": "1.0.0",
"@kbn/interpreter": "1.0.0",
"@kbn/maki": "6.1.0",
"@kbn/ui-framework": "1.0.0",
"@mapbox/mapbox-gl-draw": "^1.1.1",
"@samverschueren/stream-to-observable": "^0.3.0",
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/maps/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const GIS_API_PATH = 'api/maps';
export const EMS_DATA_FILE_PATH = 'ems/file';
export const EMS_DATA_TMS_PATH = 'ems/tms';
export const EMS_META_PATH = 'ems/meta';
export const SPRITE_PATH = '/maps/sprite';
export const MAKI_SPRITE_PATH = `${SPRITE_PATH}/maki`;

export const MAP_SAVED_OBJECT_TYPE = 'map';
export const APP_ID = 'maps';
Expand Down
22 changes: 22 additions & 0 deletions x-pack/plugins/maps/common/parse_xml_string.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { parseString } from 'xml2js';

// promise based wrapper around parseString
export async function parseXmlString(xmlString) {
const parsePromise = new Promise((resolve, reject) => {
parseString(xmlString, (error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
});

return await parsePromise;
}
16 changes: 16 additions & 0 deletions x-pack/plugins/maps/common/parse_xml_string.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { parseXmlString } from './parse_xml_string';

describe('parseXmlString', () => {
it('Should parse xml string into JS object', async () => {
const xmlAsObject = await parseXmlString('<foo>bar</foo>');
expect(xmlAsObject).toEqual({
foo: 'bar'
});
});
});
10 changes: 10 additions & 0 deletions x-pack/plugins/maps/public/components/map/mb/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@

import _ from 'lodash';
import mapboxgl from 'mapbox-gl';
import chrome from 'ui/chrome';
import { MAKI_SPRITE_PATH } from '../../../../common/constants';

function relativeToAbsolute(url) {
const a = document.createElement('a');
a.setAttribute('href', url);
return a.href;
}

export async function createMbMapInstance({ node, initialView, scrollZoom }) {
const makiUrl = relativeToAbsolute(chrome.addBasePath(MAKI_SPRITE_PATH));
return new Promise((resolve) => {
const options = {
attributionControl: false,
Expand All @@ -16,6 +25,7 @@ export async function createMbMapInstance({ node, initialView, scrollZoom }) {
version: 8,
sources: {},
layers: [],
sprite: makiUrl
},
scrollZoom
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import _ from 'lodash';
import { parseString } from 'xml2js';
import { parseXmlString } from '../../../../../common/parse_xml_string';
import fetch from 'node-fetch';
import { parse, format } from 'url';

Expand Down Expand Up @@ -76,16 +76,7 @@ export class WmsClient {
}
const body = await resp.text();

const parsePromise = new Promise((resolve, reject) => {
parseString(body, (error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
return await parsePromise;
return await parseXmlString(body);
}

async getCapabilities() {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import React from 'react';

export const PointIcon = ({ style }) => (
export const CircleIcon = ({ style }) => (
<svg
className="euiIcon euiIcon--medium mapFillableCircle"
xmlns="http://www.w3.org/2000/svg"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import PropTypes from 'prop-types';
import { styleOptionShapes, rangeShape } from '../style_option_shapes';
import { VectorStyle } from '../../../vector_style';
import { ColorGradient } from '../../color_gradient';
import { PointIcon } from './point_icon';
import { CircleIcon } from './circle_icon';
import { getVectorStyleLabel } from '../get_vector_style_label';
import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
import { StyleLegendRow } from '../../style_legend_row';
Expand All @@ -23,9 +23,9 @@ function getLineWidthIcons() {
width: '12px',
};
return [
<PointIcon style={{ ...defaultStyle, strokeWidth: '1px' }}/>,
<PointIcon style={{ ...defaultStyle, strokeWidth: '2px' }}/>,
<PointIcon style={{ ...defaultStyle, strokeWidth: '3px' }}/>,
<CircleIcon style={{ ...defaultStyle, strokeWidth: '1px' }}/>,
<CircleIcon style={{ ...defaultStyle, strokeWidth: '2px' }}/>,
<CircleIcon style={{ ...defaultStyle, strokeWidth: '3px' }}/>,
];
}

Expand All @@ -36,9 +36,9 @@ function getSymbolSizeIcons() {
fill: 'grey',
};
return [
<PointIcon style={{ ...defaultStyle, width: '4px' }}/>,
<PointIcon style={{ ...defaultStyle, width: '8px' }}/>,
<PointIcon style={{ ...defaultStyle, width: '12px' }}/>,
<CircleIcon style={{ ...defaultStyle, width: '4px' }}/>,
<CircleIcon style={{ ...defaultStyle, width: '8px' }}/>,
<CircleIcon style={{ ...defaultStyle, width: '12px' }}/>,
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React, { Component } from 'react';
import PropTypes from 'prop-types';

import { getMakiSymbolSvg, styleSvg, buildSrcUrl } from '../../../symbol_utils';

export class SymbolIcon extends Component {

state = {
imgDataUrl: undefined,
prevSymbolId: undefined,
prevFill: undefined,
}

componentDidMount() {
this._isMounted = true;
this._loadSymbol(this.props.symbolId, this.props.fill);
}

componentDidUpdate() {
this._loadSymbol(this.props.symbolId, this.props.fill);
}

componentWillUnmount() {
this._isMounted = false;
}

async _loadSymbol(nextSymbolId, nextFill) {
if (nextSymbolId === this.state.prevSymbolId
&& nextFill === this.state.prevFill) {
return;
}

let imgDataUrl;
try {
const svg = getMakiSymbolSvg(nextSymbolId);
const styledSvg = await styleSvg(svg, nextFill);
imgDataUrl = buildSrcUrl(styledSvg);
} catch (error) {
// ignore failures - component will just not display an icon
}

if (this._isMounted) {
nreese marked this conversation as resolved.
Show resolved Hide resolved
this.setState({
imgDataUrl,
prevSymbolId: nextSymbolId,
prevFill: nextFill
});
}
}

render() {
if (!this.state.imgDataUrl) {
return null;
}

return (
<img width="16px" src={this.state.imgDataUrl} alt={this.props.symbolId} />
);
}
}

SymbolIcon.propTypes = {
symbolId: PropTypes.string.isRequired,
fill: PropTypes.string.isRequired,
};
Loading