Skip to content

Commit 59a4aaa

Browse files
committed
Merge branch 'master' into igr/fix-button-loading-spinner
2 parents 7ac7e8b + a05b3cf commit 59a4aaa

19 files changed

Lines changed: 544 additions & 152 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@
235235
"@loaders.gl/gis": "4.3.2",
236236
"@loaders.gl/schema": "4.3.2",
237237
"@loaders.gl/wkt": "4.3.2",
238+
"@loaders.gl/wms": "4.3.2",
238239
"@luma.gl/constants": "8.5.21",
239240
"@luma.gl/core": "8.5.21",
240241
"@luma.gl/experimental": "8.5.21",

src/components/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"@kepler.gl/utils": "3.1.8",
5555
"@loaders.gl/mvt": "^4.3.2",
5656
"@loaders.gl/pmtiles": "^4.3.2",
57+
"@loaders.gl/wms": "4.3.2",
5758
"@mapbox/mapbox-sdk": "^0.15.3",
5859
"@nebula.gl/edit-modes": "1.0.2-alpha.1",
5960
"@tippyjs/react": "^4.2.0",

src/components/src/modals/export-data-modal.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ const ExportDataModalFactory = () => {
9494
const showTiledDatasetWarning = Object.keys(datasets).some(datasetId => {
9595
return (
9696
(datasets[datasetId].type === DatasetType.VECTOR_TILE ||
97-
datasets[datasetId].type === DatasetType.RASTER_TILE) &&
97+
datasets[datasetId].type === DatasetType.RASTER_TILE ||
98+
datasets[datasetId].type === DatasetType.WMS_TILE) &&
9899
(selectedDataset === datasetId || exportAllDatasets)
99100
);
100101
});

src/components/src/modals/tilesets-modals/common.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: MIT
22
// Copyright contributors to the kepler.gl project
33

4+
import type {WMSCapabilities} from '@loaders.gl/wms';
5+
46
import type {VectorTileMetadata} from '@kepler.gl/table';
57
import type {StacTypes} from '@kepler.gl/types';
68

@@ -11,7 +13,7 @@ export type DatasetCreationAttributes = {
1113
};
1214

1315
export type MetaResponse = {
14-
metadata?: VectorTileMetadata | StacTypes.CompleteSTACObject | null;
16+
metadata?: VectorTileMetadata | StacTypes.CompleteSTACObject | WMSCapabilities | null;
1517
dataset?: DatasetCreationAttributes | null;
1618
loading?: boolean;
1719
error?: Error | null;

src/components/src/modals/tilesets-modals/load-tileset.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import JSONPretty from 'react-json-pretty';
77
import {AutoSizer} from 'react-virtualized';
88
import styled from 'styled-components';
99

10-
import {VectorTileIcon, RasterTileIcon} from '@kepler.gl/layers';
10+
import {VectorTileIcon, RasterTileIcon, WMSLayerIcon} from '@kepler.gl/layers';
1111
import {getError, getApplicationConfig} from '@kepler.gl/utils';
1212

1313
import {MetaResponse} from './common';
@@ -16,7 +16,6 @@ import TilesetIcon from './tileset-icon';
1616
import TilesetVectorForm from './tileset-vector-form';
1717
import TilesetRasterForm from './tileset-raster-form';
1818

19-
import WMSLayerIcon from 'src/layers/src/wms-layer/wms-layer-icon';
2019
import TilesetWMSForm from './tileset-wms-form';
2120

2221
const WIDTH_ICON = '70px';
@@ -165,7 +164,6 @@ function LoadTilesetTabFactory() {
165164
</TilesetTypeContainer>
166165
<div>
167166
<CurrentForm setResponse={setResponse} />
168-
{error && <div>{getError(error)}</div>}
169167
</div>
170168
</div>
171169
<MetaContainer>

src/components/src/modals/tilesets-modals/tileset-wms-form.tsx

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33

44
import React, {useCallback, useEffect, useState} from 'react';
55
import styled from 'styled-components';
6-
import {WMSCapabilities, WMSCapabilitiesLoader} from '@loaders.gl/wms';
7-
import {load} from '@loaders.gl/core';
6+
import {WMSCapabilities} from '@loaders.gl/wms';
7+
8+
import {validateUrl} from '@kepler.gl/common-utils';
9+
import {DatasetType, REMOTE_TILE, RemoteTileFormat, WMSDatasetMetadata} from '@kepler.gl/constants';
10+
import {getWMSCapabilities, wmsCapabilitiesToDatasetMetadata} from '@kepler.gl/table';
811

9-
import {DatasetType, REMOTE_TILE, RemoteTileFormat} from '@kepler.gl/constants';
1012
import {MetaResponse} from './common';
1113
import {InputLight} from '../../common';
1214

1315
const TilesetInputContainer = styled.div`
1416
display: grid;
15-
grid-template-rows: repeat(2, 1fr);
17+
grid-template-rows: repeat(3, auto);
1618
row-gap: 18px;
1719
font-size: 12px;
1820
`;
@@ -22,18 +24,34 @@ const TilesetInputDescription = styled.div`
2224
color: ${props => props.theme.AZURE200};
2325
font-size: 11px;
2426
`;
27+
28+
const ExampleUrlsContainer = styled.div`
29+
text-align: left;
30+
color: ${props => props.theme.AZURE200};
31+
font-size: 11px;
32+
33+
.example-url {
34+
margin-top: 8px;
35+
display: block;
36+
}
37+
`;
38+
2539
type WMSTileFormProps = {
2640
setResponse: (response: MetaResponse) => void;
2741
};
2842

43+
type WMSData = {
44+
metadata: WMSCapabilities | null;
45+
layers: WMSDatasetMetadata['layers'];
46+
version: string;
47+
};
48+
2949
const TilesetWMSForm: React.FC<WMSTileFormProps> = ({setResponse}) => {
3050
const [layerName, setLayerName] = useState<string>('');
3151
const [wmsUrl, setWmsUrl] = useState<string>('');
32-
const [metadata, setMetadata] = useState<any>(null);
3352
const [loading, setLoading] = useState<boolean>(false);
3453
const [error, setError] = useState<Error | null>(null);
35-
const [availableLayers, setAvailableLayers] = useState<{name: string; title: string}[]>([]);
36-
const [wmsVersion, setWmsVersion] = useState<string>('1.3.0');
54+
const [wmsData, setWMSData] = useState<WMSData | null>(null);
3755

3856
const onLayerNameChange = useCallback(
3957
(event: React.ChangeEvent<HTMLInputElement>) => {
@@ -49,47 +67,34 @@ const TilesetWMSForm: React.FC<WMSTileFormProps> = ({setResponse}) => {
4967
const newWmsUrl = event.target.value;
5068
setWmsUrl(newWmsUrl);
5169

70+
if (!validateUrl(newWmsUrl)) {
71+
setWMSData(null);
72+
return;
73+
}
74+
5275
// Fetch WMS GetCapabilities
5376
try {
5477
setLoading(true);
5578
setError(null);
56-
const data = (await load(
57-
`${newWmsUrl}?service=WMS&request=GetCapabilities`,
58-
WMSCapabilitiesLoader
59-
)) as WMSCapabilities;
79+
80+
const data = await getWMSCapabilities(newWmsUrl);
81+
82+
const datasetMetadata = wmsCapabilitiesToDatasetMetadata(data);
6083

6184
// Extract name or title from GetCapabilities response
62-
const serviceTitle = data?.title;
85+
const serviceTitle = data?.title || data?.name;
6386
if (serviceTitle && !layerName) {
6487
setLayerName(serviceTitle);
6588
}
6689

67-
// Flatten layers if they are nested
68-
const layers = data.layers.flatMap(layer => {
69-
if (layer.layers && layer.layers.length > 0) {
70-
return layer.layers;
71-
}
72-
return layer;
90+
setWMSData({
91+
metadata: data,
92+
layers: datasetMetadata.layers,
93+
version: datasetMetadata.version
7394
});
74-
75-
if (Array.isArray(layers)) {
76-
const layerOptions = layers.map((layer: any) => ({
77-
name: layer.name,
78-
title: layer.title || layer.name
79-
}));
80-
setAvailableLayers(layerOptions);
81-
} else {
82-
setAvailableLayers([]);
83-
}
84-
85-
// Set WMS version
86-
const version = data.version || '1.3.0';
87-
setWmsVersion(version);
88-
89-
setMetadata(data);
9095
} catch (err) {
9196
setError(err instanceof Error ? err : new Error('Unknown error'));
92-
setMetadata(null);
97+
setWMSData(null);
9398
} finally {
9499
setLoading(false);
95100
}
@@ -107,12 +112,12 @@ const TilesetWMSForm: React.FC<WMSTileFormProps> = ({setResponse}) => {
107112
remoteTileFormat: RemoteTileFormat.WMS,
108113
tilesetDataUrl: wmsUrl,
109114
tilesetMetadataUrl: `${wmsUrl}?service=WMS&request=GetCapabilities`,
110-
layers: availableLayers,
111-
wmsVersion: wmsVersion
115+
layers: wmsData?.layers || [],
116+
wmsVersion: wmsData?.version || '1.3.0'
112117
}
113118
};
114119
setResponse({
115-
metadata,
120+
metadata: wmsData?.metadata ?? null,
116121
dataset,
117122
loading,
118123
error
@@ -125,7 +130,7 @@ const TilesetWMSForm: React.FC<WMSTileFormProps> = ({setResponse}) => {
125130
error
126131
});
127132
}
128-
}, [setResponse, layerName, wmsUrl, metadata, loading, error, availableLayers, wmsVersion]);
133+
}, [setResponse, layerName, wmsUrl, wmsData, loading, error]);
129134

130135
return (
131136
<TilesetInputContainer>
@@ -148,6 +153,18 @@ const TilesetWMSForm: React.FC<WMSTileFormProps> = ({setResponse}) => {
148153
/>
149154
<TilesetInputDescription>Provide a valid WMS service URL.</TilesetInputDescription>
150155
</div>
156+
<div>
157+
<TilesetInputDescription>For example, try a public WMS URL:</TilesetInputDescription>
158+
<ExampleUrlsContainer>
159+
<div className="example-url">• https://ows.terrestris.de/osm/service</div>
160+
<div className="example-url">
161+
• https://opengeo.ncep.noaa.gov/geoserver/conus/conus_cref_qcd/ows
162+
</div>
163+
<div className="example-url">
164+
• https://gibs.earthdata.nasa.gov/wms/epsg4326/best/wms.cgi
165+
</div>
166+
</ExampleUrlsContainer>
167+
</div>
151168
</TilesetInputContainer>
152169
);
153170
};

src/components/src/side-panel/layer-panel/layer-configurator.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,14 +1032,10 @@ export default function LayerConfiguratorFactory(
10321032
}) {
10331033
return (
10341034
<StyledLayerVisualConfigurator>
1035-
<LayerConfigGroup label={'layer.wms'} collapsible>
1036-
<VisConfigSlider {...layer.visConfigSettings.opacity} {...visConfiguratorProps} />
1037-
<VisConfigSwitch
1038-
label={'layerVisConfigs.transparentBackground'}
1039-
{...layer.visConfigSettings.transparent}
1040-
{...visConfiguratorProps}
1041-
property="transparent"
1042-
/>
1035+
<LayerConfigGroup label={'layer.service'}>
1036+
<PanelLabel>
1037+
<FormattedMessage id={'layer.layer'} />
1038+
</PanelLabel>
10431039
<ItemSelector
10441040
selectedItems={layer.config.visConfig.wmsLayer}
10451041
options={layerChannelConfigProps.dataset.metadata.layers}
@@ -1067,6 +1063,15 @@ export default function LayerConfiguratorFactory(
10671063
}}
10681064
/>
10691065
</LayerConfigGroup>
1066+
<LayerConfigGroup label={'layer.appearance'}>
1067+
<VisConfigSlider {...layer.visConfigSettings.opacity} {...visConfiguratorProps} />
1068+
<VisConfigSwitch
1069+
label={'layerVisConfigs.transparentBackground'}
1070+
{...layer.visConfigSettings.transparent}
1071+
{...visConfiguratorProps}
1072+
property="transparent"
1073+
/>
1074+
</LayerConfigGroup>
10701075
</StyledLayerVisualConfigurator>
10711076
);
10721077
}

src/constants/src/dataset.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,12 @@ export type RasterTileMetadataSourceType = {
6666
*/
6767
export type RasterTileDatasetMetadata = (RasterTileLocalMetadata | RasterTileRemoteMetadata) &
6868
RasterTileMetadataSourceType;
69+
70+
export type WMSDatasetMetadata = {
71+
type: typeof REMOTE_TILE;
72+
remoteTileFormat: RemoteTileFormat.WMS;
73+
tilesetDataUrl: string;
74+
tilesetMetadataUrl: string;
75+
version: string;
76+
layers: {name: string; title: string; boundingBox: number[] | null}[];
77+
};

src/constants/src/layers.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,5 @@ export const EDITOR_AVAILABLE_LAYERS: string[] = [
564564
LAYER_TYPES.arc,
565565
LAYER_TYPES.line,
566566
LAYER_TYPES.hexagonId,
567-
LAYER_TYPES.geojson,
568-
LAYER_TYPES.wms
567+
LAYER_TYPES.geojson
569568
];

src/deckgl-layers/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@
3838
"@kepler.gl/constants": "3.1.8",
3939
"@kepler.gl/types": "3.1.8",
4040
"@kepler.gl/utils": "3.1.8",
41+
"@loaders.gl/wms": "4.3.2",
4142
"@luma.gl/constants": "^8.5.20",
4243
"@luma.gl/core": "^8.5.20",
4344
"@mapbox/geo-viewport": "^0.4.1",
4445
"@mapbox/vector-tile": "^1.3.1",
46+
"@math.gl/web-mercator": "^3.6.2",
4547
"@types/d3-array": "^2.8.0",
4648
"@types/geojson": "^7946.0.8",
4749
"@types/lodash": "4.17.5",

0 commit comments

Comments
 (0)