mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[maps] fix geojson layer with joins and no left source matches stuck in loading state (#160222)
closes https://github.com/elastic/kibana/issues/156630 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
a23f0b27d1
commit
c9474270d1
6 changed files with 194 additions and 9 deletions
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { SOURCE_DATA_REQUEST_ID } from '../../../../../common/constants';
|
||||
import { VectorLayerDescriptor } from '../../../../../common/descriptor_types';
|
||||
import { InnerJoin } from '../../../joins/inner_join';
|
||||
import { IJoinSource } from '../../../sources/join_sources';
|
||||
import { IVectorSource } from '../../../sources/vector_source';
|
||||
import { GeoJsonVectorLayer } from './geojson_vector_layer';
|
||||
|
||||
const joinDataRequestId = 'join_source_a0b0da65-5e1a-4967-9dbe-74f24391afe2';
|
||||
const mockJoin = {
|
||||
hasCompleteConfig: () => {
|
||||
return true;
|
||||
},
|
||||
getSourceDataRequestId: () => {
|
||||
return joinDataRequestId;
|
||||
},
|
||||
getRightJoinSource: () => {
|
||||
return {} as unknown as IJoinSource;
|
||||
},
|
||||
} as unknown as InnerJoin;
|
||||
|
||||
describe('isLayerLoading', () => {
|
||||
test('should return true when source loading has not started', () => {
|
||||
const layer = new GeoJsonVectorLayer({
|
||||
customIcons: [],
|
||||
layerDescriptor: {},
|
||||
source: {} as unknown as IVectorSource,
|
||||
});
|
||||
expect(layer.isLayerLoading(1)).toBe(true);
|
||||
});
|
||||
|
||||
test('Should return true when source data request is pending', () => {
|
||||
const layer = new GeoJsonVectorLayer({
|
||||
customIcons: [],
|
||||
layerDescriptor: {
|
||||
__dataRequests: [
|
||||
{
|
||||
data: {},
|
||||
dataId: SOURCE_DATA_REQUEST_ID,
|
||||
dataRequestMetaAtStart: {},
|
||||
dataRequestToken: Symbol(),
|
||||
},
|
||||
],
|
||||
},
|
||||
source: {} as unknown as IVectorSource,
|
||||
});
|
||||
expect(layer.isLayerLoading(1)).toBe(true);
|
||||
});
|
||||
|
||||
describe('no joins', () => {
|
||||
test('Should return false when source data request is finished', () => {
|
||||
const layer = new GeoJsonVectorLayer({
|
||||
customIcons: [],
|
||||
layerDescriptor: {
|
||||
__dataRequests: [
|
||||
{
|
||||
data: {},
|
||||
dataId: SOURCE_DATA_REQUEST_ID,
|
||||
dataRequestMeta: {},
|
||||
dataRequestMetaAtStart: undefined,
|
||||
dataRequestToken: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
source: {} as unknown as IVectorSource,
|
||||
});
|
||||
expect(layer.isLayerLoading(1)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('joins', () => {
|
||||
describe('source data loaded with no features', () => {
|
||||
test('should return false when join loading has not started', () => {
|
||||
const layer = new GeoJsonVectorLayer({
|
||||
customIcons: [],
|
||||
joins: [mockJoin],
|
||||
layerDescriptor: {
|
||||
__dataRequests: [
|
||||
{
|
||||
data: {
|
||||
features: [],
|
||||
},
|
||||
dataId: SOURCE_DATA_REQUEST_ID,
|
||||
dataRequestMeta: {},
|
||||
dataRequestMetaAtStart: undefined,
|
||||
dataRequestToken: undefined,
|
||||
},
|
||||
],
|
||||
} as unknown as VectorLayerDescriptor,
|
||||
source: {} as unknown as IVectorSource,
|
||||
});
|
||||
expect(layer.isLayerLoading(1)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('source data loaded with features', () => {
|
||||
const sourceDataRequestDescriptorWithFeatures = {
|
||||
data: {
|
||||
features: [{}],
|
||||
},
|
||||
dataId: SOURCE_DATA_REQUEST_ID,
|
||||
dataRequestMeta: {},
|
||||
dataRequestMetaAtStart: undefined,
|
||||
dataRequestToken: undefined,
|
||||
};
|
||||
|
||||
test('should return true when join loading has not started', () => {
|
||||
const layer = new GeoJsonVectorLayer({
|
||||
customIcons: [],
|
||||
joins: [mockJoin],
|
||||
layerDescriptor: {
|
||||
__dataRequests: [sourceDataRequestDescriptorWithFeatures],
|
||||
} as unknown as VectorLayerDescriptor,
|
||||
source: {} as unknown as IVectorSource,
|
||||
});
|
||||
expect(layer.isLayerLoading(1)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when join data request is pending', () => {
|
||||
const layer = new GeoJsonVectorLayer({
|
||||
customIcons: [],
|
||||
joins: [mockJoin],
|
||||
layerDescriptor: {
|
||||
__dataRequests: [
|
||||
sourceDataRequestDescriptorWithFeatures,
|
||||
{
|
||||
dataId: joinDataRequestId,
|
||||
dataRequestMetaAtStart: {},
|
||||
dataRequestToken: Symbol(),
|
||||
},
|
||||
],
|
||||
} as unknown as VectorLayerDescriptor,
|
||||
source: {} as unknown as IVectorSource,
|
||||
});
|
||||
expect(layer.isLayerLoading(1)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false when join data request is finished', () => {
|
||||
const layer = new GeoJsonVectorLayer({
|
||||
customIcons: [],
|
||||
joins: [mockJoin],
|
||||
layerDescriptor: {
|
||||
__dataRequests: [
|
||||
sourceDataRequestDescriptorWithFeatures,
|
||||
{
|
||||
data: {},
|
||||
dataId: joinDataRequestId,
|
||||
dataRequestMeta: {},
|
||||
dataRequestMetaAtStart: undefined,
|
||||
dataRequestToken: undefined,
|
||||
},
|
||||
],
|
||||
} as unknown as VectorLayerDescriptor,
|
||||
source: {} as unknown as IVectorSource,
|
||||
});
|
||||
expect(layer.isLayerLoading(1)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -60,6 +60,23 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer {
|
|||
return layerDescriptor;
|
||||
}
|
||||
|
||||
isLayerLoading(zoom: number) {
|
||||
const isSourceLoading = super.isLayerLoading(zoom);
|
||||
if (isSourceLoading) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do not check join loading status when there are no source features. Why?
|
||||
// syncMeta short circuits join loading when there are no source features
|
||||
// because there is no reason to fetch join results when there is nothing to join with
|
||||
const featureCollection = this._getSourceFeatureCollection();
|
||||
if (!featureCollection || featureCollection?.features?.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._isLoadingJoins();
|
||||
}
|
||||
|
||||
_isTiled(): boolean {
|
||||
// Uses untiled maplibre source 'geojson'
|
||||
return false;
|
||||
|
|
|
@ -74,6 +74,11 @@ export class MvtVectorLayer extends AbstractVectorLayer {
|
|||
this._source = args.source as IMvtVectorSource;
|
||||
}
|
||||
|
||||
isLayerLoading(zoom: number) {
|
||||
const isSourceLoading = super.isLayerLoading(zoom);
|
||||
return isSourceLoading ? true : this._isLoadingJoins();
|
||||
}
|
||||
|
||||
_isTiled(): boolean {
|
||||
// Uses tiled maplibre source 'vector'
|
||||
return true;
|
||||
|
|
|
@ -259,12 +259,7 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer {
|
|||
return this.getValidJoins().length > 0;
|
||||
}
|
||||
|
||||
isLayerLoading(zoom: number) {
|
||||
const isSourceLoading = super.isLayerLoading(zoom);
|
||||
if (isSourceLoading) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_isLoadingJoins() {
|
||||
return this.getValidJoins().some((join) => {
|
||||
const joinDataRequest = this.getDataRequest(join.getSourceDataRequestId());
|
||||
return !joinDataRequest || joinDataRequest.isLoading();
|
||||
|
|
|
@ -106,7 +106,8 @@ export function GeoIndexPatternSelect(props: Props) {
|
|||
}
|
||||
|
||||
const IndexPatternSelect = getIndexPatternSelectComponent();
|
||||
const error = !hasGeoFields
|
||||
const isDataViewInvalid = !props.dataView ? false : !hasGeoFields;
|
||||
const error = isDataViewInvalid
|
||||
? i18n.translate('xpack.maps.noGeoFieldInIndexPattern.message', {
|
||||
defaultMessage: 'Data view does not contain any geospatial fields',
|
||||
})
|
||||
|
@ -116,9 +117,9 @@ export function GeoIndexPatternSelect(props: Props) {
|
|||
<>
|
||||
{_renderNoIndexPatternWarning()}
|
||||
|
||||
<EuiFormRow label={getDataViewLabel()} isInvalid={!hasGeoFields} error={error}>
|
||||
<EuiFormRow label={getDataViewLabel()} isInvalid={isDataViewInvalid} error={error}>
|
||||
<IndexPatternSelect
|
||||
isInvalid={!hasGeoFields}
|
||||
isInvalid={isDataViewInvalid}
|
||||
isDisabled={noDataViews}
|
||||
indexPatternId={props.dataView?.id ? props.dataView.id : ''}
|
||||
onChange={_onIndexPatternSelect}
|
||||
|
|
|
@ -118,6 +118,7 @@ export class AddLayerPanel extends Component<Props, State> {
|
|||
disabled={isDisabled || isLoading}
|
||||
isLoading={isLoading}
|
||||
onClick={addLayersAndClose}
|
||||
iconSide="right"
|
||||
>
|
||||
{ADD_LAYER_STEP_SECONDARY_ACTION_BUTTON_LABEL}
|
||||
</EuiButton>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue