Skip to content

Commit

Permalink
Merge pull request #736 from geonetwork/external-geojson
Browse files Browse the repository at this point in the history
Datahub: Propose external viewer button for geojson files
  • Loading branch information
fgravin authored Dec 19, 2023
2 parents 19be416 + 387b474 commit f49cddd
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 49 deletions.
4 changes: 2 additions & 2 deletions conf/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ background_color = "#fdfbff"

# Optional; URL template enabling to open map layers in an external viewer; if set, displays a button next to the map's layer drop down
# The template must include the following placeholders, which allow the datahub to inject the correct values when adding a layer to a viewer:
# ${service_url}: URL of the OWS
# ${service_type}: Type of the OWS; currently supported WMS, WFS
# ${service_url}: URL of the OWS or geojson file
# ${service_type}: Type of the OWS or geojson file; currently supported WMS, WFS, GEOJSON
# ${layer_name}: Name of the layer
# Be careful to use englobing single quotes, if your template syntax includes JSON (with double quotes)
# Examples:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,61 +43,158 @@ describe('ExternalViewerButtonComponent', () => {
expect(component.externalViewer).toEqual(false)
})
})
describe('with mapConfig and WMS link', () => {
beforeEach(() => {
component.mapConfig = MAP_CONFIG_FIXTURE
component.link = {
url: new URL(
'http://example.com/ows?service=wms&request=getcapabilities'
),
name: 'layername',
type: 'service',
accessServiceProtocol: 'wms',
}
fixture.detectChanges()
})
it('sets externalViewer to display button to true', () => {
expect(component.externalViewer).toEqual(true)
describe('with mapConfig and valid external links', () => {
let buttonComponent: MockButtonComponent
let componentSpy
let windowSpy
const openMock = jest.fn().mockReturnThis()
const focusMock = jest.fn().mockReturnThis()
describe('with mapConfig and WMS link', () => {
beforeEach(() => {
component.mapConfig = MAP_CONFIG_FIXTURE
component.link = {
url: new URL(
'http://example.com/ows?service=wms&request=getcapabilities'
),
name: 'layername',
type: 'service',
accessServiceProtocol: 'wms',
}
fixture.detectChanges()
})
it('sets externalViewer to display button to true', () => {
expect(component.externalViewer).toEqual(true)
})
describe('click button', () => {
beforeEach(() => {
buttonComponent = fixture.debugElement.query(
By.directive(MockButtonComponent)
).componentInstance
componentSpy = jest.spyOn(component, 'openInExternalViewer')
windowSpy = jest
.spyOn(global, 'window', 'get')
.mockImplementation(() => ({
open: openMock,
focus: focusMock,
}))
buttonComponent.buttonClick.emit()
})

afterEach(() => {
componentSpy.mockRestore()
windowSpy.mockRestore()
})
it('calls openInExternalViewer', () => {
expect(component.openInExternalViewer).toHaveBeenCalled()
})
it('opens window in new tab with URL including WMS link params', () => {
expect(openMock).toHaveBeenCalledWith(
'https://example.com/myviewer/#/?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["layername"],"sources":[{"url":"http%3A%2F%2Fexample.com%2Fows%3Fservice%3Dwms%26request%3Dgetcapabilities","type":"wms"}]}]',
'_blank'
)
})
it('focuses window', () => {
expect(focusMock).toHaveBeenCalled()
})
})
})
describe('click button', () => {
let buttonComponent: MockButtonComponent
let componentSpy
let windowSpy
const openMock = jest.fn().mockReturnThis()
const focusMock = jest.fn().mockReturnThis()
describe('with mapConfig and WFS link', () => {
beforeEach(() => {
buttonComponent = fixture.debugElement.query(
By.directive(MockButtonComponent)
).componentInstance
componentSpy = jest.spyOn(component, 'openInExternalViewer')
windowSpy = jest
.spyOn(global, 'window', 'get')
.mockImplementation(() => ({
open: openMock,
focus: focusMock,
}))
buttonComponent.buttonClick.emit()
component.mapConfig = MAP_CONFIG_FIXTURE
component.link = {
url: new URL(
'http://example.com/ows?service=wfs&request=getcapabilities'
),
name: 'layername',
type: 'service',
accessServiceProtocol: 'wfs',
}
fixture.detectChanges()
})
it('sets externalViewer to display button to true', () => {
expect(component.externalViewer).toEqual(true)
})
describe('click button', () => {
beforeEach(() => {
buttonComponent = fixture.debugElement.query(
By.directive(MockButtonComponent)
).componentInstance
componentSpy = jest.spyOn(component, 'openInExternalViewer')
windowSpy = jest
.spyOn(global, 'window', 'get')
.mockImplementation(() => ({
open: openMock,
focus: focusMock,
}))
buttonComponent.buttonClick.emit()
})

afterEach(() => {
componentSpy.mockRestore()
windowSpy.mockRestore()
afterEach(() => {
componentSpy.mockRestore()
windowSpy.mockRestore()
})
it('calls openInExternalViewer', () => {
expect(component.openInExternalViewer).toHaveBeenCalled()
})
it('opens window in new tab with URL including WFS link params', () => {
expect(openMock).toHaveBeenCalledWith(
'https://example.com/myviewer/#/?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["layername"],"sources":[{"url":"http%3A%2F%2Fexample.com%2Fows%3Fservice%3Dwfs%26request%3Dgetcapabilities","type":"wfs"}]}]',
'_blank'
)
})
it('focuses window', () => {
expect(focusMock).toHaveBeenCalled()
})
})
it('calls openInExternalViewer', () => {
expect(component.openInExternalViewer).toHaveBeenCalled()
})
describe('with mapConfig and GEOJSON link', () => {
beforeEach(() => {
component.mapConfig = MAP_CONFIG_FIXTURE
component.link = {
url: new URL('http://example.com/somespatialdata.geojson'),
type: 'download',
mimeType: 'application/vnd.geo+json',
}
fixture.detectChanges()
})
it('opens window in new tab with URL including WMS link params', () => {
expect(openMock).toHaveBeenCalledWith(
'https://example.com/myviewer?url=http%3A%2F%2Fexample.com%2Fows%3Fservice%3Dwms%26request%3Dgetcapabilities&name=layername&type=wms',
'_blank'
)
it('sets externalViewer to display button to true', () => {
expect(component.externalViewer).toEqual(true)
})
it('focuses window', () => {
expect(focusMock).toHaveBeenCalled()
describe('click button', () => {
beforeEach(() => {
buttonComponent = fixture.debugElement.query(
By.directive(MockButtonComponent)
).componentInstance
componentSpy = jest.spyOn(component, 'openInExternalViewer')
windowSpy = jest
.spyOn(global, 'window', 'get')
.mockImplementation(() => ({
open: openMock,
focus: focusMock,
}))
buttonComponent.buttonClick.emit()
})

afterEach(() => {
componentSpy.mockRestore()
windowSpy.mockRestore()
})
it('calls openInExternalViewer', () => {
expect(component.openInExternalViewer).toHaveBeenCalled()
})
it('opens window in new tab with URL including link params', () => {
expect(openMock).toHaveBeenCalledWith(
'https://example.com/myviewer/#/?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["externalviewer.dataset.unnamed"],"sources":[{"url":"http%3A%2F%2Fexample.com%2Fsomespatialdata.geojson","type":"geojson"}]}]',
'_blank'
)
})
it('focuses window', () => {
expect(focusMock).toHaveBeenCalled()
})
})
})
})
describe('with mapConfig and non WMS link', () => {
describe('with mapConfig and invalid external link (non WMS/WFS/GEOJSON)', () => {
beforeEach(() => {
component.mapConfig = MAP_CONFIG_FIXTURE
component.link = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { MapConfig } from '@geonetwork-ui/util/app-config'
import { DatasetDistribution } from '@geonetwork-ui/common/domain/model/record'
import { marker } from '@biesbjerg/ngx-translate-extract-marker'
import { TranslateService } from '@ngx-translate/core'
import { getFileFormat } from '@geonetwork-ui/util/shared'

marker('externalviewer.dataset.unnamed')

@Component({
selector: 'gn-ui-external-viewer-button',
Expand Down Expand Up @@ -31,14 +36,24 @@ export class ExternalViewerButtonComponent {
if (this.link.accessServiceProtocol === 'wfs') {
return 'wfs'
}
} else if (
this.link.type === 'download' &&
getFileFormat(this.link) === 'geojson'
) {
return 'geojson'
}
return null
}

constructor(private translateService: TranslateService) {}

openInExternalViewer() {
const templateUrl = this.mapConfig.EXTERNAL_VIEWER_URL_TEMPLATE
const layerName = this.link.name
? this.link.name
: this.translateService.instant('externalviewer.dataset.unnamed')
const url = templateUrl
.replace('${layer_name}', `${this.link.name}`)
.replace('${layer_name}', `${layerName}`)
.replace(
'${service_url}',
`${encodeURIComponent(this.link.url.toString())}`
Expand Down
2 changes: 1 addition & 1 deletion libs/util/app-config/src/lib/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const MAP_CONFIG_FIXTURE: MapConfig = {
MAX_EXTENT: [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855],
DO_NOT_USE_DEFAULT_BASEMAP: false,
EXTERNAL_VIEWER_URL_TEMPLATE:
'https://example.com/myviewer?url=${service_url}&name=${layer_name}&type=${service_type}',
'https://example.com/myviewer/#/?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["${layer_name}"],"sources":[{"url":"${service_url}","type":"${service_type}"}]}]',
EXTERNAL_VIEWER_OPEN_NEW_TAB: true,
MAP_LAYERS: [
{
Expand Down
1 change: 1 addition & 0 deletions translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"downloads.format.unknown": "unbekannt",
"downloads.wfs.featuretype.not.found": "Die Schicht wurde nicht gefunden",
"dropFile": "Datei ablegen",
"externalviewer.dataset.unnamed": "Datensatz aus dem Datahub",
"facets.block.title.OrgForResource": "Organisation",
"facets.block.title.availableInServices": "Verfügbar für",
"facets.block.title.cl_hierarchyLevel.key": "Ressourcentyp",
Expand Down
1 change: 1 addition & 0 deletions translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"downloads.format.unknown": "unknown",
"downloads.wfs.featuretype.not.found": "The layer was not found",
"dropFile": "drop file",
"externalviewer.dataset.unnamed": "Datahub layer",
"facets.block.title.OrgForResource": "Organisation",
"facets.block.title.availableInServices": "Available for",
"facets.block.title.cl_hierarchyLevel.key": "Resource type",
Expand Down
1 change: 1 addition & 0 deletions translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"downloads.format.unknown": "",
"downloads.wfs.featuretype.not.found": "",
"dropFile": "",
"externalviewer.dataset.unnamed": "",
"facets.block.title.OrgForResource": "",
"facets.block.title.availableInServices": "",
"facets.block.title.cl_hierarchyLevel.key": "",
Expand Down
1 change: 1 addition & 0 deletions translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"downloads.format.unknown": "inconnu",
"downloads.wfs.featuretype.not.found": "La couche n'a pas été retrouvée",
"dropFile": "Faites glisser votre fichier",
"externalviewer.dataset.unnamed": "Couche du datahub",
"facets.block.title.OrgForResource": "Organisation",
"facets.block.title.availableInServices": "Disponible pour",
"facets.block.title.cl_hierarchyLevel.key": "Type de ressource",
Expand Down
1 change: 1 addition & 0 deletions translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"downloads.format.unknown": "",
"downloads.wfs.featuretype.not.found": "",
"dropFile": "",
"externalviewer.dataset.unnamed": "",
"facets.block.title.OrgForResource": "",
"facets.block.title.availableInServices": "",
"facets.block.title.cl_hierarchyLevel.key": "",
Expand Down
1 change: 1 addition & 0 deletions translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"downloads.format.unknown": "",
"downloads.wfs.featuretype.not.found": "",
"dropFile": "",
"externalviewer.dataset.unnamed": "",
"facets.block.title.OrgForResource": "",
"facets.block.title.availableInServices": "",
"facets.block.title.cl_hierarchyLevel.key": "",
Expand Down
1 change: 1 addition & 0 deletions translations/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"downloads.format.unknown": "",
"downloads.wfs.featuretype.not.found": "",
"dropFile": "",
"externalviewer.dataset.unnamed": "",
"facets.block.title.OrgForResource": "",
"facets.block.title.availableInServices": "",
"facets.block.title.cl_hierarchyLevel.key": "",
Expand Down
1 change: 1 addition & 0 deletions translations/sk.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"downloads.format.unknown": "neznámy",
"downloads.wfs.featuretype.not.found": "Vrstva nebola nájdená",
"dropFile": "nahrať súbor",
"externalviewer.dataset.unnamed": "",
"facets.block.title.OrgForResource": "Organizácia",
"facets.block.title.availableInServices": "Dostupné pre",
"facets.block.title.cl_hierarchyLevel.key": "Typ zdroja",
Expand Down

0 comments on commit f49cddd

Please sign in to comment.