Skip to content

Commit

Permalink
feat: use useProjFromEpsgIO hook
Browse files Browse the repository at this point in the history
BREAKING CHANGE: refactors CoordinateReferenceSystemCombo to use useProjFromEpsgIO for CCRS fetching
  • Loading branch information
ahennr authored and simonseyock committed May 6, 2024
1 parent 7dddfce commit 741851d
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 292 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,51 @@ This demonstrates the usage of the CoordinateReferenceSystemCombo.
import CoordinateReferenceSystemCombo from
'@terrestris/react-geo/dist/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo';
import { applyTransform } from 'ol/extent';
import MapComponent from '@terrestris/react-util/dist/Components/MapComponent/MapComponent';
import MapContext from '@terrestris/react-util/dist/Context/MapContext/MapContext';
import OlLayerTile from 'ol/layer/Tile';
import OlMap from 'ol/Map';
import {
fromLonLat,
get,
getTransform
} from 'ol/proj';
import { register } from 'ol/proj/proj4';
import OlSourceOSM from 'ol/source/OSM';
import OlView from 'ol/View';
import React, { useEffect, useState } from 'react';
import proj4 from 'proj4';
import * as React from 'react';
import { register } from 'ol/proj/proj4';

const predefinedCrsDefinitions = [{
code: '25832',
value: 'ETRS89 / UTM zone 32N',
proj4def: '+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs',
name: 'ETRS89 / UTM zone 32N',
proj4: '+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs',
bbox: [83.92, 6, 38.76, 12]
}, {
code: '31466',
value: 'DHDN / 3-degree Gauss-Kruger zone 2',
proj4def: '+proj=tmerc +lat_0=0 +lon_0=6 +k=1 +x_0=2500000 +y_0=0 +ellps=bessel ' +
name: 'DHDN / 3-degree Gauss-Kruger zone 2',
proj4: '+proj=tmerc +lat_0=0 +lon_0=6 +k=1 +x_0=2500000 +y_0=0 +ellps=bessel ' +
'+towgs84=598.1,73.7,418.2,0.202,0.045,-2.455,6.7 +units=m +no_defs',
bbox: [53.81, 5.86, 49.11, 7.5]
}, {
code: '31467',
value: 'DHDN / 3-degree Gauss-Kruger zone 3',
proj4def: '+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel ' +
name: 'DHDN / 3-degree Gauss-Kruger zone 3',
proj4: '+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel ' +
'+towgs84=598.1,73.7,418.2,0.202,0.045,-2.455,6.7 +units=m +no_defs',
bbox: [55.09, 7.5, 47.27, 10.51]
}, {
code: '4326',
value: 'WGS 84',
proj4def: '+proj=longlat +datum=WGS84 +no_defs',
name: 'WGS 84',
proj4: '+proj=longlat +datum=WGS84 +no_defs',
bbox: [90, -180, -90, 180]
}];

class CoordinateReferenceSystemComboExample extends React.Component {

constructor(props) {
const CoordinateReferenceSystemComboExample = () => {

super(props);

this.mapDivId = `map-${Math.random()}`;

this.map = new OlMap({
const [map, setMap] = useState();

useEffect(() => {
setMap(new OlMap({
layers: [
new OlLayerTile({
name: 'OSM',
Expand All @@ -60,13 +59,13 @@ class CoordinateReferenceSystemComboExample extends React.Component {
center: fromLonLat([37.40570, 8.81566]),
zoom: 4
})
});
}));

register(proj4);
}
}, []);

componentDidMount() {
this.map.setTarget(this.mapDivId);
if (!map) {
return null;
}

/**
Expand All @@ -76,20 +75,20 @@ class CoordinateReferenceSystemComboExample extends React.Component {
* original code of setProjection can be found here:
* https://openlayers.org/en/latest/examples/reprojection-by-code.html
*/
setProjection(crsObj) {
setProjection = function(crsObj) {
const {
code,
value,
proj4def,
name,
proj4: proj4str,
bbox
} = crsObj;

if (code === null || value === null || proj4def === null || bbox === null) {
if (code === null || name === null || proj4str === null || bbox === null) {
return;
}

const newProjCode = 'EPSG:' + code;
proj4.defs(newProjCode, proj4def);
proj4.defs(newProjCode, proj4str);

register(proj4);
const newProj = get(newProjCode);
Expand All @@ -102,53 +101,50 @@ class CoordinateReferenceSystemComboExample extends React.Component {
const newView = new OlView({
projection: newProj
});
this.map.setView(newView);
map.setView(newView);
newView.fit(extent);
}

render() {
return (
<div>
<div
id={this.mapDivId}
style={{
height: '400px'
}}
return (
<MapContext.Provider value={map}>
<MapComponent
map={map}
style={{
height: '400px'
}}
/>
<div className="example-block">
<span>
A <code>CoordinateReferenceSystemCombo</code> with autocomplete mode
where CRS are fetched from <a href="https://epsg.io/">epsg.io/</a>.
If a CRS is selected (prop <code>onSelect</code>), the projection is
used to perform client-side raster reprojection of OSM layer in map.
</span>

<br />

<CoordinateReferenceSystemCombo
emptyTextPlaceholderText="Type to fetch definitions dynamically"
onSelect={setProjection}
/>
</div>

<div className="example-block">
<span>
A <code>CoordinateReferenceSystemCombo</code> with predefined definitions
of four CRS. Selecting an option does not affect the map.
</span>

<div className="example-block">
<span>
A <code>CoordinateReferenceSystemCombo</code> with autocomplete mode
where CRS are fetched from <a href="https://epsg.io/">epsg.io/</a>.
If a CRS is selected (prop <code>onSelect</code>), the projection is
used to perform client-side raster reprojection of OSM layer in map.
</span>

<br />

<CoordinateReferenceSystemCombo
emptyTextPlaceholderText="Type to fetch definitions dynamically"
onSelect={this.setProjection.bind(this)}
/>
</div>

<div className="example-block">
<span>
A <code>CoordinateReferenceSystemCombo</code> with predefined definitions
of four CRS. Selecting an option does not affect the map.
</span>

<br />

{/* A CoordinateReferenceSystemCombo having predefinedCrsDefinitions*/}
<CoordinateReferenceSystemCombo
predefinedCrsDefinitions={predefinedCrsDefinitions}
onSelect={this.setProjection.bind(this)}
/>
</div>
<br />

{/* A CoordinateReferenceSystemCombo having predefinedCrsDefinitions*/}
<CoordinateReferenceSystemCombo
predefinedCrsDefinitions={predefinedCrsDefinitions}
onSelect={setProjection}
/>
</div>
);
}
</MapContext.Provider>
);
}

<CoordinateReferenceSystemComboExample />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import Logger from '@terrestris/base-util/dist/Logger';
import { actSetTimeout } from '@terrestris/react-util/dist/Util/rtlTestUtils';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { enableFetchMocks, FetchMock } from 'jest-fetch-mock';
import * as React from 'react';

import {
findAntdDropdownOptionByText,
queryAntdDropdownOption
} from '../../Util/antdTestQueries';
import { findAntdDropdownOptionByText, queryAntdDropdownOption } from '../../Util/antdTestQueries';
import CoordinateReferenceSystemCombo from '../CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo';

describe('<CoordinateReferenceSystemCombo />', () => {
Expand Down Expand Up @@ -108,51 +104,8 @@ describe('<CoordinateReferenceSystemCombo />', () => {
});
});

describe('error handling', () => {
it('logs error message', async () => {
const error = new Error('Peter');
(fetch as FetchMock).mockRejectOnce(error);

const loggerSpy = jest.spyOn(Logger, 'error');

render(<CoordinateReferenceSystemCombo />);
const combobox = screen.getByRole('combobox');
await userEvent.type(combobox, 'a');

await waitFor(() => {
expect(loggerSpy).toHaveBeenCalled();
});

expect(loggerSpy).toHaveBeenCalledWith('Error while requesting in CoordinateReferenceSystemCombo', error);

loggerSpy.mockRestore();
});
});

describe('option clicks are handled correctly', () => {

it('calls the onSelect callback with the correct value', async () => {
const onSelect = jest.fn();

render(<CoordinateReferenceSystemCombo onSelect={onSelect} />);

const combobox = screen.getByRole('combobox');

await userEvent.type(combobox, 'a');

const result = resultMock.results[0];
const expected = transformedResults[0];

const option = await findAntdDropdownOptionByText(`${result.name} (EPSG:${result.code})`);

// we have to use fireEvent directly instead of `userEvent.click()` because antd is in the way
fireEvent.click(option);

await waitFor(() => {
expect(onSelect).toBeCalledWith(expected);
});
});

it('sets the value of the combobox to the correct value', async () => {
const onSelect = jest.fn();

Expand Down
Loading

0 comments on commit 741851d

Please sign in to comment.