From 7a0cae91f80d64cf7f84380a42ed2dc97f0aba6e Mon Sep 17 00:00:00 2001 From: Thomas Aulinger Date: Tue, 10 Sep 2024 13:04:51 +0200 Subject: [PATCH] ContextMenu: display parcel number when available (#2539) * add i18n for parcel * handle "parcel" property * add "parcel" property * display parcel number when available # Conflicts: # test/modules/map/i18n/contextMenu.provider.test.js --- .../contextMenu/MapContextMenuContent.js | 7 ++- src/modules/map/i18n/contextMenu.provider.js | 2 + src/services/AdministrationService.js | 1 + .../provider/administration.provider.js | 5 +- .../contextMenu/MapContextMenuContent.test.js | 47 +++++++++++++++---- .../map/i18n/contextMenu.provider.test.js | 6 ++- .../provider/administration.provider.test.js | 25 ++++++++-- 7 files changed, 76 insertions(+), 17 deletions(-) diff --git a/src/modules/map/components/contextMenu/MapContextMenuContent.js b/src/modules/map/components/contextMenu/MapContextMenuContent.js index 7e3a39082a..ddc2dbe367 100644 --- a/src/modules/map/components/contextMenu/MapContextMenuContent.js +++ b/src/modules/map/components/contextMenu/MapContextMenuContent.js @@ -109,7 +109,7 @@ export class MapContextMenuContent extends MvuElement { const { coordinate, elevation, - administration: { community, district } + administration: { community, district, parcel } } = model; const translate = (key) => this._translationService.translate(key); @@ -148,6 +148,11 @@ export class MapContextMenuContent extends MvuElement {
  • ${translate('map_contextMenuContent_district_label')}${district || '-'}
  • + ${parcel + ? html`
  • + ${translate('map_contextMenuContent_parcel_label')}${parcel || '-'} +
  • ` + : nothing} ${stringifiedCoords.map((strCoord) => html`
  • ${strCoord}
  • `)}
  • ${translate('map_contextMenuContent_elevation_label')}${elevation || '-'} diff --git a/src/modules/map/i18n/contextMenu.provider.js b/src/modules/map/i18n/contextMenu.provider.js index 535e5b0058..f4912725e2 100644 --- a/src/modules/map/i18n/contextMenu.provider.js +++ b/src/modules/map/i18n/contextMenu.provider.js @@ -8,6 +8,7 @@ export const provide = (lang) => { map_contextMenuContent_elevation_label: 'Elev.', map_contextMenuContent_community_label: 'Community', map_contextMenuContent_district_label: 'District', + map_contextMenuContent_parcel_label: 'Parcel', map_contextMenuContent_copy_icon: 'Copy to clipboard', map_contextMenuContent_clipboard_error: '"Copy to clipboard" is not available', map_contextMenuContent_clipboard_success: 'was copied to clipboard' @@ -21,6 +22,7 @@ export const provide = (lang) => { map_contextMenuContent_elevation_label: 'Höhe', map_contextMenuContent_community_label: 'Gemeinde', map_contextMenuContent_district_label: 'Gemarkung', + map_contextMenuContent_parcel_label: 'Flurstück', map_contextMenuContent_copy_icon: 'In die Zwischenablage kopieren', map_contextMenuContent_clipboard_error: '"In die Zwischenablage kopieren" steht nicht zur Verfügung', map_contextMenuContent_clipboard_success: 'wurde in die Zwischenablage kopiert' diff --git a/src/services/AdministrationService.js b/src/services/AdministrationService.js index 0153a3e3c0..917903dfb7 100644 --- a/src/services/AdministrationService.js +++ b/src/services/AdministrationService.js @@ -18,6 +18,7 @@ import { isCoordinate } from '../utils/checks'; * @typedef {Object} Administration * @property {string} community The community at the delivered coordinate. * @property {string} district The district at the delivered coordinate. + * @property {string|null} parcel The parcel number at the delivered coordinate. */ /** diff --git a/src/services/provider/administration.provider.js b/src/services/provider/administration.provider.js index 991bae9751..2bb7e52d9b 100644 --- a/src/services/provider/administration.provider.js +++ b/src/services/provider/administration.provider.js @@ -17,10 +17,11 @@ export const loadBvvAdministration = async (coordinate3857) => { switch (result.status) { case 200: { - const { gemeinde: community, gemarkung: district } = await result.json(); + const { gemeinde: community, gemarkung: district, flstBezeichnung: parcel } = await result.json(); return { community, - district + district, + parcel }; } case 404: { diff --git a/test/modules/map/components/contextMenu/MapContextMenuContent.test.js b/test/modules/map/components/contextMenu/MapContextMenuContent.test.js index 6bdb295fd7..b19e079476 100644 --- a/test/modules/map/components/contextMenu/MapContextMenuContent.test.js +++ b/test/modules/map/components/contextMenu/MapContextMenuContent.test.js @@ -59,7 +59,7 @@ describe('OlMapContextMenuContent', () => { }); describe('when screen coordinate available', () => { - it('renders the content', async () => { + it('renders the content when parcel is not available', async () => { const coordinateMock = [1000, 2000]; const stringifiedCoord = 'stringified coordinate'; const getCoordinateRepresentationsMock = spyOn(mapServiceMock, 'getCoordinateRepresentations').and.returnValue([ @@ -70,24 +70,24 @@ describe('OlMapContextMenuContent', () => { const elevationMock = spyOn(elevationServiceMock, 'getElevation').withArgs(coordinateMock).and.returnValue(42); const administrationMock = spyOn(administrationServiceMock, 'getAdministration') .withArgs(coordinateMock) - .and.returnValue({ community: 'LDBV', district: 'Ref42' }); + .and.returnValue({ community: 'LDBV', district: 'Ref42', parcel: null }); const element = await setup(); element.coordinate = coordinateMock; + await TestUtils.timeout(); expect(element.shadowRoot.querySelector('.container')).toBeTruthy(); expect(element.shadowRoot.querySelector('.content')).toBeTruthy(); + expect(element.shadowRoot.querySelectorAll('.label')).toHaveSize(4); expect(element.shadowRoot.querySelectorAll('.label')[0].innerText).toBe('map_contextMenuContent_community_label'); expect(element.shadowRoot.querySelectorAll('.label')[1].innerText).toBe('map_contextMenuContent_district_label'); expect(element.shadowRoot.querySelectorAll('.label')[2].innerText).toBe(GlobalCoordinateRepresentations.WGS84.label); expect(element.shadowRoot.querySelectorAll('.label')[3].innerText).toBe('map_contextMenuContent_elevation_label'); - window.requestAnimationFrame(() => { - expect(element.shadowRoot.querySelectorAll('.coordinate')[0].innerText).toEqual('LDBV'); - expect(element.shadowRoot.querySelectorAll('.coordinate')[1].innerText).toEqual('Ref42'); - expect(element.shadowRoot.querySelectorAll('.coordinate')[2].innerText).toBe(stringifiedCoord); - expect(element.shadowRoot.querySelectorAll('.coordinate')[3].innerText).toEqual('42 (m)'); - }); + expect(element.shadowRoot.querySelectorAll('.coordinate')[0].innerText).toEqual('LDBV'); + expect(element.shadowRoot.querySelectorAll('.coordinate')[1].innerText).toEqual('Ref42'); + expect(element.shadowRoot.querySelectorAll('.coordinate')[2].innerText).toBe(stringifiedCoord); + expect(element.shadowRoot.querySelectorAll('.coordinate')[3].innerText).toEqual('42 (m)'); const copyIcon = element.shadowRoot.querySelector(Icon.tag); expect(copyIcon).toBeTruthy(); @@ -108,6 +108,37 @@ describe('OlMapContextMenuContent', () => { expect(element.shadowRoot.querySelectorAll('ba-routing-chip')[0].coordinate).toBe(coordinateMock); }); + it('renders the content when parcel is available', async () => { + const coordinateMock = [1000, 2000]; + const stringifiedCoord = 'stringified coordinate'; + spyOn(mapServiceMock, 'getCoordinateRepresentations').and.returnValue([GlobalCoordinateRepresentations.WGS84]); + spyOn(mapServiceMock, 'getSrid').and.returnValue(3857); + spyOn(coordinateServiceMock, 'stringify').and.returnValue(stringifiedCoord); + spyOn(elevationServiceMock, 'getElevation').withArgs(coordinateMock).and.returnValue(42); + spyOn(administrationServiceMock, 'getAdministration') + .withArgs(coordinateMock) + .and.returnValue({ community: 'LDBV', district: 'Ref42', parcel: '12345' }); + const element = await setup(); + + element.coordinate = coordinateMock; + + await TestUtils.timeout(); + expect(element.shadowRoot.querySelector('.container')).toBeTruthy(); + expect(element.shadowRoot.querySelector('.content')).toBeTruthy(); + expect(element.shadowRoot.querySelectorAll('.label')).toHaveSize(5); + expect(element.shadowRoot.querySelectorAll('.label')[0].innerText).toBe('map_contextMenuContent_community_label'); + expect(element.shadowRoot.querySelectorAll('.label')[1].innerText).toBe('map_contextMenuContent_district_label'); + expect(element.shadowRoot.querySelectorAll('.label')[2].innerText).toBe('map_contextMenuContent_parcel_label'); + expect(element.shadowRoot.querySelectorAll('.label')[3].innerText).toBe(GlobalCoordinateRepresentations.WGS84.label); + expect(element.shadowRoot.querySelectorAll('.label')[4].innerText).toBe('map_contextMenuContent_elevation_label'); + + expect(element.shadowRoot.querySelectorAll('.coordinate')[0].innerText).toEqual('LDBV'); + expect(element.shadowRoot.querySelectorAll('.coordinate')[1].innerText).toEqual('Ref42'); + expect(element.shadowRoot.querySelectorAll('.coordinate')[2].innerText).toEqual('12345'); + expect(element.shadowRoot.querySelectorAll('.coordinate')[3].innerText).toBe(stringifiedCoord); + expect(element.shadowRoot.querySelectorAll('.coordinate')[4].innerText).toEqual('42 (m)'); + }); + it('renders the content when AdministrationService returns null', async () => { spyOn(mapServiceMock, 'getCoordinateRepresentations').and.returnValue([{ label: 'code42', code: 42 }]); spyOn(administrationServiceMock, 'getAdministration').and.resolveTo(null); diff --git a/test/modules/map/i18n/contextMenu.provider.test.js b/test/modules/map/i18n/contextMenu.provider.test.js index 3eb18191bd..86895981a6 100644 --- a/test/modules/map/i18n/contextMenu.provider.test.js +++ b/test/modules/map/i18n/contextMenu.provider.test.js @@ -9,6 +9,7 @@ describe('i18n for context menu', () => { expect(map.map_contextMenuContent_elevation_label).toBe('Elev.'); expect(map.map_contextMenuContent_community_label).toBe('Community'); expect(map.map_contextMenuContent_district_label).toBe('District'); + expect(map.map_contextMenuContent_parcel_label).toBe('Parcel'); expect(map.map_contextMenuContent_copy_icon).toBe('Copy to clipboard'); expect(map.map_contextMenuContent_clipboard_error).toBe('"Copy to clipboard" is not available'); expect(map.map_contextMenuContent_clipboard_success).toBe('was copied to clipboard'); @@ -22,13 +23,14 @@ describe('i18n for context menu', () => { expect(map.map_contextMenuContent_elevation_label).toBe('Höhe'); expect(map.map_contextMenuContent_community_label).toBe('Gemeinde'); expect(map.map_contextMenuContent_district_label).toBe('Gemarkung'); + expect(map.map_contextMenuContent_parcel_label).toBe('Flurstück'); expect(map.map_contextMenuContent_copy_icon).toBe('In die Zwischenablage kopieren'); expect(map.map_contextMenuContent_clipboard_error).toBe('"In die Zwischenablage kopieren" steht nicht zur Verfügung'); expect(map.map_contextMenuContent_clipboard_success).toBe('wurde in die Zwischenablage kopiert'); }); - it('have the expected amount of translations', () => { - const expectedSize = 8; + it('contains the expected amount of entries', () => { + const expectedSize = 9; const deMap = provide('de'); const enMap = provide('en'); diff --git a/test/service/provider/administration.provider.test.js b/test/service/provider/administration.provider.test.js index 81c2fee7b4..93d466ef3c 100644 --- a/test/service/provider/administration.provider.test.js +++ b/test/service/provider/administration.provider.test.js @@ -17,9 +17,9 @@ describe('Administration provider', () => { const coordinateMock = [21, 42]; - it('loads an Administration object', async () => { + it('loads an Administration object without a parcel', async () => { const backendUrl = 'https://backend.url'; - const administrationMock = { gemeinde: 'gemeinde', gemarkung: 'gemarkung' }; + const administrationMock = { gemeinde: 'gemeinde', gemarkung: 'gemarkung', flstBezeichnung: null }; const configServiceSpy = spyOn(configService, 'getValueAsPath').withArgs('BACKEND_URL').and.returnValue(backendUrl); const httpServiceSpy = spyOn(httpService, 'get').and.returnValue(Promise.resolve(new Response(JSON.stringify(administrationMock)))); @@ -27,9 +27,26 @@ describe('Administration provider', () => { expect(configServiceSpy).toHaveBeenCalled(); expect(httpServiceSpy).toHaveBeenCalled(); - expect(administration.community).toEqual(administrationMock.gemeinde); - expect(administration.district).toEqual(administrationMock.gemarkung); + expect(administration.community).toBe(administrationMock.gemeinde); + expect(administration.district).toBe(administrationMock.gemarkung); + expect(administration.parcel).toBeNull(); }); + + it('loads an Administration object containing a parcel', async () => { + const backendUrl = 'https://backend.url'; + const administrationMock = { gemeinde: 'gemeinde', gemarkung: 'gemarkung', flstBezeichnung: '12345' }; + const configServiceSpy = spyOn(configService, 'getValueAsPath').withArgs('BACKEND_URL').and.returnValue(backendUrl); + const httpServiceSpy = spyOn(httpService, 'get').and.returnValue(Promise.resolve(new Response(JSON.stringify(administrationMock)))); + + const administration = await loadBvvAdministration(coordinateMock); + + expect(configServiceSpy).toHaveBeenCalled(); + expect(httpServiceSpy).toHaveBeenCalled(); + expect(administration.community).toBe(administrationMock.gemeinde); + expect(administration.district).toBe(administrationMock.gemarkung); + expect(administration.parcel).toBe(administrationMock.flstBezeichnung); + }); + it('return null when for status 404', async () => { const backendUrl = 'https://backend.url'; const configServiceSpy = spyOn(configService, 'getValueAsPath').withArgs('BACKEND_URL').and.returnValue(backendUrl);