@opengeoweb/store 9.22.0 → 9.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
- import { webmapUtils, LayerType, getWMJSMapById, WMLayer, webmapTestSettings, getWMSRequests, isProjectionSupported, handleDateUtilsISOString, getCapabilities } from '@opengeoweb/webmap';
2
- import { createAction, createSlice, createSelector, createEntityAdapter, createListenerMiddleware } from '@reduxjs/toolkit';
1
+ import { webmapUtils, LayerType, getWMJSMapById, WMLayer, webmapTestSettings, isProjectionSupported, handleDateUtilsISOString, getCapabilities, getWMSRequests } from '@opengeoweb/webmap';
2
+ import { createAction, createSlice, createSelector, createEntityAdapter, createListenerMiddleware, isAnyOf } from '@reduxjs/toolkit';
3
3
  import { getGeoJson, moveFeature, createInterSections, getLastEmptyFeatureIndex, defaultLayers, emptyGeoJSON, addSelectionTypeToGeoJSON, getFeatureCollection, defaultIntersectionStyleProperties } from '@opengeoweb/webmap-react';
4
4
  export { defaultLayers } from '@opengeoweb/webmap-react';
5
5
  import { dateUtils, defaultDelay, withEggs } from '@opengeoweb/shared';
@@ -2000,7 +2000,7 @@ var LayerActionOrigin;
2000
2000
  LayerActionOrigin["wmsLoader"] = "WMSLayerTreeConnect";
2001
2001
  LayerActionOrigin["ReactMapViewParseLayer"] = "ReactMapViewParseLayer";
2002
2002
  LayerActionOrigin["setLayerDimensionSaga"] = "setLayerDimensionSaga";
2003
- LayerActionOrigin["toggleAutoUpdateSaga"] = "toggleAutoUpdateSaga";
2003
+ LayerActionOrigin["toggleAutoUpdateListener"] = "toggleAutoUpdateListener";
2004
2004
  LayerActionOrigin["unregisterMapSaga"] = "unregisterMapSaga";
2005
2005
  })(LayerActionOrigin || (LayerActionOrigin = {}));
2006
2006
 
@@ -4635,6 +4635,7 @@ var DialogTypes;
4635
4635
  DialogTypes["ObjectManager"] = "objectManager";
4636
4636
  DialogTypes["PublicWarnings"] = "publicWarnings";
4637
4637
  DialogTypes["Search"] = "search";
4638
+ DialogTypes["AreaObjectLoader"] = "areaObjectLoader";
4638
4639
  })(DialogTypes || (DialogTypes = {}));
4639
4640
 
4640
4641
  var types$3 = /*#__PURE__*/Object.freeze({
@@ -4999,17 +5000,7 @@ const setBboxOrTimeSync = (draft, action) => {
4999
5000
  });
5000
5001
  }
5001
5002
  };
5002
- const {
5003
- syncGroupAddGroup,
5004
- syncGroupAddSource,
5005
- syncGroupAddTarget,
5006
- syncGroupClear,
5007
- syncGroupLinkTarget,
5008
- syncGroupRemoveGroup,
5009
- syncGroupRemoveSource,
5010
- syncGroupRemoveTarget,
5011
- syncGroupSetViewState
5012
- } = slice$4.actions;
5003
+ slice$4.actions;
5013
5004
  const {
5014
5005
  actions,
5015
5006
  reducer: reducer$3
@@ -7630,115 +7621,6 @@ fixRegExpWellKnownSymbolLogic('split', function (SPLIT, nativeSplit, maybeCallNa
7630
7621
  ];
7631
7622
  }, BUGGY || !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC, UNSUPPORTED_Y);
7632
7623
 
7633
- /* A map with all the timerIds and their current step */
7634
- const stepMap = new Map();
7635
- /* A map with a list of timers and their dwell */
7636
- const timerDwellMap = new Map();
7637
- /**
7638
- * Returns the next step for given timerId.
7639
- * @param timerId The timer id
7640
- * @param numberOfStepsInAnimation Animation length in steps
7641
- * @param numStepsToGoForward Amount of steps to go forwards, defaults to 1. Can be positive and negative
7642
- * @returns
7643
- */
7644
- const getNextStep = (timerId, numberOfStepsInAnimation, numStepsToGoForward = 1) => {
7645
- const currentStep = getCurrentStep(timerId);
7646
- const nextStep = currentStep + numStepsToGoForward;
7647
- const nextStepClipped = (nextStep % numberOfStepsInAnimation + numberOfStepsInAnimation) % numberOfStepsInAnimation;
7648
- return nextStepClipped;
7649
- };
7650
- /**
7651
- * Handles dwell at the end of the animation loop sequence. The number of steps to wait till proceed can be set by the dwell parameter.
7652
- * @param timerId The timer id
7653
- * @param numberOfStepsInAnimation Number of steps in the animation
7654
- * @param dwell The number of steps to wait at the end of the animation sequence before to continue
7655
- * @returns
7656
- */
7657
- const handleTimerDwell = (timerId, numberOfStepsInAnimation, dwell = 8) => {
7658
- if (dwell > 0) {
7659
- const currentStep = getCurrentStep(timerId);
7660
- // Reset the dwell if we are not at the last animation step
7661
- if (currentStep < numberOfStepsInAnimation - 1) {
7662
- timerDwellMap.set(timerId, dwell);
7663
- return false;
7664
- }
7665
- // We are at the last animation step, check the dwell
7666
- const timerDwell = timerDwellMap.has(timerId) && timerDwellMap.get(timerId) || 0;
7667
- if (currentStep === numberOfStepsInAnimation - 1 && timerDwell > 0) {
7668
- timerDwellMap.set(timerId, timerDwell - 1);
7669
- return true;
7670
- }
7671
- }
7672
- return false;
7673
- };
7674
- /**
7675
- * Set step for the timerId
7676
- * @param timerId
7677
- * @param timerStep
7678
- */
7679
- const setStep = (timerId, timerStep) => {
7680
- stepMap.set(timerId, timerStep);
7681
- };
7682
- /**
7683
- * Gets the current step for the timer
7684
- * @param timerId
7685
- * @returns
7686
- */
7687
- const getCurrentStep = timerId => {
7688
- return stepMap.get(timerId) || 0;
7689
- };
7690
- const MAX_NUMBER_STEPS_FORWARD_TO_PREFETCH = 2;
7691
- const MAX_NUMBER_OF_PARALLEL_LOADING_IMAGES = 8;
7692
- /**
7693
- * This prefetches all images connected to the same sync group as provided timerId
7694
- * @param timerId The timerId
7695
- * @param animationListValues List of animation steps in isostring to animate
7696
- * @param targets List of targets to check
7697
- * @returns True if all maps are ready to go forward, false if the map has no data to display yet.
7698
- */
7699
- const prefetchAnimationTargetsForMetronome = (timerId, animationListValues, targets) => {
7700
- let timerShouldStepForward = true;
7701
- // The following code prefetches/buffers for all maps in the group
7702
- for (let numPrefetch = 0; numPrefetch < MAX_NUMBER_STEPS_FORWARD_TO_PREFETCH; numPrefetch += 1) {
7703
- const nextStep = getNextStep(timerId, animationListValues.length, numPrefetch + 1);
7704
- const nextTimeValueStepToCheck = animationListValues[nextStep];
7705
- for (const target of targets) {
7706
- const targetMapId = target.targetId;
7707
- const wmMap = getWMJSMapById(targetMapId);
7708
- if (wmMap) {
7709
- const layersImageUrls = getWMSRequests(wmMap, [{
7710
- name: 'time',
7711
- currentValue: nextTimeValueStepToCheck
7712
- }]);
7713
- for (const layersImageUrl of layersImageUrls) {
7714
- const image = wmMap.getMapImageStore.getImage(layersImageUrl.url);
7715
- if (!image.isLoaded()) {
7716
- if (wmMap.getMapImageStore.getNumImagesLoading() < MAX_NUMBER_OF_PARALLEL_LOADING_IMAGES) {
7717
- image.load();
7718
- }
7719
- if (numPrefetch === 0) {
7720
- const altImage = wmMap.getAlternativeImage(layersImageUrl.url, wmMap.getBBOX(), true);
7721
- // No alternative image available yet, so skipping animation.
7722
- if (altImage.length === 0) {
7723
- // This is useful to indicate that the map is loading and has nothing yet to display.
7724
- // console.warn('No data available: Not stepping forward');
7725
- timerShouldStepForward = false;
7726
- }
7727
- }
7728
- } else if (image.isStale()) {
7729
- if (wmMap.getMapImageStore.getNumImagesLoading() < MAX_NUMBER_OF_PARALLEL_LOADING_IMAGES) {
7730
- image.forceReload(true);
7731
- }
7732
- }
7733
- }
7734
- } else {
7735
- return false; // Map was not registered so there is nothing to prefetch
7736
- }
7737
- }
7738
- }
7739
- return timerShouldStepForward;
7740
- };
7741
-
7742
7624
  const isAnimationEndTimeValid = animationEndTime => {
7743
7625
  const hasValidPrefix = animationEndTime.split(/[-+]/)[0] === 'NOW' || animationEndTime.split(/[-+]/)[0] === 'TODAY';
7744
7626
  const durationString = animationEndTime.substring(animationEndTime.indexOf('PT') + 2);
@@ -7749,37 +7631,6 @@ const isAnimationEndTimeValid = animationEndTime => {
7749
7631
  const parsedDate = dateUtils.parseISO(animationEndTime);
7750
7632
  return dateUtils.isValid(parsedDate);
7751
7633
  };
7752
- function* startAnimationSaga({
7753
- payload
7754
- }) {
7755
- const {
7756
- mapId,
7757
- initialTime
7758
- } = payload;
7759
- const speedDelay = yield select(getMapAnimationDelay, mapId);
7760
- const speed = 1000 / (speedDelay || 1);
7761
- metronome.register(null, speed, mapId);
7762
- const timeList = yield select(getAnimationList, mapId);
7763
- // In case of the timeList
7764
- if (timeList && timeList.length > 0) {
7765
- // Determine animation step based on initialTime and timeList
7766
- const initalTimerStep = timeList === null || timeList === void 0 ? void 0 : timeList.findIndex(timeNameValue => {
7767
- return timeNameValue.value === initialTime;
7768
- });
7769
- if (initalTimerStep !== -1) {
7770
- setStep(mapId, initalTimerStep);
7771
- }
7772
- }
7773
- }
7774
- // eslint-disable-next-line require-yield
7775
- function* stopAnimationSaga({
7776
- payload
7777
- }) {
7778
- const {
7779
- mapId
7780
- } = payload;
7781
- metronome.unregister(mapId);
7782
- }
7783
7634
  function* deleteLayerSaga({
7784
7635
  payload
7785
7636
  }) {
@@ -7793,7 +7644,7 @@ function* deleteLayerSaga({
7793
7644
  }));
7794
7645
  }
7795
7646
  }
7796
- function* updateAnimation(mapId, maxValue) {
7647
+ function* updateAnimation$1(mapId, maxValue) {
7797
7648
  const shouldEndtimeOverride$1 = yield select(shouldEndtimeOverride, mapId);
7798
7649
  if (shouldEndtimeOverride$1 === true) {
7799
7650
  return;
@@ -7871,59 +7722,7 @@ function* setLayerDimensionsSaga({
7871
7722
  }))));
7872
7723
  }
7873
7724
  }
7874
- yield call$e(updateAnimation, mapId, incomingMaxTime);
7875
- }
7876
- } catch (error) {
7877
- // eslint-disable-next-line no-console
7878
- console.warn(error);
7879
- }
7880
- }
7881
- function* toggleAutoUpdateSaga({
7882
- payload
7883
- }) {
7884
- const {
7885
- shouldAutoUpdate,
7886
- mapId
7887
- } = payload;
7888
- if (!shouldAutoUpdate) {
7889
- return;
7890
- }
7891
- try {
7892
- // go to end of active layer
7893
- const autoUpdateLayerId = yield select(getAutoUpdateLayerId, mapId);
7894
- const timeDimension = yield select(getLayerTimeDimension, autoUpdateLayerId);
7895
- if (timeDimension === null || timeDimension === void 0 ? void 0 : timeDimension.maxValue) {
7896
- yield put(layerActions.layerChangeDimension({
7897
- layerId: autoUpdateLayerId,
7898
- origin: LayerActionOrigin.toggleAutoUpdateSaga,
7899
- dimension: {
7900
- name: 'time',
7901
- currentValue: timeDimension.maxValue
7902
- }
7903
- }));
7904
- // Change time value for all other timesliders that are synced by syncgroups
7905
- const syncedMapIds = yield select(getSyncedMapIdsForTimeslider);
7906
- if (syncedMapIds.length > 0) {
7907
- yield all(syncedMapIds.map(syncedMapId => put(setTime({
7908
- origin: 'mapStore saga',
7909
- sourceId: syncedMapId,
7910
- value: timeDimension.maxValue
7911
- }))));
7912
- // When timesliders are synced by syncgrous autoupdate is toggled on, toggle autoupdate off for other timesliders
7913
- const payloads = syncedMapIds.reduce((syncedMapIdList, syncedMapId) => {
7914
- if (syncedMapId !== mapId) {
7915
- return syncedMapIdList.concat({
7916
- mapId: syncedMapId,
7917
- shouldAutoUpdate: false
7918
- });
7919
- }
7920
- return syncedMapIdList;
7921
- }, []);
7922
- if (payloads.length > 0) {
7923
- yield all(payloads.map(payload => put(mapActions.toggleAutoUpdate(payload))));
7924
- }
7925
- }
7926
- yield call$e(updateAnimation, mapId, timeDimension.maxValue);
7725
+ yield call$e(updateAnimation$1, mapId, incomingMaxTime);
7927
7726
  }
7928
7727
  } catch (error) {
7929
7728
  // eslint-disable-next-line no-console
@@ -8257,13 +8056,10 @@ function* setStepBackwardOrForwardSaga({
8257
8056
  }));
8258
8057
  }
8259
8058
  }
8260
- function* rootSaga$4() {
8059
+ function* rootSaga$2() {
8261
8060
  // resets IWMJSMap state
8262
- yield takeLatest(mapActions.mapStopAnimation.type, stopAnimationSaga);
8263
- yield takeLatest(mapActions.mapStartAnimation.type, startAnimationSaga);
8264
8061
  yield takeLatest(layerActions.layerDelete.type, deleteLayerSaga);
8265
8062
  yield takeLatest(layerActions.onUpdateLayerInformation.type, setLayerDimensionsSaga);
8266
- yield takeLatest(mapActions.toggleAutoUpdate.type, toggleAutoUpdateSaga);
8267
8063
  yield takeEvery(mapActions.setMapPreset.type, setMapPresetSaga);
8268
8064
  yield takeEvery(mapActions.unregisterMap.type, unregisterMapSaga);
8269
8065
  yield takeEvery(mapActions.setStepBackwardOrForward.type, setStepBackwardOrForwardSaga);
@@ -8295,85 +8091,194 @@ function* fetchInitialServicesSaga({
8295
8091
  }));
8296
8092
  }));
8297
8093
  }
8298
- function* rootSaga$3() {
8094
+ function* rootSaga$1() {
8299
8095
  yield takeEvery(serviceActions.fetchInitialServices, fetchInitialServicesSaga);
8300
8096
  }
8301
8097
 
8098
+ /* A map with all the timerIds and their current step */
8099
+ const stepMap = new Map();
8100
+ /* A map with a list of timers and their dwell */
8101
+ const timerDwellMap = new Map();
8302
8102
  /**
8303
- * This handler is triggered by the metronome. An array of timerIds is given as argument.
8304
- * It will update the animation loop of multiple maps and sliders
8305
- * It will prefetch images for maps
8306
- * @param timerIds string[] array of timerIds
8307
- * @param listenerApi ListenerEffectAPI<CoreAppStore, Dispatch, unknown> listenerApi as received from listener
8103
+ * Returns the next step for given timerId.
8104
+ * @param timerId The timer id
8105
+ * @param numberOfStepsInAnimation Animation length in steps
8106
+ * @param numStepsToGoForward Amount of steps to go forwards, defaults to 1. Can be positive and negative
8107
+ * @returns
8308
8108
  */
8309
- const metronomeHandler = (timerIds, listenerApi) => {
8310
- const targetsWithUpdateValue = [];
8311
- for (const timerId of timerIds) {
8312
- const animationListValuesNameAndValue = getAnimationList(listenerApi.getState(), timerId);
8313
- const animationListValues = animationListValuesNameAndValue.map(nameAndValue => nameAndValue.value);
8314
- const targets = getTargets(listenerApi.getState(), {
8315
- sourceId: timerId,
8316
- origin: timerId
8317
- }, SYNCGROUPS_TYPE_SETTIME);
8318
- if (targets.length === 0) {
8319
- // When there are no targets, default to one
8320
- targets.push({
8321
- targetId: timerId,
8322
- value: ''
8323
- });
8109
+ const getNextStep = (timerId, numberOfStepsInAnimation, numStepsToGoForward = 1) => {
8110
+ const currentStep = getCurrentStep(timerId);
8111
+ const nextStep = currentStep + numStepsToGoForward;
8112
+ const nextStepClipped = (nextStep % numberOfStepsInAnimation + numberOfStepsInAnimation) % numberOfStepsInAnimation;
8113
+ return nextStepClipped;
8114
+ };
8115
+ /**
8116
+ * Handles dwell at the end of the animation loop sequence. The number of steps to wait till proceed can be set by the dwell parameter.
8117
+ * @param timerId The timer id
8118
+ * @param numberOfStepsInAnimation Number of steps in the animation
8119
+ * @param dwell The number of steps to wait at the end of the animation sequence before to continue
8120
+ * @returns
8121
+ */
8122
+ const handleTimerDwell = (timerId, numberOfStepsInAnimation, dwell = 8) => {
8123
+ if (dwell > 0) {
8124
+ const currentStep = getCurrentStep(timerId);
8125
+ // Reset the dwell if we are not at the last animation step
8126
+ if (currentStep < numberOfStepsInAnimation - 1) {
8127
+ timerDwellMap.set(timerId, dwell);
8128
+ return false;
8129
+ }
8130
+ // We are at the last animation step, check the dwell
8131
+ const timerDwell = timerDwellMap.has(timerId) && timerDwellMap.get(timerId) || 0;
8132
+ if (currentStep === numberOfStepsInAnimation - 1 && timerDwell > 0) {
8133
+ timerDwellMap.set(timerId, timerDwell - 1);
8134
+ return true;
8324
8135
  }
8325
- const timerIsInDwell = handleTimerDwell(timerId, animationListValues.length);
8326
- const timerShouldStepForward = prefetchAnimationTargetsForMetronome(timerId, animationListValues, targets) && !timerIsInDwell;
8327
- // Determine the next step
8328
- const timerStep = timerShouldStepForward ? getNextStep(timerId, animationListValues.length) : getCurrentStep(timerId);
8329
- setStep(timerId, timerStep);
8330
- const updatedValue = animationListValues[timerStep];
8331
- targetsWithUpdateValue.push(...targets.map(target => {
8332
- return Object.assign(Object.assign({}, target), {
8333
- value: updatedValue
8334
- });
8335
- }));
8336
- const speedDelay = getMapAnimationDelay(listenerApi.getState(), timerId);
8337
- const speed = 1000 / (speedDelay || 1);
8338
- metronome.setSpeed(timerId, speed);
8339
- }
8340
- // Update all targets of all sync groups in one action.
8341
- if (targetsWithUpdateValue.length > 0) {
8342
- listenerApi.dispatch(setTimeSync(null, targetsWithUpdateValue, ['metronomesaga']));
8343
8136
  }
8137
+ return false;
8344
8138
  };
8345
- const metronomeListener = createListenerMiddleware();
8346
- metronomeListener.startListening({
8347
- actionCreator: mapActions.mapStartAnimation,
8348
- effect: (_, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
8349
- // register handler with access to listenerApi
8350
- metronome.handleTimerTicks = timerIds => {
8351
- metronomeHandler(timerIds, listenerApi);
8352
- };
8353
- })
8354
- });
8355
-
8356
- /* *
8357
- * Licensed under the Apache License, Version 2.0 (the "License");
8358
- * you may not use this file except in compliance with the License.
8359
- * You may obtain a copy of the License at
8360
- *
8361
- * http://www.apache.org/licenses/LICENSE-2.0
8362
- *
8363
- * Unless required by applicable law or agreed to in writing, software
8364
- * distributed under the License is distributed on an "AS IS" BASIS,
8365
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8366
- * See the License for the specific language governing permissions and
8367
- * limitations under the License.
8368
- *
8369
- * Copyright 2024 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
8370
- * Copyright 2024 - Finnish Meteorological Institute (FMI)
8371
- * */
8372
- const layersListener = createListenerMiddleware();
8373
- layersListener.startListening({
8374
- actionCreator: layerActions.showLayerInfo,
8375
- effect: ({
8376
- payload
8139
+ /**
8140
+ * Set step for the timerId
8141
+ * @param timerId
8142
+ * @param timerStep
8143
+ */
8144
+ const setStep = (timerId, timerStep) => {
8145
+ stepMap.set(timerId, timerStep);
8146
+ };
8147
+ /**
8148
+ * Gets the current step for the timer
8149
+ * @param timerId
8150
+ * @returns
8151
+ */
8152
+ const getCurrentStep = timerId => {
8153
+ return stepMap.get(timerId) || 0;
8154
+ };
8155
+ const MAX_NUMBER_STEPS_FORWARD_TO_PREFETCH = 2;
8156
+ const MAX_NUMBER_OF_PARALLEL_LOADING_IMAGES = 8;
8157
+ /**
8158
+ * This prefetches all images connected to the same sync group as provided timerId
8159
+ * @param timerId The timerId
8160
+ * @param animationListValues List of animation steps in isostring to animate
8161
+ * @param targets List of targets to check
8162
+ * @returns True if all maps are ready to go forward, false if the map has no data to display yet.
8163
+ */
8164
+ const prefetchAnimationTargetsForMetronome = (timerId, animationListValues, targets) => {
8165
+ let timerShouldStepForward = true;
8166
+ // The following code prefetches/buffers for all maps in the group
8167
+ for (let numPrefetch = 0; numPrefetch < MAX_NUMBER_STEPS_FORWARD_TO_PREFETCH; numPrefetch += 1) {
8168
+ const nextStep = getNextStep(timerId, animationListValues.length, numPrefetch + 1);
8169
+ const nextTimeValueStepToCheck = animationListValues[nextStep];
8170
+ for (const target of targets) {
8171
+ const targetMapId = target.targetId;
8172
+ const wmMap = getWMJSMapById(targetMapId);
8173
+ if (wmMap) {
8174
+ const layersImageUrls = getWMSRequests(wmMap, [{
8175
+ name: 'time',
8176
+ currentValue: nextTimeValueStepToCheck
8177
+ }]);
8178
+ for (const layersImageUrl of layersImageUrls) {
8179
+ const image = wmMap.getMapImageStore.getImage(layersImageUrl.url);
8180
+ if (!image.isLoaded()) {
8181
+ if (wmMap.getMapImageStore.getNumImagesLoading() < MAX_NUMBER_OF_PARALLEL_LOADING_IMAGES) {
8182
+ image.load();
8183
+ }
8184
+ if (numPrefetch === 0) {
8185
+ const altImage = wmMap.getAlternativeImage(layersImageUrl.url, wmMap.getBBOX(), true);
8186
+ // No alternative image available yet, so skipping animation.
8187
+ if (altImage.length === 0) {
8188
+ // This is useful to indicate that the map is loading and has nothing yet to display.
8189
+ // console.warn('No data available: Not stepping forward');
8190
+ timerShouldStepForward = false;
8191
+ }
8192
+ }
8193
+ } else if (image.isStale()) {
8194
+ if (wmMap.getMapImageStore.getNumImagesLoading() < MAX_NUMBER_OF_PARALLEL_LOADING_IMAGES) {
8195
+ image.forceReload(true);
8196
+ }
8197
+ }
8198
+ }
8199
+ } else {
8200
+ return false; // Map was not registered so there is nothing to prefetch
8201
+ }
8202
+ }
8203
+ }
8204
+ return timerShouldStepForward;
8205
+ };
8206
+
8207
+ /**
8208
+ * This handler is triggered by the metronome. An array of timerIds is given as argument.
8209
+ * It will update the animation loop of multiple maps and sliders
8210
+ * It will prefetch images for maps
8211
+ * @param timerIds string[] array of timerIds
8212
+ * @param listenerApi ListenerEffectAPI<CoreAppStore, Dispatch, unknown> listenerApi as received from listener
8213
+ */
8214
+ const metronomeHandler = (timerIds, listenerApi) => {
8215
+ const targetsWithUpdateValue = [];
8216
+ for (const timerId of timerIds) {
8217
+ const animationListValuesNameAndValue = getAnimationList(listenerApi.getState(), timerId);
8218
+ const animationListValues = animationListValuesNameAndValue.map(nameAndValue => nameAndValue.value);
8219
+ const targets = getTargets(listenerApi.getState(), {
8220
+ sourceId: timerId,
8221
+ origin: timerId
8222
+ }, SYNCGROUPS_TYPE_SETTIME);
8223
+ if (targets.length === 0) {
8224
+ // When there are no targets, default to one
8225
+ targets.push({
8226
+ targetId: timerId,
8227
+ value: ''
8228
+ });
8229
+ }
8230
+ const timerIsInDwell = handleTimerDwell(timerId, animationListValues.length);
8231
+ const timerShouldStepForward = prefetchAnimationTargetsForMetronome(timerId, animationListValues, targets) && !timerIsInDwell;
8232
+ // Determine the next step
8233
+ const timerStep = timerShouldStepForward ? getNextStep(timerId, animationListValues.length) : getCurrentStep(timerId);
8234
+ setStep(timerId, timerStep);
8235
+ const updatedValue = animationListValues[timerStep];
8236
+ targetsWithUpdateValue.push(...targets.map(target => {
8237
+ return Object.assign(Object.assign({}, target), {
8238
+ value: updatedValue
8239
+ });
8240
+ }));
8241
+ const speedDelay = getMapAnimationDelay(listenerApi.getState(), timerId);
8242
+ const speed = 1000 / (speedDelay || 1);
8243
+ metronome.setSpeed(timerId, speed);
8244
+ }
8245
+ // Update all targets of all sync groups in one action.
8246
+ if (targetsWithUpdateValue.length > 0) {
8247
+ listenerApi.dispatch(setTimeSync(null, targetsWithUpdateValue, ['metronomesaga']));
8248
+ }
8249
+ };
8250
+ const metronomeListener = createListenerMiddleware();
8251
+ metronomeListener.startListening({
8252
+ actionCreator: mapActions.mapStartAnimation,
8253
+ effect: (_, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
8254
+ // register handler with access to listenerApi
8255
+ metronome.handleTimerTicks = timerIds => {
8256
+ metronomeHandler(timerIds, listenerApi);
8257
+ };
8258
+ })
8259
+ });
8260
+
8261
+ /* *
8262
+ * Licensed under the Apache License, Version 2.0 (the "License");
8263
+ * you may not use this file except in compliance with the License.
8264
+ * You may obtain a copy of the License at
8265
+ *
8266
+ * http://www.apache.org/licenses/LICENSE-2.0
8267
+ *
8268
+ * Unless required by applicable law or agreed to in writing, software
8269
+ * distributed under the License is distributed on an "AS IS" BASIS,
8270
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8271
+ * See the License for the specific language governing permissions and
8272
+ * limitations under the License.
8273
+ *
8274
+ * Copyright 2024 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
8275
+ * Copyright 2024 - Finnish Meteorological Institute (FMI)
8276
+ * */
8277
+ const layersListener = createListenerMiddleware();
8278
+ layersListener.startListening({
8279
+ actionCreator: layerActions.showLayerInfo,
8280
+ effect: ({
8281
+ payload
8377
8282
  }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
8378
8283
  const {
8379
8284
  mapId,
@@ -8461,6 +8366,126 @@ mapUiListener.startListening({
8461
8366
  })
8462
8367
  });
8463
8368
 
8369
+ const mapListener = createListenerMiddleware();
8370
+ const updateAnimation = (mapId, maxValue, listenerApi) => {
8371
+ const shouldEndtimeOverride$1 = shouldEndtimeOverride(listenerApi.getState(), mapId);
8372
+ if (shouldEndtimeOverride$1 === true) {
8373
+ return;
8374
+ }
8375
+ const animationStart = getAnimationStartTime(listenerApi.getState(), mapId);
8376
+ // Calculate how much time the animation start need to move forwards
8377
+ const animationEnd = getAnimationEndTime(listenerApi.getState(), mapId);
8378
+ const animationEndUnix = dateUtils.unix(dateUtils.utc(animationEnd));
8379
+ const maxTimeAsUnix = dateUtils.unix(dateUtils.utc(maxValue));
8380
+ const timeInSecondToShiftAnimationForwards = maxTimeAsUnix - animationEndUnix;
8381
+ const animationStartUnix = dateUtils.unix(dateUtils.utc(animationStart));
8382
+ const newAnimationStartTime = dateUtils.dateToString(dateUtils.fromUnix(animationStartUnix + timeInSecondToShiftAnimationForwards), dateFormat);
8383
+ const newAnimationEndTime = dateUtils.dateToString(dateUtils.fromUnix(animationEndUnix + timeInSecondToShiftAnimationForwards), dateFormat);
8384
+ if (!newAnimationStartTime || !newAnimationEndTime) {
8385
+ return;
8386
+ }
8387
+ listenerApi.dispatch(mapActions.setAnimationEndTime({
8388
+ mapId,
8389
+ animationEndTime: newAnimationEndTime
8390
+ }));
8391
+ listenerApi.dispatch(mapActions.setAnimationStartTime({
8392
+ mapId,
8393
+ animationStartTime: newAnimationStartTime
8394
+ }));
8395
+ };
8396
+ mapListener.startListening({
8397
+ actionCreator: mapActions.toggleAutoUpdate,
8398
+ effect: ({
8399
+ payload
8400
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
8401
+ listenerApi.cancelActiveListeners();
8402
+ const {
8403
+ shouldAutoUpdate,
8404
+ mapId
8405
+ } = payload;
8406
+ if (!shouldAutoUpdate) {
8407
+ return;
8408
+ }
8409
+ try {
8410
+ const autoUpdateLayerId = getAutoUpdateLayerId(listenerApi.getState(), mapId);
8411
+ const timeDimension = getLayerTimeDimension(listenerApi.getState(), autoUpdateLayerId);
8412
+ const syncedMapIds = getSyncedMapIdsForTimeslider(listenerApi.getState());
8413
+ // go to end of active layer
8414
+ if ((timeDimension === null || timeDimension === void 0 ? void 0 : timeDimension.maxValue) && autoUpdateLayerId) {
8415
+ listenerApi.dispatch(layerActions.layerChangeDimension({
8416
+ layerId: autoUpdateLayerId,
8417
+ origin: LayerActionOrigin.toggleAutoUpdateListener,
8418
+ dimension: {
8419
+ name: 'time',
8420
+ currentValue: timeDimension.maxValue
8421
+ }
8422
+ }));
8423
+ // Change time value for all timesliders that are synced by syncgroups
8424
+ if (syncedMapIds.length > 0) {
8425
+ syncedMapIds.map(syncedMapId => listenerApi.dispatch(setTime({
8426
+ origin: LayerActionOrigin.toggleAutoUpdateListener,
8427
+ sourceId: syncedMapId,
8428
+ value: timeDimension.maxValue
8429
+ })));
8430
+ }
8431
+ updateAnimation(mapId, timeDimension.maxValue, listenerApi);
8432
+ }
8433
+ // Toggle autoupdate off for synced timesliders
8434
+ const payloads = syncedMapIds.reduce((syncedMapIdList, syncedMapId) => {
8435
+ if (syncedMapId !== mapId) {
8436
+ return syncedMapIdList.concat({
8437
+ mapId: syncedMapId,
8438
+ shouldAutoUpdate: false
8439
+ });
8440
+ }
8441
+ return syncedMapIdList;
8442
+ }, []);
8443
+ if (payloads.length > 0) {
8444
+ payloads.map(payload => listenerApi.dispatch(mapActions.toggleAutoUpdate(payload)));
8445
+ }
8446
+ } catch (error) {
8447
+ // eslint-disable-next-line no-console
8448
+ console.warn(error);
8449
+ }
8450
+ })
8451
+ });
8452
+ mapListener.startListening({
8453
+ actionCreator: mapActions.mapStartAnimation,
8454
+ effect: ({
8455
+ payload
8456
+ }, listenerApi) => {
8457
+ const {
8458
+ mapId,
8459
+ initialTime
8460
+ } = payload;
8461
+ const speedDelay = getMapAnimationDelay(listenerApi.getState(), mapId);
8462
+ const speed = 1000 / (speedDelay || 1);
8463
+ metronome.register(null, speed, mapId);
8464
+ const timeList = getAnimationList(listenerApi.getState(), mapId);
8465
+ // In case of the timeList
8466
+ if (timeList && timeList.length > 0) {
8467
+ // Determine animation step based on initialTime and timeList
8468
+ const initalTimerStep = timeList === null || timeList === void 0 ? void 0 : timeList.findIndex(timeNameValue => {
8469
+ return timeNameValue.value === initialTime;
8470
+ });
8471
+ if (initalTimerStep !== -1) {
8472
+ setStep(mapId, initalTimerStep);
8473
+ }
8474
+ }
8475
+ }
8476
+ });
8477
+ mapListener.startListening({
8478
+ actionCreator: mapActions.mapStopAnimation,
8479
+ effect: ({
8480
+ payload
8481
+ }) => {
8482
+ const {
8483
+ mapId
8484
+ } = payload;
8485
+ metronome.unregister(mapId);
8486
+ }
8487
+ });
8488
+
8464
8489
  // TODO: This fixes typecheck errors but maybe there is a better way to do that
8465
8490
  createStore$1({
8466
8491
  extensions: [getSagaExtension()]
@@ -8473,8 +8498,8 @@ const mapStoreReducers = {
8473
8498
  const mapStoreModuleConfig = {
8474
8499
  id: 'webmap-module',
8475
8500
  reducersMap: mapStoreReducers,
8476
- sagas: [rootSaga$4, rootSaga$3],
8477
- middlewares: [metronomeListener.middleware, layersListener.middleware, mapUiListener.middleware]
8501
+ sagas: [rootSaga$2, rootSaga$1],
8502
+ middlewares: [metronomeListener.middleware, layersListener.middleware, mapUiListener.middleware, mapListener.middleware]
8478
8503
  };
8479
8504
 
8480
8505
  const mapStoreActions = Object.assign(Object.assign(Object.assign({}, layerActions), mapActions), serviceActions);
@@ -8673,132 +8698,55 @@ const getMapBaseLayerActionsTargets = (state, payload, actionType) => {
8673
8698
  };
8674
8699
 
8675
8700
  const setTimeValidatorRexexp = /^(19|20)\d\d-(0[1-9]|1[012])-([012]\d|3[01])T([01]\d|2[0-3]):([0-5]\d):([0-5]\d)Z$/;
8676
- function* setTimeSaga({
8677
- payload
8678
- }) {
8679
- const {
8680
- value,
8681
- origin
8682
- } = payload;
8683
- /* Test if the value is according to the expected time format */
8684
- if (!setTimeValidatorRexexp.test(value)) {
8685
- console.error(`setTime value ${value} does not conform to format [YYYY-MM-DDThh:mm:ssZ]. It was triggered by ${origin}`);
8686
- } else {
8687
- const targets = yield select(getTargets, payload, SYNCGROUPS_TYPE_SETTIME);
8688
- const groups = yield select(getTargetGroups, payload, SYNCGROUPS_TYPE_SETTIME);
8689
- yield put(setTimeSync(payload, targets, groups));
8690
- }
8691
- }
8692
- function* setBBoxSaga({
8693
- payload
8694
- }) {
8695
- const targets = yield select(getTargets, payload, SYNCGROUPS_TYPE_SETBBOX);
8696
- const groups = yield select(getTargetGroups, payload, SYNCGROUPS_TYPE_SETBBOX);
8697
- yield put(setBboxSync(payload, targets, groups));
8698
- }
8699
- function* layerActionsSaga({
8700
- payload,
8701
- type
8702
- }) {
8703
- /* Should not listen to actions from itself */
8704
- if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
8705
- return;
8706
- }
8707
- const targets = yield select(getLayerActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
8708
- if (targets && targets.length > 0) {
8709
- yield put(setLayerActionSync(payload, targets, type));
8710
- }
8711
- }
8712
- function* addLayerActionsSaga({
8713
- payload,
8714
- type
8715
- }) {
8716
- /* Should not listen to actions from itself */
8717
- if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
8718
- return;
8719
- }
8720
- const targets = yield select(getAddLayerActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
8721
- if (targets && targets.length > 0) {
8722
- yield put(setLayerActionSync(payload, targets, type));
8723
- }
8724
- }
8725
- function* duplicateMapLayerActionsSaga({
8726
- payload
8727
- }) {
8728
- const sourceLayer = yield select(getLayerById, payload.oldLayerId);
8729
- const newPayload = {
8730
- mapId: payload.mapId,
8731
- layer: sourceLayer,
8732
- origin: payload.origin
8733
- };
8734
- const targets = yield select(getAddLayerActionsTargets, newPayload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
8735
- if (targets && targets.length > 0) {
8736
- yield put(setLayerActionSync(newPayload, targets, layerActions.addLayer.type));
8737
- }
8738
- }
8739
- function* deleteLayerActionsSaga({
8740
- payload,
8741
- type
8742
- }) {
8743
- /* Should not listen to actions from itself */
8744
- if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
8745
- return;
8746
- }
8747
- const targets = yield select(getLayerDeleteActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
8748
- if (targets && targets.length > 0) {
8749
- yield put(setLayerActionSync(payload, targets, type));
8750
- }
8751
- }
8752
- function* moveLayerActionsSaga({
8753
- payload,
8754
- type
8755
- }) {
8756
- /* Should not listen to actions from itself */
8757
- if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
8758
- return;
8759
- }
8760
- const targets = yield select(getLayerMoveActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
8761
- if (targets && targets.length > 0) {
8762
- yield put(setLayerActionSync(payload, targets, type));
8763
- }
8764
- }
8765
- function* setAutoLayerIdActionsSaga({
8766
- payload,
8767
- type
8768
- }) {
8769
- const targets = yield select(getSetActiveLayerIdActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
8770
- if (targets && targets.length > 0) {
8771
- yield put(setLayerActionSync(payload, targets, type));
8772
- }
8773
- }
8774
- function* mapBaseLayerActionsSaga({
8775
- payload,
8776
- type
8777
- }) {
8778
- /* Should not listen to actions from itself */
8779
- if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
8780
- return;
8781
- }
8782
- const targets = yield select(getMapBaseLayerActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
8783
- if (targets && targets.length > 0) {
8784
- yield put(setLayerActionSync(payload, targets, type));
8785
- }
8786
- }
8787
- function* rootSaga$2() {
8788
- yield takeLatest(setTime.type, setTimeSaga);
8789
- yield takeLatest(setBbox.type, setBBoxSaga);
8790
- yield takeLatest(layerActions.layerChangeName.type, layerActionsSaga);
8791
- yield takeLatest(layerActions.layerChangeEnabled.type, layerActionsSaga);
8792
- yield takeLatest(layerActions.layerChangeOpacity.type, layerActionsSaga);
8793
- yield takeLatest(layerActions.layerChangeDimension.type, layerActionsSaga);
8794
- yield takeLatest(layerActions.layerChangeStyle.type, layerActionsSaga);
8795
- yield takeLatest(layerActions.layerDelete.type, deleteLayerActionsSaga);
8796
- yield takeLatest(layerActions.addLayer.type, addLayerActionsSaga);
8797
- yield takeLatest(layerActions.duplicateMapLayer.type, duplicateMapLayerActionsSaga);
8798
- yield takeLatest(mapActions.layerMoveLayer.type, moveLayerActionsSaga);
8799
- yield takeLatest(mapActions.setAutoLayerId.type, setAutoLayerIdActionsSaga);
8800
- yield takeLatest(layerActions.setBaseLayers.type, mapBaseLayerActionsSaga);
8801
- }
8701
+ const genericListener = createListenerMiddleware();
8702
+ genericListener.startListening({
8703
+ actionCreator: setTime,
8704
+ effect: ({
8705
+ payload
8706
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
8707
+ listenerApi.cancelActiveListeners();
8708
+ const {
8709
+ value,
8710
+ origin
8711
+ } = payload;
8712
+ /* Test if the value is according to the expected time format */
8713
+ if (!setTimeValidatorRexexp.test(value)) {
8714
+ console.error(`setTime value ${value} does not conform to format [YYYY-MM-DDThh:mm:ssZ]. It was triggered by ${origin}`);
8715
+ } else {
8716
+ const targets = getTargets(listenerApi.getState(), payload, SYNCGROUPS_TYPE_SETTIME);
8717
+ const groups = getTargetGroups(listenerApi.getState(), payload, SYNCGROUPS_TYPE_SETTIME);
8718
+ listenerApi.dispatch(setTimeSync(payload, targets, groups));
8719
+ }
8720
+ })
8721
+ });
8722
+ genericListener.startListening({
8723
+ actionCreator: setBbox,
8724
+ effect: ({
8725
+ payload
8726
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
8727
+ listenerApi.cancelActiveListeners();
8728
+ const targets = getTargets(listenerApi.getState(), payload, SYNCGROUPS_TYPE_SETBBOX);
8729
+ const groups = getTargetGroups(listenerApi.getState(), payload, SYNCGROUPS_TYPE_SETBBOX);
8730
+ listenerApi.dispatch(setBboxSync(payload, targets, groups));
8731
+ })
8732
+ });
8733
+ genericListener.startListening({
8734
+ matcher: isAnyOf(layerActions.layerChangeName, layerActions.layerChangeEnabled, layerActions.layerChangeOpacity, layerActions.layerChangeDimension, layerActions.layerChangeStyle),
8735
+ effect: ({
8736
+ payload,
8737
+ type
8738
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
8739
+ listenerApi.cancelActiveListeners();
8740
+ /* Should not listen to actions from itself */
8741
+ if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
8742
+ return;
8743
+ }
8744
+ const targets = getLayerActionsTargets(listenerApi.getState(), payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
8745
+ if (targets && targets.length > 0) {
8746
+ listenerApi.dispatch(setLayerActionSync(payload, targets, type));
8747
+ }
8748
+ })
8749
+ });
8802
8750
 
8803
8751
  /* *
8804
8752
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -8873,18 +8821,19 @@ var utils = /*#__PURE__*/Object.freeze({
8873
8821
  * See the License for the specific language governing permissions and
8874
8822
  * limitations under the License.
8875
8823
  *
8876
- * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
8877
- * Copyright 2023 - Finnish Meteorological Institute (FMI)
8824
+ * Copyright 2024 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
8825
+ * Copyright 2024 - Finnish Meteorological Institute (FMI)
8878
8826
  * */
8879
- function* navigateToUrlSaga(action) {
8880
- const {
8827
+ const routerListener = createListenerMiddleware();
8828
+ routerListener.startListening({
8829
+ actionCreator: routerActions.navigateToUrl,
8830
+ effect: ({
8881
8831
  payload
8882
- } = action;
8883
- yield call$e(historyDict.navigate, payload.url);
8884
- }
8885
- function* rootSaga$1() {
8886
- yield takeLatest(routerActions.navigateToUrl.type, navigateToUrlSaga);
8887
- }
8832
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
8833
+ listenerApi.cancelActiveListeners();
8834
+ historyDict.navigate(payload.url);
8835
+ })
8836
+ });
8888
8837
 
8889
8838
  /* *
8890
8839
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -8907,7 +8856,7 @@ const routerModuleConfig = {
8907
8856
  reducersMap: {
8908
8857
  router: reducer$1
8909
8858
  },
8910
- sagas: [rootSaga$1]
8859
+ middlewares: [routerListener.middleware]
8911
8860
  };
8912
8861
 
8913
8862
  // reducer utils
@@ -9133,195 +9082,212 @@ var selectors = /*#__PURE__*/Object.freeze({
9133
9082
  selectDrawToolById: selectDrawToolById
9134
9083
  });
9135
9084
 
9085
+ const drawingToolListener = createListenerMiddleware();
9136
9086
  const registerOrigin = 'drawings saga:registerDrawToolSaga';
9137
- function* registerDrawToolSaga({
9138
- payload
9139
- }) {
9140
- const {
9141
- mapId,
9142
- geoJSONLayerId,
9143
- geoJSONIntersectionLayerId,
9144
- geoJSONIntersectionBoundsLayerId,
9145
- defaultGeoJSON = emptyGeoJSON,
9146
- defaultGeoJSONIntersection = emptyGeoJSON,
9147
- defaultGeoJSONIntersectionBounds,
9148
- defaultGeoJSONIntersectionProperties = defaultIntersectionStyleProperties
9149
- } = payload;
9150
- // create for every drawTool a draw layer
9151
- if (geoJSONLayerId && mapId) {
9152
- yield put(mapStoreActions.addLayer({
9153
- mapId,
9154
- layer: {
9155
- // empty geoJSON
9156
- geojson: defaultGeoJSON,
9157
- layerType: LayerType.featureLayer
9158
- },
9159
- layerId: geoJSONLayerId,
9160
- origin: registerOrigin
9161
- }));
9162
- }
9163
- // create intersection layer
9164
- if (geoJSONIntersectionLayerId && mapId) {
9165
- yield put(mapStoreActions.addLayer({
9087
+ // register draw tool
9088
+ drawingToolListener.startListening({
9089
+ actionCreator: drawtoolActions.registerDrawTool,
9090
+ effect: ({
9091
+ payload
9092
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9093
+ listenerApi.cancelActiveListeners();
9094
+ const {
9166
9095
  mapId,
9167
- layer: {
9168
- geojson: defaultGeoJSONIntersection,
9169
- layerType: LayerType.featureLayer,
9170
- defaultGeoJSONProperties: defaultGeoJSONIntersectionProperties
9171
- },
9172
- layerId: geoJSONIntersectionLayerId,
9173
- origin: registerOrigin
9174
- }));
9175
- }
9176
- // create intersection bounds layer
9177
- if (geoJSONIntersectionBoundsLayerId && mapId) {
9178
- const existingBoundsLayer = yield select(getLayerById, geoJSONIntersectionBoundsLayerId);
9179
- // don't add a new boundslayer when another drawtool using that same boundslayer
9180
- if (!existingBoundsLayer) {
9181
- yield put(mapStoreActions.addLayer({
9096
+ geoJSONLayerId,
9097
+ geoJSONIntersectionLayerId,
9098
+ geoJSONIntersectionBoundsLayerId,
9099
+ defaultGeoJSON = emptyGeoJSON,
9100
+ defaultGeoJSONIntersection = emptyGeoJSON,
9101
+ defaultGeoJSONIntersectionBounds,
9102
+ defaultGeoJSONIntersectionProperties = defaultIntersectionStyleProperties
9103
+ } = payload;
9104
+ // create for every drawTool a draw layer
9105
+ if (geoJSONLayerId && mapId) {
9106
+ listenerApi.dispatch(mapStoreActions.addLayer({
9182
9107
  mapId,
9183
9108
  layer: {
9184
- geojson: defaultGeoJSONIntersectionBounds,
9109
+ // empty geoJSON
9110
+ geojson: defaultGeoJSON,
9185
9111
  layerType: LayerType.featureLayer
9186
9112
  },
9187
- layerId: geoJSONIntersectionBoundsLayerId,
9113
+ layerId: geoJSONLayerId,
9188
9114
  origin: registerOrigin
9189
9115
  }));
9190
9116
  }
9191
- yield put(layerActions.orderLayerToFront({
9192
- layerId: geoJSONIntersectionBoundsLayerId
9193
- }));
9194
- }
9195
- }
9196
- function* changeDrawToolSaga({
9197
- payload
9198
- }) {
9199
- var _a, _b, _c;
9200
- try {
9201
- const {
9202
- drawModeId,
9203
- drawToolId,
9204
- shouldUpdateShape = true
9205
- } = payload;
9206
- const drawingTool = yield select(selectDrawToolById, drawToolId);
9207
- const {
9208
- shouldAllowMultipleShapes = false,
9209
- geoJSONIntersectionLayerId,
9210
- geoJSONIntersectionBoundsLayerId
9211
- } = drawingTool;
9212
- const newDrawMode = yield select(getDrawModeById, drawToolId, drawModeId);
9213
- // disable layer when no new drawmode or when selecting same tool and is selectable
9214
- if (!newDrawMode || !drawingTool.activeDrawModeId && newDrawMode.isSelectable) {
9215
- yield put(layerActions.toggleFeatureMode({
9216
- layerId: drawingTool.geoJSONLayerId,
9217
- isInEditMode: false,
9218
- drawMode: ''
9117
+ // create intersection layer
9118
+ if (geoJSONIntersectionLayerId && mapId) {
9119
+ listenerApi.dispatch(mapStoreActions.addLayer({
9120
+ mapId,
9121
+ layer: {
9122
+ geojson: defaultGeoJSONIntersection,
9123
+ layerType: LayerType.featureLayer,
9124
+ defaultGeoJSONProperties: defaultGeoJSONIntersectionProperties
9125
+ },
9126
+ layerId: geoJSONIntersectionLayerId,
9127
+ origin: registerOrigin
9219
9128
  }));
9220
- const geoJSONLayer = yield select(getLayerById, drawingTool.geoJSONLayerId);
9221
- const geoJSON = geoJSONLayer === null || geoJSONLayer === void 0 ? void 0 : geoJSONLayer.geojson;
9222
- const lastFeatureIndex = geoJSON !== undefined ? getLastEmptyFeatureIndex(geoJSON) : undefined;
9223
- if (lastFeatureIndex !== undefined) {
9224
- const newGeoJSON = Object.assign(Object.assign({}, geoJSON), {
9225
- features: geoJSON.features.filter((_feature, index) => index !== lastFeatureIndex)
9226
- });
9227
- yield put(layerActions.updateFeature({
9228
- layerId: drawingTool.geoJSONLayerId,
9229
- geojson: newGeoJSON
9129
+ }
9130
+ // create intersection bounds layer
9131
+ if (geoJSONIntersectionBoundsLayerId && mapId) {
9132
+ const existingBoundsLayer = getLayerById(listenerApi.getState(), geoJSONIntersectionBoundsLayerId);
9133
+ // don't add a new boundslayer when another drawtool using that same boundslayer
9134
+ if (!existingBoundsLayer) {
9135
+ listenerApi.dispatch(mapStoreActions.addLayer({
9136
+ mapId,
9137
+ layer: {
9138
+ geojson: defaultGeoJSONIntersectionBounds,
9139
+ layerType: LayerType.featureLayer
9140
+ },
9141
+ layerId: geoJSONIntersectionBoundsLayerId,
9142
+ origin: registerOrigin
9230
9143
  }));
9231
- yield put(layerActions.setSelectedFeature({
9144
+ }
9145
+ listenerApi.dispatch(layerActions.orderLayerToFront({
9146
+ layerId: geoJSONIntersectionBoundsLayerId
9147
+ }));
9148
+ }
9149
+ })
9150
+ });
9151
+ // change draw tool
9152
+ drawingToolListener.startListening({
9153
+ actionCreator: drawtoolActions.changeDrawToolMode,
9154
+ effect: ({
9155
+ payload
9156
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9157
+ var _a, _b, _c;
9158
+ listenerApi.cancelActiveListeners();
9159
+ try {
9160
+ const {
9161
+ drawModeId,
9162
+ drawToolId,
9163
+ shouldUpdateShape = true
9164
+ } = payload;
9165
+ const drawingTool = selectDrawToolById(listenerApi.getState(), drawToolId);
9166
+ if (!drawingTool) {
9167
+ return;
9168
+ }
9169
+ const {
9170
+ shouldAllowMultipleShapes = false,
9171
+ geoJSONIntersectionLayerId,
9172
+ geoJSONIntersectionBoundsLayerId
9173
+ } = drawingTool;
9174
+ const newDrawMode = getDrawModeById(listenerApi.getState(), drawToolId, drawModeId);
9175
+ // disable layer when no new drawmode or when selecting same tool and is selectable
9176
+ if (!newDrawMode || !drawingTool.activeDrawModeId && newDrawMode.isSelectable) {
9177
+ listenerApi.dispatch(layerActions.toggleFeatureMode({
9232
9178
  layerId: drawingTool.geoJSONLayerId,
9233
- selectedFeatureIndex: newGeoJSON.features.length > 0 ? newGeoJSON.features.length - 1 : 0
9179
+ isInEditMode: false,
9180
+ drawMode: ''
9234
9181
  }));
9182
+ const geoJSONLayer = getLayerById(listenerApi.getState(), drawingTool.geoJSONLayerId);
9183
+ const geoJSON = geoJSONLayer === null || geoJSONLayer === void 0 ? void 0 : geoJSONLayer.geojson;
9184
+ const lastFeatureIndex = geoJSON !== undefined ? getLastEmptyFeatureIndex(geoJSON) : undefined;
9185
+ if (lastFeatureIndex !== undefined) {
9186
+ const newGeoJSON = Object.assign(Object.assign({}, geoJSON), {
9187
+ features: geoJSON.features.filter((_feature, index) => index !== lastFeatureIndex)
9188
+ });
9189
+ listenerApi.dispatch(layerActions.updateFeature({
9190
+ layerId: drawingTool.geoJSONLayerId,
9191
+ geojson: newGeoJSON
9192
+ }));
9193
+ listenerApi.dispatch(layerActions.setSelectedFeature({
9194
+ layerId: drawingTool.geoJSONLayerId,
9195
+ selectedFeatureIndex: newGeoJSON.features.length > 0 ? newGeoJSON.features.length - 1 : 0
9196
+ }));
9197
+ }
9198
+ return;
9235
9199
  }
9236
- return;
9237
- }
9238
- // delete shape
9239
- if (newDrawMode.value === 'DELETE') {
9240
- yield put(layerActions.layerChangeGeojson({
9241
- layerId: drawingTool.geoJSONLayerId,
9242
- geojson: emptyGeoJSON
9243
- }));
9244
- // clear intersection shape
9245
- if (geoJSONIntersectionLayerId) {
9246
- yield put(layerActions.layerChangeGeojson({
9247
- layerId: geoJSONIntersectionLayerId,
9200
+ // delete shape
9201
+ if (newDrawMode.value === 'DELETE') {
9202
+ listenerApi.dispatch(layerActions.layerChangeGeojson({
9203
+ layerId: drawingTool.geoJSONLayerId,
9248
9204
  geojson: emptyGeoJSON
9249
9205
  }));
9206
+ // clear intersection shape
9207
+ if (geoJSONIntersectionLayerId) {
9208
+ listenerApi.dispatch(layerActions.layerChangeGeojson({
9209
+ layerId: geoJSONIntersectionLayerId,
9210
+ geojson: emptyGeoJSON
9211
+ }));
9212
+ }
9213
+ listenerApi.dispatch(layerActions.toggleFeatureMode({
9214
+ layerId: drawingTool.geoJSONLayerId,
9215
+ isInEditMode: false,
9216
+ drawMode: ''
9217
+ }));
9218
+ return;
9219
+ }
9220
+ // check tool is selected of existing drawn shape
9221
+ const currentGeoJSONLayer = getLayerById(listenerApi.getState(), drawingTool.geoJSONLayerId);
9222
+ const {
9223
+ geojson: currentGeoJSON,
9224
+ selectedFeatureIndex = 0
9225
+ } = currentGeoJSONLayer || {};
9226
+ const currentSelectionType = (_b = (_a = currentGeoJSON === null || currentGeoJSON === void 0 ? void 0 : currentGeoJSON.features[selectedFeatureIndex]) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.selectionType;
9227
+ const newSelectionType = newDrawMode.selectionType;
9228
+ const isNewToolSelected = currentSelectionType !== newSelectionType;
9229
+ const shouldUpdateNewShape = !((_c = currentGeoJSON === null || currentGeoJSON === void 0 ? void 0 : currentGeoJSON.features) === null || _c === void 0 ? void 0 : _c.length) || isNewToolSelected || !newDrawMode.isSelectable && shouldAllowMultipleShapes;
9230
+ // don't change anything if same tool is selected again
9231
+ if (shouldUpdateNewShape && shouldUpdateShape) {
9232
+ const shapeWithSelectionType = addSelectionTypeToGeoJSON(newDrawMode.shape, newDrawMode.selectionType);
9233
+ const geoJSONFeatureCollection = getFeatureCollection(shapeWithSelectionType, shouldAllowMultipleShapes, currentGeoJSON);
9234
+ const newGeoJSON = getGeoJson(geoJSONFeatureCollection, shouldAllowMultipleShapes);
9235
+ if (shouldAllowMultipleShapes) {
9236
+ moveFeature(currentGeoJSON, newGeoJSON, selectedFeatureIndex, '');
9237
+ }
9238
+ listenerApi.dispatch(layerActions.setSelectedFeature({
9239
+ layerId: drawingTool.geoJSONLayerId,
9240
+ selectedFeatureIndex: newGeoJSON.features.length - 1
9241
+ }));
9242
+ listenerApi.dispatch(layerActions.updateFeature(Object.assign(Object.assign({
9243
+ layerId: drawingTool.geoJSONLayerId,
9244
+ geojson: newGeoJSON
9245
+ }, geoJSONIntersectionLayerId && {
9246
+ geoJSONIntersectionLayerId
9247
+ }), geoJSONIntersectionBoundsLayerId && {
9248
+ geoJSONIntersectionBoundsLayerId
9249
+ })));
9250
9250
  }
9251
- yield put(layerActions.toggleFeatureMode({
9251
+ listenerApi.dispatch(layerActions.toggleFeatureMode({
9252
9252
  layerId: drawingTool.geoJSONLayerId,
9253
- isInEditMode: false,
9254
- drawMode: ''
9253
+ isInEditMode: newDrawMode.isSelectable,
9254
+ drawMode: newDrawMode.value
9255
9255
  }));
9256
- return;
9256
+ } catch (error) {
9257
+ // eslint-disable-next-line no-console
9258
+ console.log('error changeDrawToolSaga', error);
9257
9259
  }
9258
- // check tool is selected of existing drawn shape
9259
- const currentGeoJSONLayer = yield select(getLayerById, drawingTool.geoJSONLayerId);
9260
+ })
9261
+ });
9262
+ // change intersection
9263
+ drawingToolListener.startListening({
9264
+ actionCreator: drawtoolActions.changeIntersectionBounds,
9265
+ effect: ({
9266
+ payload
9267
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9268
+ listenerApi.cancelActiveListeners();
9260
9269
  const {
9261
- geojson: currentGeoJSON,
9262
- selectedFeatureIndex = 0
9263
- } = currentGeoJSONLayer || {};
9264
- const currentSelectionType = (_b = (_a = currentGeoJSON === null || currentGeoJSON === void 0 ? void 0 : currentGeoJSON.features[selectedFeatureIndex]) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.selectionType;
9265
- const newSelectionType = newDrawMode.selectionType;
9266
- const isNewToolSelected = currentSelectionType !== newSelectionType;
9267
- const shouldUpdateNewShape = !((_c = currentGeoJSON === null || currentGeoJSON === void 0 ? void 0 : currentGeoJSON.features) === null || _c === void 0 ? void 0 : _c.length) || isNewToolSelected || !newDrawMode.isSelectable && shouldAllowMultipleShapes;
9268
- // don't change anything if same tool is selected again
9269
- if (shouldUpdateNewShape && shouldUpdateShape) {
9270
- const shapeWithSelectionType = addSelectionTypeToGeoJSON(newDrawMode.shape, newDrawMode.selectionType);
9271
- const geoJSONFeatureCollection = getFeatureCollection(shapeWithSelectionType, shouldAllowMultipleShapes, currentGeoJSON);
9272
- const newGeoJSON = getGeoJson(geoJSONFeatureCollection, shouldAllowMultipleShapes);
9273
- if (shouldAllowMultipleShapes) {
9274
- moveFeature(currentGeoJSON, newGeoJSON, selectedFeatureIndex, '');
9275
- }
9276
- yield put(layerActions.setSelectedFeature({
9277
- layerId: drawingTool.geoJSONLayerId,
9278
- selectedFeatureIndex: newGeoJSON.features.length - 1
9279
- }));
9280
- yield put(layerActions.updateFeature(Object.assign(Object.assign({
9281
- layerId: drawingTool.geoJSONLayerId,
9282
- geojson: newGeoJSON
9283
- }, geoJSONIntersectionLayerId && {
9284
- geoJSONIntersectionLayerId
9285
- }), geoJSONIntersectionBoundsLayerId && {
9286
- geoJSONIntersectionBoundsLayerId
9287
- })));
9270
+ drawToolId,
9271
+ geoJSON
9272
+ } = payload;
9273
+ const drawtool = selectDrawToolById(listenerApi.getState(), drawToolId);
9274
+ if (!drawtool) {
9275
+ return;
9288
9276
  }
9289
- yield put(layerActions.toggleFeatureMode({
9290
- layerId: drawingTool.geoJSONLayerId,
9291
- isInEditMode: newDrawMode.isSelectable,
9292
- drawMode: newDrawMode.value
9277
+ listenerApi.dispatch(layerActions.layerChangeGeojson({
9278
+ layerId: drawtool.geoJSONIntersectionBoundsLayerId,
9279
+ geojson: geoJSON
9293
9280
  }));
9294
- } catch (error) {
9295
- // eslint-disable-next-line no-console
9296
- console.log('error changeDrawToolSaga', error);
9297
- }
9298
- }
9299
- function* changeIntersectionSaga({
9300
- payload
9301
- }) {
9302
- const {
9303
- drawToolId,
9304
- geoJSON
9305
- } = payload;
9306
- const drawtool = yield select(selectDrawToolById, drawToolId);
9307
- yield put(layerActions.layerChangeGeojson({
9308
- layerId: drawtool.geoJSONIntersectionBoundsLayerId,
9309
- geojson: geoJSON
9310
- }));
9311
- yield put(layerActions.layerChangeGeojson({
9312
- layerId: drawtool.geoJSONLayerId,
9313
- geojson: emptyGeoJSON
9314
- }));
9315
- yield put(layerActions.layerChangeGeojson({
9316
- layerId: drawtool.geoJSONIntersectionLayerId,
9317
- geojson: emptyGeoJSON
9318
- }));
9319
- }
9320
- function* drawingSaga() {
9321
- yield takeLatest(drawtoolActions.registerDrawTool, registerDrawToolSaga);
9322
- yield takeLatest(drawtoolActions.changeDrawToolMode, changeDrawToolSaga);
9323
- yield takeLatest(drawtoolActions.changeIntersectionBounds, changeIntersectionSaga);
9324
- }
9281
+ listenerApi.dispatch(layerActions.layerChangeGeojson({
9282
+ layerId: drawtool.geoJSONLayerId,
9283
+ geojson: emptyGeoJSON
9284
+ }));
9285
+ listenerApi.dispatch(layerActions.layerChangeGeojson({
9286
+ layerId: drawtool.geoJSONIntersectionLayerId,
9287
+ geojson: emptyGeoJSON
9288
+ }));
9289
+ })
9290
+ });
9325
9291
 
9326
9292
  /* *
9327
9293
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -9344,7 +9310,7 @@ const drawtoolModuleConfig = {
9344
9310
  reducersMap: {
9345
9311
  drawingtools: reducer
9346
9312
  },
9347
- sagas: [drawingSaga]
9313
+ middlewares: [drawingToolListener.middleware]
9348
9314
  };
9349
9315
 
9350
9316
  /* *
@@ -9648,82 +9614,163 @@ var storeTestUtils = /*#__PURE__*/Object.freeze({
9648
9614
  * Copyright 2020 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
9649
9615
  * Copyright 2020 - Finnish Meteorological Institute (FMI)
9650
9616
  * */
9651
- function* updateSourceValueWhenLinkingComponentToGroupSaga(groupId, targetToUpdate) {
9652
- const group = yield select(getSynchronizationGroup, groupId);
9653
- if (!group) {
9617
+ function* addLayerActionsSaga({
9618
+ payload,
9619
+ type
9620
+ }) {
9621
+ /* Should not listen to actions from itself */
9622
+ if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
9654
9623
  return;
9655
9624
  }
9656
- switch (group.type) {
9657
- case SYNCGROUPS_TYPE_SETTIME:
9658
- if (!group.payloadByType[SYNCGROUPS_TYPE_SETTIME]) {
9659
- return;
9660
- }
9661
- yield put(setTimeSync(group.payloadByType[SYNCGROUPS_TYPE_SETTIME], [{
9662
- targetId: targetToUpdate,
9663
- value: group.payloadByType[SYNCGROUPS_TYPE_SETTIME].value
9664
- }], [groupId]));
9665
- break;
9666
- case SYNCGROUPS_TYPE_SETBBOX:
9667
- if (!group.payloadByType[SYNCGROUPS_TYPE_SETBBOX]) {
9668
- return;
9669
- }
9670
- yield put(setBboxSync(group.payloadByType[SYNCGROUPS_TYPE_SETBBOX], [{
9671
- targetId: targetToUpdate,
9672
- bbox: group.payloadByType[SYNCGROUPS_TYPE_SETBBOX].bbox,
9673
- srs: group.payloadByType[SYNCGROUPS_TYPE_SETBBOX].srs
9674
- }], [groupId]));
9675
- break;
9625
+ const targets = yield select(getAddLayerActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
9626
+ if (targets && targets.length > 0) {
9627
+ yield put(setLayerActionSync(payload, targets, type));
9676
9628
  }
9677
9629
  }
9678
- function* addGroupTargetSaga({
9630
+ function* duplicateMapLayerActionsSaga({
9679
9631
  payload
9680
9632
  }) {
9681
- const {
9682
- groupId,
9683
- linked,
9684
- targetId: targetToUpdate
9685
- } = payload;
9686
- if (!linked) {
9687
- yield call$e(updateSourceValueWhenLinkingComponentToGroupSaga, groupId, targetToUpdate);
9633
+ const sourceLayer = yield select(getLayerById, payload.oldLayerId);
9634
+ const newPayload = {
9635
+ mapId: payload.mapId,
9636
+ layer: sourceLayer,
9637
+ origin: payload.origin
9638
+ };
9639
+ const targets = yield select(getAddLayerActionsTargets, newPayload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
9640
+ if (targets && targets.length > 0) {
9641
+ yield put(setLayerActionSync(newPayload, targets, layerActions.addLayer.type));
9688
9642
  }
9689
9643
  }
9690
- function* linkGroupTargetSaga({
9691
- payload
9644
+ function* deleteLayerActionsSaga({
9645
+ payload,
9646
+ type
9692
9647
  }) {
9693
- const {
9694
- groupId,
9695
- linked,
9696
- targetId: targetToUpdate
9697
- } = payload;
9698
- if (!linked) {
9699
- yield call$e(updateSourceValueWhenLinkingComponentToGroupSaga, groupId, targetToUpdate);
9648
+ /* Should not listen to actions from itself */
9649
+ if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
9650
+ return;
9651
+ }
9652
+ const targets = yield select(getLayerDeleteActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
9653
+ if (targets && targets.length > 0) {
9654
+ yield put(setLayerActionSync(payload, targets, type));
9700
9655
  }
9701
9656
  }
9702
- function* updateViewStateSaga() {
9703
- const viewState = yield select(createSyncGroupViewStateSelector);
9704
- yield put(syncGroupSetViewState({
9705
- viewState
9706
- }));
9657
+ function* moveLayerActionsSaga({
9658
+ payload,
9659
+ type
9660
+ }) {
9661
+ /* Should not listen to actions from itself */
9662
+ if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
9663
+ return;
9664
+ }
9665
+ const targets = yield select(getLayerMoveActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
9666
+ if (targets && targets.length > 0) {
9667
+ yield put(setLayerActionSync(payload, targets, type));
9668
+ }
9669
+ }
9670
+ function* setAutoLayerIdActionsSaga({
9671
+ payload,
9672
+ type
9673
+ }) {
9674
+ const targets = yield select(getSetActiveLayerIdActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
9675
+ if (targets && targets.length > 0) {
9676
+ yield put(setLayerActionSync(payload, targets, type));
9677
+ }
9678
+ }
9679
+ function* mapBaseLayerActionsSaga({
9680
+ payload,
9681
+ type
9682
+ }) {
9683
+ /* Should not listen to actions from itself */
9684
+ if (payload && payload.origin === LayerActionOrigin.ReactMapViewParseLayer) {
9685
+ return;
9686
+ }
9687
+ const targets = yield select(getMapBaseLayerActionsTargets, payload, SYNCGROUPS_TYPE_SETLAYERACTIONS);
9688
+ if (targets && targets.length > 0) {
9689
+ yield put(setLayerActionSync(payload, targets, type));
9690
+ }
9707
9691
  }
9708
9692
  function* rootSaga() {
9709
- yield takeLatest(syncGroupAddTarget.type, addGroupTargetSaga);
9710
- yield takeLatest(syncGroupLinkTarget.type, linkGroupTargetSaga);
9711
- yield takeLatest(syncGroupAddGroup.type, updateViewStateSaga);
9712
- yield takeLatest(syncGroupRemoveGroup.type, updateViewStateSaga);
9713
- yield takeLatest(syncGroupAddSource.type, updateViewStateSaga);
9714
- yield takeLatest(syncGroupRemoveSource.type, updateViewStateSaga);
9715
- yield takeLatest(syncGroupAddTarget.type, updateViewStateSaga);
9716
- yield takeLatest(syncGroupRemoveTarget.type, updateViewStateSaga);
9717
- yield takeLatest(syncGroupLinkTarget.type, updateViewStateSaga);
9693
+ yield takeLatest(layerActions.layerDelete.type, deleteLayerActionsSaga);
9694
+ yield takeLatest(layerActions.addLayer.type, addLayerActionsSaga);
9695
+ yield takeLatest(layerActions.duplicateMapLayer.type, duplicateMapLayerActionsSaga);
9696
+ yield takeLatest(mapActions.layerMoveLayer.type, moveLayerActionsSaga);
9697
+ yield takeLatest(mapActions.setAutoLayerId.type, setAutoLayerIdActionsSaga);
9698
+ yield takeLatest(layerActions.setBaseLayers.type, mapBaseLayerActionsSaga);
9718
9699
  }
9719
9700
 
9701
+ /* *
9702
+ * Licensed under the Apache License, Version 2.0 (the "License");
9703
+ * you may not use this file except in compliance with the License.
9704
+ * You may obtain a copy of the License at
9705
+ *
9706
+ * http://www.apache.org/licenses/LICENSE-2.0
9707
+ *
9708
+ * Unless required by applicable law or agreed to in writing, software
9709
+ * distributed under the License is distributed on an "AS IS" BASIS,
9710
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9711
+ * See the License for the specific language governing permissions and
9712
+ * limitations under the License.
9713
+ *
9714
+ * Copyright 2024 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
9715
+ * Copyright 2024 - Finnish Meteorological Institute (FMI)
9716
+ * */
9717
+ const syncGroupsListener = createListenerMiddleware();
9718
+ syncGroupsListener.startListening({
9719
+ matcher: isAnyOf(actions.syncGroupAddTarget, actions.syncGroupLinkTarget),
9720
+ effect: ({
9721
+ payload
9722
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9723
+ listenerApi.cancelActiveListeners();
9724
+ const {
9725
+ groupId,
9726
+ linked,
9727
+ targetId: targetToUpdate
9728
+ } = payload;
9729
+ const group = getSynchronizationGroup(listenerApi.getState(), groupId);
9730
+ if (!linked && group) {
9731
+ switch (group.type) {
9732
+ case SYNCGROUPS_TYPE_SETTIME:
9733
+ if (!group.payloadByType[SYNCGROUPS_TYPE_SETTIME]) {
9734
+ return;
9735
+ }
9736
+ listenerApi.dispatch(setTimeSync(group.payloadByType[SYNCGROUPS_TYPE_SETTIME], [{
9737
+ targetId: targetToUpdate,
9738
+ value: group.payloadByType[SYNCGROUPS_TYPE_SETTIME].value
9739
+ }], [groupId]));
9740
+ break;
9741
+ case SYNCGROUPS_TYPE_SETBBOX:
9742
+ if (!group.payloadByType[SYNCGROUPS_TYPE_SETBBOX]) {
9743
+ return;
9744
+ }
9745
+ listenerApi.dispatch(setBboxSync(group.payloadByType[SYNCGROUPS_TYPE_SETBBOX], [{
9746
+ targetId: targetToUpdate,
9747
+ bbox: group.payloadByType[SYNCGROUPS_TYPE_SETBBOX].bbox,
9748
+ srs: group.payloadByType[SYNCGROUPS_TYPE_SETBBOX].srs
9749
+ }], [groupId]));
9750
+ break;
9751
+ }
9752
+ }
9753
+ })
9754
+ });
9755
+ syncGroupsListener.startListening({
9756
+ matcher: isAnyOf(actions.syncGroupAddGroup, actions.syncGroupRemoveGroup, actions.syncGroupAddSource, actions.syncGroupRemoveSource, actions.syncGroupAddTarget, actions.syncGroupRemoveTarget, actions.syncGroupLinkTarget),
9757
+ effect: (_, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9758
+ listenerApi.cancelActiveListeners();
9759
+ const viewState = createSyncGroupViewStateSelector(listenerApi.getState());
9760
+ listenerApi.dispatch(actions.syncGroupSetViewState({
9761
+ viewState
9762
+ }));
9763
+ })
9764
+ });
9765
+
9720
9766
  const synchronizationGroupConfig = {
9721
9767
  id: 'syncronizationGroupStore-module',
9722
9768
  reducersMap: {
9723
9769
  syncronizationGroupStore: reducer$3,
9724
9770
  loadingIndicatorStore: loadingIndicatorReducer
9725
9771
  },
9726
- sagas: [rootSaga$2, rootSaga]
9772
+ sagas: [rootSaga],
9773
+ middlewares: [genericListener.middleware, syncGroupsListener.middleware]
9727
9774
  };
9728
9775
 
9729
9776
  /* *
@@ -9769,7 +9816,7 @@ const coreModuleConfig = [mapStoreModuleConfig, synchronizationGroupConfig, uiMo
9769
9816
 
9770
9817
  const createStore = () => createStore$1({
9771
9818
  extensions: [getSagaExtension({}), {
9772
- middlewares: [metronomeListener.middleware]
9819
+ middlewares: [metronomeListener.middleware, mapListener.middleware]
9773
9820
  }]
9774
9821
  });
9775
9822
  const WrapperWithModules = withEggs(coreModuleConfig)(({
@@ -9792,4 +9839,4 @@ const StoreProvider = ({
9792
9839
  })
9793
9840
  }));
9794
9841
 
9795
- export { IS_LEGEND_OPEN_BY_DEFAULT, StoreProvider, coreModuleConfig, createStore, drawtoolActions, drawtoolModuleConfig, reducer as drawtoolReducer, selectors as drawtoolSelectors, filterLayers$1 as filterLayers, genericActions, rootSaga$2 as genericSaga, selectors$4 as genericSelectors, types$1 as genericTypes, getSingularDrawtoolDrawLayerId, getUserAddedServices, initialState$3 as initialState, layerActions, reducer$6 as layerReducer, selectors$7 as layerSelectors, types$5 as layerTypes, utils$2 as layerUtils, loadingIndicatorActions, constants as loadingIndicatorConstants, loadingIndicatorReducer, selectors$3 as loadingIndicatorSelectors, mapActions, enums as mapEnums, rootSaga$4 as mapSaga, selectors$2 as mapSelectors, mapStoreActions, mapStoreModuleConfig, mapStoreReducers, types$4 as mapTypes, mapUtils, routerActions, routerModuleConfig, utils as routerUtils, selectorMemoizationOptions, serviceActions, selectors$1 as serviceSelectors, types as serviceTypes, setUserAddedServices, storeTestSettings, storeTestUtils, utils$1 as storeUtils, constants$1 as syncConstants, actions as syncGroupsActions, reducer$3 as syncGroupsReducer, selector as syncGroupsSelector, selectors$5 as syncGroupsSelectors, types$2 as syncGroupsTypes, types$2 as types, uiActions, uiModuleConfig, reducer$5 as uiReducer, selectors$6 as uiSelectors, types$3 as uiTypes, useSetupDialog, reducer$4 as webmapReducer };
9842
+ export { IS_LEGEND_OPEN_BY_DEFAULT, StoreProvider, coreModuleConfig, createStore, drawtoolActions, drawtoolModuleConfig, reducer as drawtoolReducer, selectors as drawtoolSelectors, filterLayers$1 as filterLayers, genericActions, genericListener, selectors$4 as genericSelectors, types$1 as genericTypes, getSingularDrawtoolDrawLayerId, getUserAddedServices, initialState$3 as initialState, layerActions, reducer$6 as layerReducer, selectors$7 as layerSelectors, types$5 as layerTypes, utils$2 as layerUtils, loadingIndicatorActions, constants as loadingIndicatorConstants, loadingIndicatorReducer, selectors$3 as loadingIndicatorSelectors, mapActions, enums as mapEnums, rootSaga$2 as mapSaga, selectors$2 as mapSelectors, mapStoreActions, mapStoreModuleConfig, mapStoreReducers, types$4 as mapTypes, mapUtils, routerActions, routerModuleConfig, utils as routerUtils, selectorMemoizationOptions, serviceActions, selectors$1 as serviceSelectors, types as serviceTypes, setUserAddedServices, storeTestSettings, storeTestUtils, utils$1 as storeUtils, constants$1 as syncConstants, actions as syncGroupsActions, reducer$3 as syncGroupsReducer, selector as syncGroupsSelector, selectors$5 as syncGroupsSelectors, types$2 as syncGroupsTypes, types$2 as types, uiActions, uiModuleConfig, reducer$5 as uiReducer, selectors$6 as uiSelectors, types$3 as uiTypes, useSetupDialog, reducer$4 as webmapReducer };