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

[Region Map] Fix loading default vector map and base layer setting #43858

Merged
merged 10 commits into from
Sep 11, 2019
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import React, { useEffect, useState, useCallback, useMemo } from 'react';
import React, { useState, useCallback, useMemo } from 'react';
import { EuiIcon, EuiLink, EuiPanel, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
Expand All @@ -36,6 +36,10 @@ import { mapToLayerWithId } from '../util';
import { RegionMapVisParams } from '../types';
import { RegionMapsConfig } from '../plugin';

// TODO: Below import is temporary, use `react-use` lib instead.
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { useMount } from '../../../../../plugins/kibana_react/public/util/use_mount';

const mapLayerForOption = ({ layerId, name }: VectorLayer) => ({
text: name,
value: layerId,
Expand All @@ -52,26 +56,32 @@ export type RegionMapOptionsProps = {
} & VisOptionsProps<RegionMapVisParams>;

function RegionMapOptions(props: RegionMapOptionsProps) {
const { includeElasticMapsService, serviceSettings, stateParams, vis, setValue } = props;
const {
includeElasticMapsService,
serviceSettings,
stateParams,
vis,
setValue,
forceUpdateVis,
} = props;
const [vectorLayers, setVectorLayers] = useState<VectorLayer[]>(
vis.type.editorConfig.collections.vectorLayers
);
const [vectorLayerOptions, setVectorLayerOptions] = useState(vectorLayers.map(mapLayerForOption));
const currentLayerId = stateParams.selectedLayer && stateParams.selectedLayer.layerId;
const fieldOptions = useMemo(
() =>
((stateParams.selectedLayer && stateParams.selectedLayer.fields) || []).map(
mapFieldForOption
),
[currentLayerId]
[stateParams.selectedLayer]
);

const setEmsHotLink = useCallback(
async (layer: VectorLayer) => {
const emsHotLink = await serviceSettings.getEMSHotLink(layer);
setValue('emsHotLink', emsHotLink);
},
[setValue]
[setValue, serviceSettings]
);

const setLayer = useCallback(
Expand All @@ -84,7 +94,7 @@ function RegionMapOptions(props: RegionMapOptionsProps) {
setEmsHotLink(newLayer);
}
},
[vectorLayers, setValue]
[vectorLayers, setEmsHotLink, setValue]
);

const setField = useCallback(
Expand All @@ -93,10 +103,10 @@ function RegionMapOptions(props: RegionMapOptionsProps) {
setValue(paramName, stateParams.selectedLayer.fields.find(f => f.name === value));
}
},
[currentLayerId, setValue]
[setValue, stateParams.selectedLayer]
);

useEffect(() => {
const onMount = () => {
async function setDefaultValues() {
try {
const layers = await serviceSettings.getFileLayers();
Expand Down Expand Up @@ -129,6 +139,12 @@ function RegionMapOptions(props: RegionMapOptionsProps) {
if (newLayer.isEMS) {
setEmsHotLink(newLayer);
}

// apply default changes directly to visualization
// without it, these values will be reset after visualization loading
// caused by vis state watcher at line 138 in src/legacy/ui/public/vis/editors/default/default.js
// the approach could be revised after removing angular
forceUpdateVis();
}
} catch (error) {
toastNotifications.addWarning(error.message);
Expand All @@ -138,7 +154,9 @@ function RegionMapOptions(props: RegionMapOptionsProps) {
if (includeElasticMapsService) {
setDefaultValues();
}
}, []);
};

useMount(onMount);

return (
<>
Expand Down
19 changes: 16 additions & 3 deletions src/legacy/core_plugins/tile_map/public/components/wms_options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import React, { useEffect, useState } from 'react';
import React, { useState } from 'react';
import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
Expand All @@ -30,9 +30,14 @@ import { WmsInternalOptions } from './wms_internal_options';
import { TileMapOptionsProps } from './tile_map_options';
import { TileMapVisParams } from '../types';

// TODO: Below import is temporary, use `react-use` lib instead.
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { useMount } from '../../../../../plugins/kibana_react/public/util/use_mount';

const mapLayerForOption = ({ id }: TmsLayer) => ({ text: id, value: id });

function WmsOptions({
forceUpdateVis,
serviceSettings,
stateParams,
setValue,
Expand Down Expand Up @@ -61,7 +66,7 @@ function WmsOptions({
}
};

useEffect(() => {
const onMount = () => {
serviceSettings
.getTMSServices()
.then(services => {
Expand All @@ -75,10 +80,18 @@ function WmsOptions({

if (!wms.selectedTmsLayer && newBaseLayers.length) {
setWmsOption('selectedTmsLayer', newBaseLayers[0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setting this here will require:

  • clicking on the "play" button
  • or calling forceUpdateVis (to send changes down to vis)

however i am wondering, should this happen here ? i see a few options:

  • have tms stuff preloaded (at the vis registration time) ... then we should be able to set visualization defaults to the first layer.
  • move the logic into map visualization .... if layer is not set use the first layer

i would prefer the first one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code which registers vis is run every time when the app opens (or the page is refreshed) no matter what plugin opened. I think the layers should be fetched only when map visualization opens. For example during redirecting to the editor but before rendering the default editor we can load tms layers and set the first layer. I tried to implement this idea. @ppisljar could you please have a look?


// apply default changes directly to visualization
// without it, these values will be reset after visualization loading
// caused by vis state watcher at line 138 in src/legacy/ui/public/vis/editors/default/default.js
// the approach could be revised after removing angular
forceUpdateVis();
}
})
.catch((error: Error) => toastNotifications.addWarning(error.message));
}, []);
};

useMount(onMount);

return (
<EuiPanel paddingSize="s">
Expand Down
1 change: 1 addition & 0 deletions src/legacy/ui/public/vis/editors/default/sidebar.html
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
visualize-editor="visualizeEditor"
editor="tab.editor"
on-agg-params-change="onAggParamsChange"
force-update-vis="stageEditableVis"
></vis-editor-vis-options>
</div>

Expand Down
5 changes: 4 additions & 1 deletion src/legacy/ui/public/vis/editors/default/vis_options.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ uiModules
['setValue', { watchDepth: 'reference' }],
['setValidity', { watchDepth: 'reference' }],
['setTouched', { watchDepth: 'reference' }],
['forceUpdateVis', { watchDepth: 'reference' }],
'hasHistogramAgg',
]))
.directive('visEditorVisOptions', function ($compile) {
Expand All @@ -53,6 +54,7 @@ uiModules
editorState: '=',
onAggParamsChange: '=',
hasHistogramAgg: '=',
forceUpdateVis: '=',
},
link: function ($scope, $el, attrs, ngModelCtrl) {
$scope.setValue = (paramName, value) =>
Expand Down Expand Up @@ -81,7 +83,8 @@ uiModules
ui-state="uiState"
set-value="setValue"
set-validity="setValidity"
set-touched="setTouched">
set-touched="setTouched"
force-update-vis="forceUpdateVis">
</vis-options-react-wrapper>`;
const $editor = $compile(comp)($scope);
$el.append($editor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ export interface VisOptionsProps<VisParamType = unknown> {
setValue<T extends keyof VisParamType>(paramName: T, value: VisParamType[T]): void;
setValidity(isValid: boolean): void;
setTouched(isTouched: boolean): void;
forceUpdateVis(): void;
}
24 changes: 24 additions & 0 deletions src/plugins/kibana_react/public/util/use_mount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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 { useEffect } from 'react';

export function useMount(fn: () => void): void {
useEffect(fn, []);
}