Skip to content

Commit b7beb6e

Browse files
authored
Merge pull request #3508 from terrestris/refactor-add-wms
Refactor AddWmsPanel component
2 parents c0066c7 + 3063c98 commit b7beb6e

5 files changed

Lines changed: 239 additions & 328 deletions

File tree

src/Container/AddWmsPanel/AddWmsLayerEntry/AddWmsLayerEntry.tsx

Lines changed: 71 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -4,133 +4,111 @@ import { faCopyright, faInfo } from '@fortawesome/free-solid-svg-icons';
44
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
55
import { WmsLayer } from '@terrestris/react-util/dist/Util/typeUtils';
66
import { Checkbox, Tooltip } from 'antd';
7+
import { FrameState } from 'ol/Map';
78
import { Attribution as OlAttribution } from 'ol/source/Source';
8-
import * as React from 'react';
9+
import React, { useEffect, useState } from 'react';
910

10-
interface AddWmsLayerEntryProps {
11+
export type AddWmsLayerEntryProps = {
12+
/**
13+
* Object containing layer information
14+
*/
15+
wmsLayer: WmsLayer;
1116
/**
1217
* Function returning a span with the textual representation of this layer
1318
* Default: Title of the layer and its abstract (if available)
1419
*/
15-
layerTextTemplateFn: (layer: WmsLayer) => React.ReactNode;
20+
layerTextTemplateFn?: (layer: WmsLayer) => JSX.Element;
1621
/**
1722
* Optional text to be shown in Tooltip for a layer that can be queried
1823
*/
19-
layerQueryableText: string;
24+
layerQueryableText?: string;
2025
/**
2126
* ARIA label for the icon which indicates that the layer has copyright / attribution
2227
* information. This label increases the accessibility of the generated HTML. If not
2328
* set explicitly, a generic English label will be added. Make sure to translate this
2429
* to the page language if needed.
2530
*/
26-
ariaLabelCopyright: string;
31+
ariaLabelCopyright?: string;
2732
/**
2833
* ARIA label for the icon which indicates that the layer is queryable. This label
2934
* increases the accessibility of the generated HTML. If not set explicitly, a generic
3035
* English label will be added. Make sure to translate this to the page language if
3136
* needed.
3237
*/
33-
ariaLabelQueryable: string;
34-
/**
35-
* Object containing layer information
36-
*/
37-
wmsLayer: WmsLayer;
38-
}
39-
40-
interface AddWmsLayerEntryState {
41-
copyright: OlAttribution | null;
42-
queryable: boolean;
43-
}
38+
ariaLabelQueryable?: string;
39+
};
4440

4541
/**
4642
* Class representing a layer parsed from capabilities document.
47-
* This componment is used in AddWmsPanel
43+
* This component is used in AddWmsPanel
4844
*
49-
* @class AddWmsLayerEntry
50-
* @extends React.Component
5145
*/
52-
export class AddWmsLayerEntry extends React.Component<AddWmsLayerEntryProps, AddWmsLayerEntryState> {
53-
54-
/**
55-
* The defaultProps.
56-
*/
57-
static defaultProps = {
58-
layerQueryableText: 'Layer is queryable',
59-
ariaLabelCopyright: 'Icon indicating that attribution information for layer is available',
60-
ariaLabelQueryable: 'Icon indicating that the layer is queryable',
61-
layerTextTemplateFn: (wmsLayer: WmsLayer) => {
62-
const title = wmsLayer.get('title');
63-
const abstract = wmsLayer.get('abstract');
64-
return abstract ?
65-
<span>{`${title} - ${abstract}:`}</span> :
66-
<span>{`${title}`}</span>;
67-
}
68-
};
69-
70-
/**
71-
* Create the AddWmsLayerEntry.
72-
*
73-
* @constructs AddWmsLayerEntry
74-
*/
75-
constructor(props: AddWmsLayerEntryProps) {
76-
super(props);
77-
// TODO: getAttributions is not @api and returns a function in v6.5
78-
this.state = {
79-
copyright: props.wmsLayer.getSource()?.getAttributions() || null,
80-
queryable: props.wmsLayer.get('queryable')
81-
};
46+
export const AddWmsLayerEntry: React.FC<AddWmsLayerEntryProps> = ({
47+
wmsLayer,
48+
layerQueryableText = 'Layer is queryable',
49+
ariaLabelCopyright = 'Icon indicating that attribution information for layer is available',
50+
ariaLabelQueryable = 'Icon indicating that the layer is queryable',
51+
layerTextTemplateFn = (layer: WmsLayer) => {
52+
const title = layer.get('title');
53+
const abstract = layer.get('abstract');
54+
return abstract ?
55+
<span>{`${title} - ${abstract}:`}</span> :
56+
<span>{`${title}`}</span>;
8257
}
58+
}) => {
8359

84-
/**
85-
* The render function
86-
*/
87-
render() {
88-
const {
89-
wmsLayer,
90-
layerTextTemplateFn,
91-
layerQueryableText,
92-
ariaLabelCopyright,
93-
ariaLabelQueryable
94-
} = this.props;
95-
96-
const {
97-
copyright,
98-
queryable
99-
} = this.state;
60+
const [copyright, setCopyright] = useState<string | null>(null);
61+
const [queryable, setQueryable] = useState<boolean>();
10062

101-
const title = wmsLayer.get('title');
102-
const layerTextSpan = layerTextTemplateFn(wmsLayer);
63+
useEffect(() => {
64+
if (wmsLayer) {
65+
if (wmsLayer.getSource()?.getAttributions()) {
66+
const attributionsFn = wmsLayer.getSource()?.getAttributions() as OlAttribution;
67+
const attributions = (attributionsFn({} as FrameState));
68+
if (attributions?.length > 0) {
69+
if (Array.isArray(attributions)) {
70+
setCopyright(attributions.join(', '));
71+
} else {
72+
setCopyright(attributions);
73+
}
74+
}
75+
}
76+
setQueryable(!!wmsLayer.get('queryable'));
77+
}
78+
}, [wmsLayer]);
10379

104-
return (
105-
<Checkbox value={title} className="add-wms-layer-checkbox-line">
106-
<div className="add-wms-layer-entry">
107-
{layerTextSpan}
108-
{
109-
copyright ? (
80+
return (
81+
<Checkbox
82+
className="add-wms-layer-checkbox-line"
83+
value={wmsLayer.get('title')}
84+
>
85+
<div className="add-wms-layer-entry">
86+
{layerTextTemplateFn(wmsLayer)}
87+
{
88+
copyright && (
89+
<Tooltip title={copyright}>
11090
<FontAwesomeIcon
11191
className="add-wms-add-info-icon attribution-info"
11292
icon={faCopyright}
11393
aria-label={ariaLabelCopyright}
11494
/>
115-
)
116-
: null
117-
}
118-
{
119-
queryable ? (
120-
<Tooltip title={layerQueryableText}>
121-
<FontAwesomeIcon
122-
className="add-wms-add-info-icon queryable-info"
123-
icon={faInfo}
124-
aria-label={ariaLabelQueryable}
125-
/>
126-
</Tooltip>
127-
)
128-
: null
129-
}
130-
</div>
131-
</Checkbox>
132-
);
133-
}
134-
}
95+
</Tooltip>
96+
)
97+
}
98+
{
99+
queryable && (
100+
<Tooltip title={layerQueryableText}>
101+
<FontAwesomeIcon
102+
className="add-wms-add-info-icon queryable-info"
103+
icon={faInfo}
104+
aria-label={ariaLabelQueryable}
105+
/>
106+
</Tooltip>
107+
)
108+
}
109+
</div>
110+
</Checkbox >
111+
);
112+
};
135113

136114
export default AddWmsLayerEntry;

src/Container/AddWmsPanel/AddWmsPanel.example.md

Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,30 @@ An `AddWmsPanel` shows a list of the parsed layers and each checked layer (or th
66
import CapabilitiesUtil from '@terrestris/ol-util/dist/CapabilitiesUtil/CapabilitiesUtil';
77
import SimpleButton from '@terrestris/react-geo/dist/Button/SimpleButton/SimpleButton';
88
import AddWmsPanel from '@terrestris/react-geo/dist/Container/AddWmsPanel/AddWmsPanel';
9+
import MapContext from '@terrestris/react-util/dist/Context/MapContext/MapContext';
10+
import useMap from '@terrestris/react-util/dist/hooks/useMap';
11+
import MapComponent from '@terrestris/react-util/dist/Map/MapComponent/MapComponent';
12+
import { WmsLayer } from '@terrestris/react-util/dist/Util/typeUtils';
913
import OlLayerTile from 'ol/layer/Tile';
1014
import OlMap from 'ol/Map';
1115
import { fromLonLat } from 'ol/proj';
1216
import OlSourceOSM from 'ol/source/OSM';
1317
import OlView from 'ol/View';
14-
import * as React from 'react';
18+
import {
19+
useEffect,
20+
useState
21+
} from 'react';
1522

1623
// Please note: CORS headers must be set on server providing capabilities document. Otherwise proxy needed.
17-
const WMS_CAPABILITIES_URL = 'https://ows.terrestris.de/osm/service?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities';
24+
const CAPABILITIES_URL = 'https://ows.terrestris.de/osm/service?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities';
1825

19-
class AddWmsPanelExample extends React.Component {
26+
const AddWmsPanelExample = () => {
2027

21-
constructor(props) {
22-
super(props);
28+
const [map, setMap] = useState();
29+
const [wmsLayers, setWmsLayers] = useState();
2330

24-
this.mapDivId = `map-${Math.random()}`;
25-
26-
this.map = new OlMap({
31+
useEffect(() => {
32+
const olMap = new OlMap({
2733
layers: [
2834
new OlLayerTile({
2935
name: 'OSM',
@@ -35,64 +41,46 @@ class AddWmsPanelExample extends React.Component {
3541
zoom: 4
3642
})
3743
});
44+
setMap(olMap);
45+
}, []);
3846

39-
this.state = {
40-
layers: []
41-
};
42-
}
47+
const onClick = async () => {
48+
try {
49+
const capabilities = await CapabilitiesUtil.getWmsCapabilities(CAPABILITIES_URL);
50+
const capaLayers = await CapabilitiesUtil.getLayersFromWmsCapabilities(capabilities);
51+
if (capaLayers) {
52+
setWmsLayers(capaLayers);
53+
}
54+
} catch (error) {
55+
alert('Could not extract layers from capabilities document.')
56+
}
57+
};
4358

44-
componentDidMount() {
45-
this.map.setTarget(this.mapDivId);
59+
if (!map) {
60+
return null;
4661
}
4762

48-
onClick() {
49-
CapabilitiesUtil.getWmsCapabilities(WMS_CAPABILITIES_URL)
50-
.then(CapabilitiesUtil.getLayersFromWmsCapabilities)
51-
.then(layers => {
52-
this.setState({
53-
layers: layers
54-
});
55-
})
56-
.catch(() => alert('Could not parse capabilities document.'));
57-
}
58-
59-
render() {
60-
const {
61-
layers
62-
} = this.state;
63-
64-
return (
63+
return (
64+
<MapContext.Provider value={map}>
65+
<MapComponent
66+
map={map}
67+
style={{
68+
height: '400px'
69+
}}
70+
/>
6571
<div>
66-
<div
67-
id={this.mapDivId}
68-
style={{
69-
height: '400px'
70-
}}
72+
<SimpleButton
73+
onClick={onClick}
74+
>
75+
Fetch capabilities of OWS terrestris
76+
</SimpleButton>
77+
<AddWmsPanel
78+
wmsLayers={wmsLayers}
7179
/>
72-
<div>
73-
<SimpleButton
74-
onClick={this.onClick.bind(this)}
75-
>
76-
Fetch capabilities of OWS terrestris
77-
</SimpleButton>
78-
<AddWmsPanel
79-
style={{
80-
position: 'relative',
81-
display: 'flex',
82-
flexDirection: 'column'
83-
}}
84-
key="1"
85-
map={this.map}
86-
wmsLayers={layers}
87-
draggable={true}
88-
x={0}
89-
y={0}
90-
/>
91-
</div>
9280
</div>
93-
);
94-
}
95-
}
81+
</MapContext.Provider>
82+
);
83+
};
9684

9785
<AddWmsPanelExample />
9886
```

src/Container/AddWmsPanel/AddWmsPanel.less

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
flex-direction: column;
44

55
.ant-checkbox-group {
6-
flex: 1;
7-
height: 100%;
8-
overflow-y: auto;
6+
display: block;
7+
98
}
109

1110
.buttons {

0 commit comments

Comments
 (0)