diff --git a/demo/js/ml-datasets.js b/demo/js/ml-datasets.js index 635c0384..454ed7d1 100644 --- a/demo/js/ml-datasets.js +++ b/demo/js/ml-datasets.js @@ -301,7 +301,7 @@ const hedgeControlDataset = { const datasetsPlugin = createDatasetsPlugin({ layerAdapter: maplibreLayerAdapter, globals: { - opacityMode: 'multiply', // 'dataset', 'global' or 'multiply' + opacityMode: 'dataset', // 'dataset', 'global' or 'multiply' opacity: 0.75, visible: true }, @@ -396,15 +396,12 @@ const testFeatureVisibility = () => { const testSetOpacity = () => { setTimeout(() => datasetsPlugin.setOpacity(0.8, { datasetId: 'land-covers' }), 500) setTimeout(() => datasetsPlugin.setOpacity(0.2, { datasetId: 'land-covers', sublayerId: '130-131' }), 2000) - // setTimeout(() => datasetsPlugin.setOpacity(0.8, { datasetId: 'land-covers', sublayerId: '130-131' }), 2000) - // setTimeout(() => datasetsPlugin.setOpacity(0.3, { datasetId: 'land-covers', sublayerId: '130-131' }), 2500) setTimeout(() => datasetsPlugin.setOpacity(0.97, { datasetId: 'land-covers' }), 4000) - // setTimeout(() => datasetsPlugin.setOpacity(1, { datasetId: 'land-covers', sublayerId: '130-131' }), 6000) - - setTimeout(() => datasetsPlugin.setOpacity(0), 8000) - setTimeout(() => datasetsPlugin.setOpacity(1), 10000) - // TODO: - // setTimeout(() => datasetsPlugin.setGlobal({ opacityMode: 'multiply' }), 2000) + setTimeout(() => datasetsPlugin.setOpacity(0), 6000) + setTimeout(() => datasetsPlugin.setGlobals({ opacityMode: 'global' }), 7000) + setTimeout(() => datasetsPlugin.setOpacity(0.8), 7500) + setTimeout(() => datasetsPlugin.setGlobals({ opacityMode: 'dataset' }), 8000) + setTimeout(() => datasetsPlugin.setGlobals({ opacityMode: 'multiply' }), 9000) } const testSetStyle = () => { diff --git a/plugins/beta/datasets/src/api/setGlobals.js b/plugins/beta/datasets/src/api/setGlobals.js new file mode 100644 index 00000000..10195266 --- /dev/null +++ b/plugins/beta/datasets/src/api/setGlobals.js @@ -0,0 +1,20 @@ +import { logger } from '../../../../../src/services/logger.js' +export const setGlobals = ({ pluginState: { dispatch } }, values) => { + const { opacityMode } = values + const payload = {} + let valuesSet = false + if (opacityMode) { + if (!['dataset', 'global', 'multiply'].includes(opacityMode)) { + logger.warn(`Ignoring invalid opacityMode: ${opacityMode}. Must be one of 'dataset', 'global' or 'multiply'.`) + } else { + valuesSet = true + payload.opacityMode = opacityMode + } + } + + if (valuesSet) { + dispatch({ type: 'SET_GLOBAL_STATE', payload }) + } else { + logger.warn('setGlobals: requires a valid value for opacityMode to be set') + } +} diff --git a/plugins/beta/datasets/src/api/setGlobals.test.js b/plugins/beta/datasets/src/api/setGlobals.test.js new file mode 100644 index 00000000..bb0e1651 --- /dev/null +++ b/plugins/beta/datasets/src/api/setGlobals.test.js @@ -0,0 +1,63 @@ +import { setGlobals } from './setGlobals.js' +import { logger } from '../../../../../src/services/logger.js' + +jest.mock('../../../../../src/services/logger.js', () => ({ + logger: { warn: jest.fn() } +})) + +describe('setGlobals', () => { + const dispatch = jest.fn() + + beforeEach(() => { + jest.clearAllMocks() + }) + + it('dispatches SET_GLOBAL_STATE with opacityMode when valid value is provided', () => { + setGlobals({ pluginState: { dispatch } }, { opacityMode: 'dataset' }) + + expect(dispatch).toHaveBeenCalledWith({ + type: 'SET_GLOBAL_STATE', + payload: { opacityMode: 'dataset' } + }) + }) + + it.each(['dataset', 'global', 'multiply'])('accepts valid opacityMode: %s', (opacityMode) => { + setGlobals({ pluginState: { dispatch } }, { opacityMode }) + + expect(dispatch).toHaveBeenCalledWith({ + type: 'SET_GLOBAL_STATE', + payload: { opacityMode } + }) + expect(logger.warn).not.toHaveBeenCalled() + }) + + it('warns and does not dispatch when opacityMode is invalid', () => { + setGlobals({ pluginState: { dispatch } }, { opacityMode: 'invalid' }) + + expect(logger.warn).toHaveBeenCalledWith( + "Ignoring invalid opacityMode: invalid. Must be one of 'dataset', 'global' or 'multiply'." + ) + expect(dispatch).not.toHaveBeenCalled() + }) + + it('warns and does not dispatch when no valid values are provided', () => { + setGlobals({ pluginState: { dispatch } }, {}) + + expect(logger.warn).toHaveBeenCalledWith( + 'setGlobals: requires a valid value for opacityMode to be set' + ) + expect(dispatch).not.toHaveBeenCalled() + }) + + it('warns about invalid opacityMode and then warns no valid values set', () => { + setGlobals({ pluginState: { dispatch } }, { opacityMode: 'bad' }) + + expect(logger.warn).toHaveBeenCalledWith( + "Ignoring invalid opacityMode: bad. Must be one of 'dataset', 'global' or 'multiply'." + ) + expect(logger.warn).toHaveBeenCalledWith( + 'setGlobals: requires a valid value for opacityMode to be set' + ) + expect(dispatch).not.toHaveBeenCalled() + }) +}) diff --git a/plugins/beta/datasets/src/datasets.js b/plugins/beta/datasets/src/datasets.js index 8d024a63..6d5f0ad5 100644 --- a/plugins/beta/datasets/src/datasets.js +++ b/plugins/beta/datasets/src/datasets.js @@ -18,7 +18,7 @@ export const createDatasets = ({ const dynamicSources = new Map() if (pluginConfig.globals) { - dispatch({ type: 'INITIALISE_GLOBAL_STATE', payload: pluginConfig.globals }) + dispatch({ type: 'SET_GLOBAL_STATE', payload: pluginConfig.globals }) } // Initialise all datasets via the adapter, then set up dynamic sources diff --git a/plugins/beta/datasets/src/manifest.js b/plugins/beta/datasets/src/manifest.js index c1fbadd8..bb33ee5e 100755 --- a/plugins/beta/datasets/src/manifest.js +++ b/plugins/beta/datasets/src/manifest.js @@ -12,6 +12,7 @@ import { getStyle } from './api/getStyle.js' import { setOpacity } from './api/setOpacity.js' import { getOpacity } from './api/getOpacity.js' import { setData } from './api/setData.js' +import { setGlobals } from './api/setGlobals.js' export const manifest = { InitComponent: DatasetsInit, @@ -118,6 +119,7 @@ export const manifest = { getStyle, setOpacity, getOpacity, - setData + setData, + setGlobals } } diff --git a/plugins/beta/datasets/src/reducer.js b/plugins/beta/datasets/src/reducer.js index 4c43e3df..bb49c00e 100755 --- a/plugins/beta/datasets/src/reducer.js +++ b/plugins/beta/datasets/src/reducer.js @@ -34,9 +34,13 @@ const validateDatasetExists = (state, datasetId, prefix, suffix = 'not found') = return true } -const initialiseGlobalState = (state, payload) => { +const setGlobalState = (state, payload) => { + // For now we only have opacityMode, but if we add more global state + // properties we may not require applyGlobalOpacity to be triggered here. + const applyGlobalOpacity = [...state.layerAdapterActions.applyGlobalOpacity, []] return { ...state, + layerAdapterActions: { ...state.layerAdapterActions, applyGlobalOpacity }, globals: { ...state.globals, ...payload } } } @@ -181,7 +185,7 @@ const setOpacity = (state, payload) => { const setGlobalOpacity = (state, payload) => { const { opacity } = payload - const applyGlobalOpacity = [...state.layerAdapterActions.applyDatasetOpacity, []] + const applyGlobalOpacity = [...state.layerAdapterActions.applyGlobalOpacity, []] return { ...state, layerAdapterActions: { ...state.layerAdapterActions, applyGlobalOpacity }, @@ -204,7 +208,7 @@ const actions = { SHOW_FEATURES: showFeatures, SET_LAYER_ADAPTER: setLayerAdapter, SET_LAYER_ADAPTER_ACTIONS: setLayerAdapterActions, - INITIALISE_GLOBAL_STATE: initialiseGlobalState + SET_GLOBAL_STATE: setGlobalState } export {