Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 87 additions & 7 deletions demo/js/esri-datasets.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { transformGeocodeRequest, transformVtsRequest3857, setupEsriConfig } fro

const nonFloodZoneLight = '#2b8cbe'
const nonFloodZoneDark = '#7fcdbb'
const white = '#ffffff'
const darkTeal = '#12393d'

const COLOURS = {
// floodExtents: { default: nonFloodZoneLight, dark: nonFloodZoneDark },
Expand Down Expand Up @@ -36,8 +38,6 @@ const nonFloodZoneDepthBandsLight = [COLOURS.depthOver2300.default, COLOURS.dept
// GREENS dark tones > 2300 to < 150
const nonFloodZoneDepthBandsDark = [COLOURS.depthOver2300.dark, COLOURS.depth2300.dark, COLOURS.depth1200.dark, COLOURS.depth900.dark, COLOURS.depth600.dark, COLOURS.depth300.dark, COLOURS.depth150.dark]



const datasetFloodZonesCC = {
id: 'floodzonescc',
label: 'Flood Zones Climate Change',
Expand Down Expand Up @@ -326,8 +326,88 @@ const surfaceWaterDepthAllDataset = {
]
}

const datasetMainRivers = {
id: 'mainrivers',
label: 'Main Rivers',
groupLabel: 'Map features',
type: 'FeatureService',
tiles: 'https://services1.arcgis.com/JZM7qJpmv7vJ0Hzx/arcgis/rest/services/Statutory_Main_River_Map/FeatureServer',
showInKey: true,
showInMenu: true,
sourceLayer: 'Statutory_Main_River_Map',
visible: false,
style: {
renderer: {
type: 'simple',
symbol: {
type: 'simple-line',
width: '3px',
color: { outdoor: darkTeal, dark: white },
}
},
stroke: { outdoor: darkTeal, dark: white },
strokeWidth: 3
}
}

const datasetWaterStorageAreas = {
id: 'waterstorage',
label: 'Water Storage',
groupLabel: 'Map features',
type: 'FeatureService',
tiles: 'https://services1.arcgis.com/JZM7qJpmv7vJ0Hzx/arcgis/rest/services/Flood_Storage_Areas_NON_PRODUCTION/FeatureServer',
showInKey: true,
showInMenu: true,
sourceLayer: 'Flood_Storage_Areas',
visible: false,
style: {
renderer: {
type: 'simple',
symbol: {
type: 'simple-fill',
style: 'diagonal-cross',
color: { outdoor: darkTeal, dark: white },
outline: {
color: { outdoor: darkTeal, dark: white },
width: 1
}
}
},
stroke: { outdoor: darkTeal, dark: white },
strokeWidth: 1,
fillPattern: 'diagonal-cross-hatch',
fillPatternForegroundColor: { outdoor: darkTeal, dark: white },
fillPatternBackgroundColor: 'transparent'
}
}

const datasetFloodDefences = {
id: 'flooddefence',
label: 'Flood Defence',
groupLabel: 'Map features',
type: 'FeatureService',
tiles: 'https://services1.arcgis.com/JZM7qJpmv7vJ0Hzx/arcgis/rest/services/Defences_NON_PRODUCTION/FeatureServer',
showInKey: true,
showInMenu: true,
sourceLayer: 'Defences',
visible: false,
style: {
renderer: {
type: 'simple',
symbol: {
type: 'simple-line',
width: '3px',
color: '#f47738',
}
},
stroke: '#f47738',
strokeWidth: 3
}
}

const datasets = [
datasetFloodZonesCC, datasetFloodZones, surfaceWaterDataset, surfaceWaterDepthAllDataset
datasetFloodZonesCC, datasetFloodZones, surfaceWaterDataset, surfaceWaterDepthAllDataset,
datasetWaterStorageAreas, datasetFloodDefences, datasetMainRivers
]

const menu = [
Expand Down Expand Up @@ -391,14 +471,14 @@ const menu = [
]
}, {
id: 'features',
label: 'Map features',
groupLabel: 'Map features',
urlKey: 'features',
type: 'checkbox',
visibleWhen: true,
items: [
{ id: 'water-storage', label: 'Water storage', checked: false },
{ id: 'flood-defence', label: 'Flood defence', checked: false },
{ id: 'main-rivers', label: 'Main rivers', checked: false },
{ id: 'waterstorage', label: 'Water storage' },
{ id: 'flooddefence', label: 'Flood defence' },
{ id: 'mainrivers', label: 'Main rivers' },
]
}
]
Expand Down
18 changes: 9 additions & 9 deletions demo/js/ml-datasets.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,15 +467,15 @@ const testSetData = () => {
}

interactiveMap.on('datasets:ready', function () {
testGetters()
testInvalidApiCalls()
testFeatureVisibility()
testSetOpacity()
testSetStyle()
testVisibility()
testGlobalVisibility()
testRemoveAndAddDataset()
testSetData()
// testGetters()
// testInvalidApiCalls()
// testFeatureVisibility()
// testSetOpacity()
// testSetStyle()
// testVisibility()
// testGlobalVisibility()
// testRemoveAndAddDataset()
// testSetData()
})

// Ref to the selected features
Expand Down
3 changes: 2 additions & 1 deletion jest.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ export default {
testPathIgnorePatterns: ['<rootDir>/src/test-utils.js'],
coveragePathIgnorePatterns: [
'/__mocks__/',
'/__data__/',
'<rootDir>/src/index.umd.js',
'<rootDir>/stylelint.config.js',
'<rootDir>/coverage',
'<rootDir>/demo',
'<rootDir>/src/test-utils.js',
'<rootDir>/plugins/datasets/',
// '<rootDir>/plugins/datasets/',
'<rootDir>/providers/beta/',
'<rootDir>/plugins/beta/draw-es',
'<rootDir>/plugins/beta/draw-ml',
Expand Down
81 changes: 58 additions & 23 deletions plugins/datasets/src/adapters/esri/esriLayerAdapter.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import VectorTileLayer from '@arcgis/core/layers/VectorTileLayer.js'
import FeatureLayer from '@arcgis/core/layers/FeatureLayer.js'
import GroupLayer from '@arcgis/core/layers/GroupLayer.js'
import { LayerAdapter } from '../layerAdapter.js'
import { datasetRegistry } from '../../registry/datasetRegistry.js'
import { EsriDataset } from './registry/esriDataset.js'
import { logger } from '../../../../../src/services/logger.js'

export default class EsriLayerAdapter extends LayerAdapter {
constructor (mapProvider, symbolRegistry, patternRegistry) {
constructor (mapProvider) {
super()
this._mapProvider = mapProvider
this._map = mapProvider.map
// TODO: Implement symbolRegistry and patternRegistry usage in the adapter

// _vectorTileLayers is a map of datasetId to VectorTileLayer instances
// _mapVisibilityLayers is a map of datasetId to VectorTileLayer or FeatureLayer instances
// it includes stand alone vectorTileLayers and vectorTileLayers that are part of a groupLayer
// but does not include group layers themselves, which are tracked in _groupLayers
this._vectorTileLayers = {}
this._mapVisibilityLayers = {}

// _vectorTileOpacityLayers is a map of datasetId to VectorTileLayer/GroupLayer where opacity is applied
// it includes stand alone vectorTileLayers and groupLayers that contain vectorTileLayers
// _mapOpacityLayers is a map of datasetId to mapLayers where opacity is applied
// it includes featureLayers, vectorTileLayers and groupLayers
// but does not include vectorTileLayers that are part of a groupLayer
this._vectorTileOpacityLayers = {}
this._mapOpacityLayers = {}

// _groupLayers is a map of esriGroupId to GroupLayer
this._groupLayers = {}
Expand All @@ -33,7 +33,7 @@
async init () {
const topLevelDatasets = datasetRegistry.topLevelDatasets()
// ensure the datasets are added in order
for await (const registryDataset of topLevelDatasets) {
for (const registryDataset of topLevelDatasets) {
await this._addLayers(registryDataset)
}

Expand Down Expand Up @@ -62,17 +62,41 @@
return this._groupLayers[esriGroupId]
}

async _addFeatureLayers (registryDataset) {
const featureLayer = new FeatureLayer({
id: registryDataset.id,
url: registryDataset.tiles,
renderer: registryDataset.renderer,
opacity: 1,
visible: false
})
this._mapVisibilityLayers[registryDataset.id] = featureLayer
this._mapOpacityLayers[registryDataset.id] = featureLayer
try {
this._map.add(featureLayer)
return featureLayer.when()
} catch (error) {
logger.error(`Error adding FeatureLayer for dataset ${registryDataset.id}:`, error)
}
return Promise.resolve() // Return a resolved promise to avoid unhandled promise rejection

Check failure on line 81 in plugins/datasets/src/adapters/esri/esriLayerAdapter.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `return value` over `return Promise.resolve(value)`.

See more on https://sonarcloud.io/project/issues?id=DEFRA_interactive-map&issues=AZ9vDz85_DKIVWEQltku&open=AZ9vDz85_DKIVWEQltku&pullRequest=408
}

async _addLayers (registryDataset) {
const { esriGroupId } = registryDataset
const { type, esriGroupId } = registryDataset

if (type === 'FeatureService') {
return this._addFeatureLayers(registryDataset)
}

const vectorTileParent = esriGroupId ? this._addGroupLayer(esriGroupId) : this._map
const vectorTileLayer = new VectorTileLayer({
id: registryDataset.id,
url: registryDataset.tiles,
opacity: 1,
visible: false
})
this._vectorTileLayers[registryDataset.id] = vectorTileLayer
this._vectorTileOpacityLayers[registryDataset.id] = esriGroupId ? vectorTileParent : vectorTileLayer
this._mapVisibilityLayers[registryDataset.id] = vectorTileLayer
this._mapOpacityLayers[registryDataset.id] = esriGroupId ? vectorTileParent : vectorTileLayer
vectorTileParent.add(vectorTileLayer)
return vectorTileLayer.when()
}
Expand All @@ -85,7 +109,7 @@
}
await this._addLayers(registryDataset)
const { parentId } = registryDataset
const vectorTileLayer = this._vectorTileLayers[parentId || datasetId]
const vectorTileLayer = this._mapVisibilityLayers[parentId || datasetId]
this.applyDatasetOpacity(datasetId)
this._applyStyleLayerPaintProperties(registryDataset, vectorTileLayer)
this.applyDatasetVisibility(datasetId)
Expand All @@ -97,7 +121,7 @@
return
}
const { esriGroupId } = registryDataset
const vectorTileLayer = this._vectorTileLayers[datasetId]
const vectorTileLayer = this._mapVisibilityLayers[datasetId]
// If the dataset is part of a group layer, we need to remove it from the group layer
const groupLayer = esriGroupId ? this._groupLayers[esriGroupId] : null
const vectorTileParent = groupLayer || this._map
Expand All @@ -106,12 +130,12 @@
// Remove the vectorTileLayer from the map or group layer
vectorTileParent.remove(vectorTileLayer)
// And remove the vectorTileLayer from the adapter's internal state
delete this._vectorTileLayers[datasetId]
delete this._vectorTileOpacityLayers[datasetId]
delete this._mapVisibilityLayers[datasetId]
delete this._mapOpacityLayers[datasetId]
}

// If the group layer has no more sublayers, we need to also remove the group layer from the map
if (groupLayer && groupLayer.layers.length === 0) {
if (groupLayer?.layers.length === 0) {
this._map.remove(groupLayer)
delete this._groupLayers[esriGroupId]
}
Expand All @@ -121,13 +145,17 @@
// if this is a sublayer, we need to apply the visibility to the vectorTileLayers style sheet
// if this is a top level dataset, we need to apply the visibility to the vectorTileLayer/ groupLayer itself
const { id, isSublayer, visible, parentId } = registryDataset
const vectorTileLayer = this._vectorTileLayers[isSublayer ? parentId : id]
const vectorTileLayer = this._mapVisibilityLayers[isSublayer ? parentId : id]
if (!vectorTileLayer) {
return
}

if (isSublayer) {
this._applyStyleLayerVisibility(registryDataset, vectorTileLayer)
// Don't apply the visibility change to the parent, since the parent may have other sublayers that are visible
return
} else if (visible) {
}
if (visible) {
// No need to apply style layer visibility for datasets that are hidden
registryDataset.sublayers.forEach(sublayer => this._applyStyleLayerVisibility(sublayer, vectorTileLayer))
}
Expand All @@ -146,15 +174,15 @@
}

async applyDatasetOpacity (datasetId) {
const vectorTileLayer = this._vectorTileOpacityLayers[datasetId]
const vectorTileLayer = this._mapOpacityLayers[datasetId]
const registryDataset = datasetRegistry.getDataset(datasetId)
if (vectorTileLayer && registryDataset) {
vectorTileLayer.opacity = registryDataset.opacity
}
}

async applyGlobalOpacity () {
Object.entries(this._vectorTileOpacityLayers).forEach(([datasetId, vectorTileLayer]) => {
Object.entries(this._mapOpacityLayers).forEach(([datasetId, vectorTileLayer]) => {
const registryDataset = datasetRegistry.getDataset(datasetId)
if (registryDataset) {
vectorTileLayer.opacity = registryDataset.opacity
Expand Down Expand Up @@ -185,17 +213,24 @@
async onMapStyleChange () {
datasetRegistry.forEach(registryDataset => {
const { id, isSublayer, parent } = registryDataset
const vectorTileLayer = this._vectorTileLayers[isSublayer ? parent.id : id]
this._applyStyleLayerVisibility(registryDataset, vectorTileLayer)
this._applyStyleLayerPaintProperties(registryDataset, vectorTileLayer)

// mapLayer could be a VectorTileLayer or a FeatureLayer, depending on the dataset type
const mapLayer = this._mapVisibilityLayers[isSublayer ? parent.id : id]
if (registryDataset.type === 'FeatureService') {
// FeatureLayers don't have style layers, so we don't need to apply style layer visibility or paint properties
mapLayer.renderer = registryDataset.renderer
} else {
this._applyStyleLayerVisibility(registryDataset, mapLayer)
this._applyStyleLayerPaintProperties(registryDataset, mapLayer)
}
})
// TODO - handle dynamic sources

Check warning on line 227 in plugins/datasets/src/adapters/esri/esriLayerAdapter.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=DEFRA_interactive-map&issues=AZ9vBDvYHyyQDcGgrDi0&open=AZ9vBDvYHyyQDcGgrDi0&pullRequest=408
}

// onMapSizeChange is not applicable to the esriLayerAdapter
async onMapSizeChange () {}

// Remaining methods are still todo

Check warning on line 233 in plugins/datasets/src/adapters/esri/esriLayerAdapter.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=DEFRA_interactive-map&issues=AZ9vBDvYHyyQDcGgrDi1&open=AZ9vBDvYHyyQDcGgrDi1&pullRequest=408
async applyFeatureFilter (...args) {
console.log('TODO: applyFeatureFilter', args)
}
Expand Down
Loading
Loading