• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jumpinjackie / mapguide-react-layout / 15160437878

21 May 2025 11:00AM UTC coverage: 21.631% (-42.6%) from 64.24%
15160437878

Pull #1552

github

web-flow
Merge 8b7153d9e into 236e2ea07
Pull Request #1552: Feature/package updates 2505

839 of 1165 branches covered (72.02%)

11 of 151 new or added lines in 25 files covered. (7.28%)

1332 existing lines in 50 files now uncovered.

4794 of 22163 relevant lines covered (21.63%)

6.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.89
/src/actions/map.ts
1
import {
1✔
2
    ActiveMapTool,
3
    ICommand,
4
    IMapView,
5
    ReduxThunkedAction,
6
    getCurrentView,
7
    getRuntimeMap,
8
    getSelectionSet,
9
    UnitOfMeasure,
10
    ILayerInfo,
11
    ReduxDispatch
12
} from "../api/common";
13
import { getViewer } from "../api/runtime";
1✔
14
import { getFiniteScaleIndexForScale } from '../utils/number';
1✔
15
import { Client } from "../api/client";
1✔
16
import { QueryMapFeaturesResponse, FeatureSet, SelectedFeature, SelectedFeatureSet } from '../api/contracts/query';
17
import { IQueryMapFeaturesOptions, QueryFeaturesSet } from '../api/request-builder';
1✔
18
import { buildSelectionXml } from '../api/builders/deArrayify';
1✔
19
import { ActionType } from '../constants/actions';
1✔
20
import {
21
    IMapSetBusyCountAction,
22
    IMapSetBaseLayerAction,
23
    IMapSetScaleAction,
24
    IMapSetMouseCoordinatesAction,
25
    IMapSetLayerTransparencyAction,
26
    IMapSetViewSizeUnitsAction,
27
    IMapPreviousViewAction,
28
    IMapNextViewAction,
29
    ISetActiveMapToolAction,
30
    ISetActiveMapAction,
31
    ISetManualFeatureTooltipsEnabledAction,
32
    ISetFeatureTooltipsEnabledAction,
33
    IMapSetViewRotationAction,
34
    IMapSetViewRotationEnabledAction,
35
    IShowSelectedFeatureAction,
36
    IMapSetSelectionAction,
37
    IMapResizedAction,
38
    IAddedLayerAction,
39
    IRemoveLayerAction,
40
    ISetLayerIndexAction,
41
    ISetLayerOpacityAction,
42
    ISetLayerVisibilityAction,
43
    ISetMapLayerVectorStyle,
44
    IAddMapLayerBusyWorkerAction,
45
    IRemoveMapLayerBusyWorkerAction,
46
    IAddClientSelectedFeatureAction,
47
    IClearClientSelectionAction,
48
    ISetHeatmapLayerBlurAction,
49
    ISetHeatmapLayerRadiusAction,
50
    IEnableSelectDragPanAction
51
} from './defs';
52
import { persistSelectionSetToLocalStorage } from '../api/session-store';
1✔
53
import { getSiteVersion, canUseQueryMapFeaturesV4 } from '../utils/site-version';
1✔
54
import { areViewsCloseToEqual } from '../utils/viewer-state';
1✔
55
import { IVectorLayerStyle, VectorStyleSource } from '../api/ol-style-contracts';
56
import { ClientSelectionFeature } from "../api/contracts/common";
57
import xor from "lodash.xor";
1✔
58
import xorby from "lodash.xorby";
1✔
59
import { RuntimeMap } from "../api/contracts/runtime-map";
60
import { debug } from "../utils/logger";
1✔
61

62
function combineSelectedFeatures(oldRes: SelectedFeature[], newRes: SelectedFeature[]): SelectedFeature[] {
2✔
63
    // This function won't be called if we're using QUERYMAPFEATURES older than v4.0.0 (because we won't request
64
    // attributes on the first QUERYMAPFEATURES call and use the save merged selection XML QUERYMAPFEATURES call as an 
65
    // opportunity to get back the full attribute set of the merged selection), but if we ever do hit here we are totally
66
    // assuming a v4 QUERYMAPFEATURES response and the selected features will be having a SelectionKey set so we can easily 
67
    // xorby the 2 arrays
68
    return xorby(oldRes, newRes, f => f.SelectionKey);
2✔
69
}
2✔
70

71
function combineSelectedFeatureSets(oldRes: SelectedFeatureSet | undefined, newRes: SelectedFeatureSet | undefined): SelectedFeatureSet | undefined {
2✔
72
    if (oldRes == null) {
2!
73
        return newRes;
×
UNCOV
74
    }
×
75
    const merged: SelectedFeatureSet = {
2✔
76
        SelectedLayer: []
2✔
77
    };
2✔
78
    for (const layer of oldRes.SelectedLayer) {
2✔
79
        merged.SelectedLayer.push(layer);
2✔
80
    }
2✔
81
    if (newRes) {
2✔
82
        for (const layer of newRes.SelectedLayer) {
2✔
83
            const layerId = layer["@id"];
2✔
84
            const layerName = layer["@name"];
2✔
85
            const existing = merged.SelectedLayer.filter(l => l["@id"] == layerId && l["@name"] == layerName);
2✔
86
            if (existing.length == 0) {
2!
87
                merged.SelectedLayer.push(layer);
×
88
            } else {
2✔
89
                existing[0].Feature = combineSelectedFeatures(existing[0].Feature, layer.Feature);
2✔
90
            }
2✔
91
        }
2✔
92
    }
2✔
93
    return merged;
2✔
94
}
2✔
95

96
function combineFeatureSets(oldRes: FeatureSet | undefined, newRes: FeatureSet | undefined): FeatureSet | undefined {
2✔
97
    if (oldRes == null) {
2!
98
        return newRes;
×
UNCOV
99
    }
×
100
    const merged: FeatureSet = {
2✔
101
        Layer: []
2✔
102
    };
2✔
103
    for (const layer of oldRes.Layer) {
2✔
104
        merged.Layer.push(layer);
2✔
105
    }
2✔
106
    if (newRes) {
2✔
107
        for (const layer of newRes.Layer) {
2✔
108
            const layerId = layer["@id"];
2✔
109
            const existing = merged.Layer.filter(l => l["@id"] == layerId);
2✔
110
            if (existing.length == 0) {
2!
111
                merged.Layer.push(layer);
×
112
            } else {
2✔
113
                existing[0].Class.ID = xor(existing[0].Class.ID, layer.Class.ID);
2✔
114
            }
2✔
115
        }
2✔
116
    }
2✔
117
    return merged;
2✔
118
}
2✔
119

120
/**
121
 * @hidden Exported just to be unit testable
122
 */
123
export function combineSelections(oldRes: QueryMapFeaturesResponse | undefined, newRes: QueryMapFeaturesResponse): QueryMapFeaturesResponse {
1✔
124
    if (oldRes) {
2✔
125
        const merged: QueryMapFeaturesResponse = {
2✔
126
            SelectedFeatures: combineSelectedFeatureSets(oldRes.SelectedFeatures, newRes.SelectedFeatures),
2✔
127
            FeatureSet: combineFeatureSets(oldRes.FeatureSet, newRes.FeatureSet),
2✔
128
            Hyperlink: undefined,
2✔
129
            InlineSelectionImage: undefined
2✔
130
        };
2✔
131
        return merged;
2✔
132
    } else {
2!
133
        return newRes;
×
UNCOV
134
    }
×
135
}
2✔
136

137
/**
138
 * Options for map querying
139
 *
140
 * @export
141
 * @interface QueryMapFeatureActionOptions
142
 */
143
export interface QueryMapFeatureActionOptions {
144
    /**
145
     * The main set of map querying options
146
     *
147
     * @type {IQueryMapFeaturesOptions}
148
     * @memberof QueryMapFeatureActionOptions
149
     */
150
    options: IQueryMapFeaturesOptions;
151
    /**
152
     * If true, the selection changes will be appended to the current selection set. False otherwise
153
     *
154
     * @type {boolean}
155
     * @memberof QueryMapFeatureActionOptions
156
     */
157
    append?: boolean;
158
    /**
159
     * An optional callback to invoke on successful operation
160
     *
161
     * @memberof QueryMapFeatureActionOptions
162
     */
163
    callback?: (res: QueryMapFeaturesResponse) => void;
164
    /**
165
     * An optional callback to invoke on failure
166
     *
167
     * @memberof QueryMapFeatureActionOptions
168
     */
169
    errBack?: (err: any) => void;
170
}
171

UNCOV
172
async function queryMapFeaturesHelper(map: RuntimeMap,
×
UNCOV
173
    client: Client,
×
UNCOV
174
    opts: QueryMapFeatureActionOptions,
×
UNCOV
175
    selectionSet: QueryMapFeaturesResponse | undefined,
×
UNCOV
176
    dispatch: ReduxDispatch
×
UNCOV
177
) {
×
178
    const mapName = map.Name;
×
179
    //We want v4.0.0 QUERYMAPFEATURES if available
180
    const sv = getSiteVersion(map);
×
181
    const isV4 = canUseQueryMapFeaturesV4(sv);
×
182
    const queryOp = isV4
×
183
        ? (opts: IQueryMapFeaturesOptions) => client.queryMapFeatures_v4(opts)
×
184
        : (opts: IQueryMapFeaturesOptions) => client.queryMapFeatures(opts);
×
185

186
    const isAppendingWithAttributesOnOldMapGuide = !isV4
×
UNCOV
187
        && opts.append === true
×
UNCOV
188
        && opts.options.persist === 1
×
UNCOV
189
        && opts.options.requestdata !== undefined
×
UNCOV
190
        && (opts.options.requestdata & QueryFeaturesSet.Attributes);
×
191

192
    if (isAppendingWithAttributesOnOldMapGuide) {
×
193
        debug("Not asking for attributes in first QUERYMAPFEATURES");
×
194
        // Momentarily stop requesting for attributes
195
        opts.options.requestdata! &= ~QueryFeaturesSet.Attributes;
×
UNCOV
196
    }
×
197

198
    const res = await queryOp(opts.options);
×
199
    if (opts.options.persist === 1) {
×
200
        if (opts.append === true) {
×
201
            let combined = combineSelections(selectionSet, res);
×
202
            const mergedXml = buildSelectionXml(combined.FeatureSet);
×
203
            // Need to update the server-side selection with the merged result
204
            const opts2: IQueryMapFeaturesOptions = {
×
UNCOV
205
                session: map.SessionId,
×
UNCOV
206
                mapname: map.Name,
×
UNCOV
207
                persist: 1,
×
UNCOV
208
                featurefilter: mergedXml
×
UNCOV
209
            };
×
210
            // If appending with attributes, we can now also include attributes of the merged result
211
            if (isAppendingWithAttributesOnOldMapGuide) {
×
212
                debug("Now asking for attributes in second QUERYMAPFEATURES");
×
213
                opts2.requestdata = QueryFeaturesSet.Attributes;
×
UNCOV
214
            }
×
215
            const res2 = await queryOp(opts2);
×
216
            // If appending with attributes, res2 represents the attributes of the merged result, so accept
217
            // it as the new combined without having to do any stitching
218
            if (isAppendingWithAttributesOnOldMapGuide) {
×
219
                debug("Accepting second QUERYMAPFEATURES as new combined selection response");
×
220
                combined = res2;
×
UNCOV
221
            }
×
222
            persistSelectionSetToLocalStorage(map.SessionId, mapName, combined); // set and forget
×
223
            dispatch(setSelection(mapName, combined));
×
224
            return combined;
×
UNCOV
225
        } else {
×
226
            persistSelectionSetToLocalStorage(map.SessionId, mapName, res); // set and forget
×
227
            dispatch(setSelection(mapName, res));
×
228
            return res;
×
UNCOV
229
        }
×
UNCOV
230
    } else {
×
231
        return res;
×
UNCOV
232
    }
×
UNCOV
233
}
×
234

235
/**
236
 * Queries map features
237
 *
238
 * @export
239
 * @param {string} mapName The name of the current runtime map
240
 * @param {QueryMapFeatureActionOptions} opts query options
241
 * @returns {ReduxThunkedAction}
242
 */
243
export function queryMapFeatures(mapName: string, opts: QueryMapFeatureActionOptions): ReduxThunkedAction {
1✔
244
    return (dispatch, getState) => {
×
245
        const state = getState();
×
246
        const args = state.config;
×
247
        const map = getRuntimeMap(state);
×
248
        const selectionSet = getSelectionSet(state);
×
249
        if (map && args.agentKind && args.agentUri) {
×
250
            const client = new Client(args.agentUri, args.agentKind);
×
251
            const success = (res: QueryMapFeaturesResponse) => {
×
252
                if (opts.callback != null) {
×
253
                    opts.callback(res);
×
UNCOV
254
                }
×
UNCOV
255
            };
×
256
            const failure = (err: Error) => {
×
257
                if (opts.errBack != null) {
×
258
                    opts.errBack(err);
×
UNCOV
259
                }
×
UNCOV
260
            };
×
261
            queryMapFeaturesHelper(map, client, opts, selectionSet, dispatch).then(r => success(r))
×
262
                .catch(e => failure(e));
×
UNCOV
263
        }
×
UNCOV
264
    };
×
UNCOV
265
}
×
266

267
/**
268
 * Sets the current map view.
269
 *
270
 * NOTE: Subscribing components are not guaranteed to receive every new view change sent by
271
 * calling this method. For purposes of optimization, views passed in that are "close enough"
272
 * to the current view are not dispatched to subscribing components.
273
 * 
274
 * @export
275
 * @param {IMapView} view The map view to set
276
 * @returns {ReduxThunkedAction}
277
 */
278
export function setCurrentView(view: IMapView): ReduxThunkedAction {
1✔
279
    return (dispatch, getState) => {
×
280
        // HACK-y:
281
        //
282
        // We don't want to dispatch SET_VIEW actions with redundant view
283
        // states if the one we're about to dispatch is the same as the
284
        // previous one
285
        const state = getState();
×
286
        const currentView = getCurrentView(state);
×
287
        const newView = { ...view };
×
288
        const mapName = state.config.activeMapName;
×
289
        let dispatchThis = true;
×
290
        if (currentView && mapName) {
×
291
            //If the current map is tiled (has finite scales), "snap" the view's scale
292
            //to the closest applicable finite scale then do the test 
293
            const mapState = state.mapState[mapName];
×
294
            const fs = mapState?.mapguide?.runtimeMap?.FiniteDisplayScale;
×
295
            if (fs && fs.length > 0) {
×
296

297
                const fi = getFiniteScaleIndexForScale(fs, newView.scale);
×
298
                newView.scale = fs[fi];
×
UNCOV
299
            }
×
300
            if (areViewsCloseToEqual(currentView, newView)) {
×
301
                dispatchThis = false;
×
UNCOV
302
            }
×
UNCOV
303
        }
×
304
        if (dispatchThis && mapName) {
×
305
            dispatch({
×
UNCOV
306
                type: ActionType.MAP_SET_VIEW,
×
UNCOV
307
                payload: {
×
UNCOV
308
                    mapName,
×
UNCOV
309
                    view: newView
×
UNCOV
310
                }
×
UNCOV
311
            });
×
UNCOV
312
        }
×
UNCOV
313
    };
×
UNCOV
314
}
×
315

316
/**
317
 * Sends a map resized notification
318
 * 
319
 * @export
320
 * @param {number} width 
321
 * @param {number} height 
322
 * @returns {IMapResizedAction} 
323
 */
324
export function mapResized(width: number, height: number): IMapResizedAction {
1✔
325
    return {
1✔
326
        type: ActionType.MAP_RESIZED,
1✔
327
        payload: {
1✔
328
            width,
1✔
329
            height
1✔
330
        }
1✔
331
    }
1✔
332
}
1✔
333

334
/**
335
 * Sets the selection set for the given map
336
 * 
337
 * @param mapName 
338
 * @param selectionSet 
339
 * @returns 
340
 * 
341
 * @since 0.14 Fixed up the type of selectionSet parameter
342
 */
343
export function setSelection(mapName: string, selectionSet: QueryMapFeaturesResponse | undefined): IMapSetSelectionAction {
1✔
344
    return {
2✔
345
        type: ActionType.MAP_SET_SELECTION,
2✔
346
        payload: {
2✔
347
            mapName,
2✔
348
            selection: selectionSet
2✔
349
        }
2✔
350
    };
2✔
351
}
2✔
352

353
/**
354
 * Invokes the specified command
355
 *
356
 * @export
357
 * @param {ICommand} cmd
358
 * @param {*} [parameters]
359
 * @returns {ReduxThunkedAction}
360
 */
361
export function invokeCommand(cmd: ICommand, parameters?: any): ReduxThunkedAction {
1✔
362
    return (dispatch, getState) => {
×
363
        return cmd.invoke(dispatch, getState, getViewer(), parameters);
×
UNCOV
364
    };
×
UNCOV
365
}
×
366

367
/**
368
 * Sets the busy count of the viewer. A value greater than zero signifies that the viewer is currently
369
 * busy performing various actions (eg. Loading/Rendering the current map image)
370
 *
371
 * @export
372
 * @param {number} busyCount The current busy count
373
 * @returns {IMapSetBusyCountAction}
374
 */
375
export function setBusyCount(busyCount: number): IMapSetBusyCountAction {
1✔
376
    return {
1✔
377
        type: ActionType.MAP_SET_BUSY_COUNT,
1✔
378
        payload: busyCount
1✔
379
    };
1✔
380
}
1✔
381

382
/**
383
 * Set the given external base layer as the active base layer
384
 *
385
 * @export
386
 * @param {string} mapName The name of the current runtime map
387
 * @param {string} layerName The name of the external base layer to set as active
388
 * @returns
389
 */
390
export function setBaseLayer(mapName: string, layerName: string): IMapSetBaseLayerAction {
1✔
391
    return {
1✔
392
        type: ActionType.MAP_SET_BASE_LAYER,
1✔
393
        payload: {
1✔
394
            mapName,
1✔
395
            layerName
1✔
396
        }
1✔
397
    };
1✔
398
}
1✔
399

400
/**
401
 * Sets the view scale
402
 *
403
 * @export
404
 * @param {string} mapName The name of the current runtime map
405
 * @param {number} scale The scale to set
406
 * @returns
407
 */
408
export function setScale(mapName: string, scale: number): IMapSetScaleAction {
1✔
409
    const viewer = getViewer();
1✔
410
    let resolution;
1✔
411
    if (viewer) {
1!
412
        resolution = viewer.scaleToResolution(scale);
×
UNCOV
413
    }
×
414
    return {
1✔
415
        type: ActionType.MAP_SET_SCALE,
1✔
416
        payload: {
1✔
417
            mapName,
1✔
418
            scale,
1✔
419
            resolution
1✔
420
        }
1✔
421
    };
1✔
422
}
1✔
423

424
/**
425
 * Sets the current mouse coordinates
426
 *
427
 * @export
428
 * @param {string} mapName The name of the current runtime map
429
 * @param {*} coord The current mouse coordinates
430
 * @returns
431
 */
432
export function setMouseCoordinates(mapName: string, coord: any): IMapSetMouseCoordinatesAction {
1✔
433
    return {
1✔
434
        type: ActionType.UPDATE_MOUSE_COORDINATES,
1✔
435
        payload: {
1✔
436
            mapName,
1✔
437
            coord
1✔
438
        }
1✔
439
    };
1✔
440
}
1✔
441

442
/**
443
 * Set the transparency for the given OL layer
444
 * 
445
 * @export
446
 * @param {string} mapName The name of the current runtime map
447
 * @param {string} layerName The name of the OL layer
448
 * @param {number} opacity A value between 0 and 1. 1 - Fully Opaque, 0 - Fully Transparent
449
 * @returns 
450
 */
451
export function setLayerTransparency(mapName: string, layerName: string, opacity: number): IMapSetLayerTransparencyAction {
1✔
452
    return {
×
UNCOV
453
        type: ActionType.MAP_SET_LAYER_TRANSPARENCY,
×
UNCOV
454
        payload: {
×
UNCOV
455
            mapName,
×
UNCOV
456
            layerName,
×
UNCOV
457
            opacity
×
UNCOV
458
        }
×
UNCOV
459
    };
×
UNCOV
460
}
×
461

462
/**
463
 * Sets the units for the map view size display
464
 * 
465
 * @export
466
 * @param {UnitOfMeasure} unit 
467
 * @returns {IMapSetViewSizeUnitsAction} 
468
 */
469
export function setViewSizeUnits(unit: UnitOfMeasure): IMapSetViewSizeUnitsAction {
1✔
470
    return {
1✔
471
        type: ActionType.MAP_SET_VIEW_SIZE_UNITS,
1✔
472
        payload: unit
1✔
473
    };
1✔
474
}
1✔
475

476
/**
477
 * Goes back to the previous view on the navigation stack
478
 *
479
 * @export
480
 * @param {string} mapName The name of the current runtime map
481
 * @returns
482
 */
483
export function previousView(mapName: string): IMapPreviousViewAction {
1✔
484
    return {
2✔
485
        type: ActionType.MAP_PREVIOUS_VIEW,
2✔
486
        payload: {
2✔
487
            mapName
2✔
488
        }
2✔
489
    };
2✔
490
}
2✔
491

492
/**
493
 * Goes to the next view on the navigation stack
494
 *
495
 * @export
496
 * @param {string} mapName The name of the current runtime amp
497
 * @returns
498
 */
499
export function nextView(mapName: string): IMapNextViewAction {
1✔
500
    return {
2✔
501
        type: ActionType.MAP_NEXT_VIEW,
2✔
502
        payload: {
2✔
503
            mapName
2✔
504
        }
2✔
505
    };
2✔
506
}
2✔
507

508
/**
509
 * Sets the active map tool
510
 *
511
 * @export
512
 * @param {ActiveMapTool} tool The active map tool command
513
 * @returns
514
 */
515
export function setActiveTool(tool: ActiveMapTool): ISetActiveMapToolAction {
1✔
516
    return {
1✔
517
        type: ActionType.MAP_SET_ACTIVE_TOOL,
1✔
518
        payload: tool
1✔
519
    };
1✔
520
}
1✔
521

522
/**
523
 * Sets the active runtime map
524
 *
525
 * @export
526
 * @param {string} mapName The name of the runtime map to set as active
527
 * @returns
528
 */
529
export function setActiveMap(mapName: string): ISetActiveMapAction {
1✔
530
    return {
1✔
531
        type: ActionType.MAP_SET_ACTIVE_MAP,
1✔
532
        payload: mapName
1✔
533
    };
1✔
534
}
1✔
535

536
/**
537
 * Sets whether feature tooltips (aka. Map Tips) are enabled
538
 *
539
 * @export
540
 * @param {boolean} enabled
541
 * @returns
542
 */
543
export function setFeatureTooltipsEnabled(enabled: boolean): ISetFeatureTooltipsEnabledAction {
1✔
544
    return {
1✔
545
        type: ActionType.MAP_SET_MAPTIP,
1✔
546
        payload: enabled
1✔
547
    };
1✔
548
}
1✔
549

550
/**
551
 * Sets whether the select tool can pan while dragging
552
 * 
553
 * @param enabled 
554
 * @since 0.14.2
555
 */
556
export function enableSelectDragPan(enabled: boolean): IEnableSelectDragPanAction {
1✔
557
    return {
×
UNCOV
558
        type: ActionType.MAP_ENABLE_SELECT_DRAGPAN,
×
UNCOV
559
        payload: enabled
×
UNCOV
560
    }
×
UNCOV
561
}
×
562

563
/**
564
 * Sets whether manual feature tooltips (aka. Map Tips) are enabled
565
 *
566
 * @export
567
 * @param {boolean} enabled
568
 * @returns
569
 */
570
export function setManualFeatureTooltipsEnabled(enabled: boolean): ISetManualFeatureTooltipsEnabledAction {
1✔
571
    return {
2✔
572
        type: ActionType.MAP_SET_MANUAL_MAPTIP,
2✔
573
        payload: enabled
2✔
574
    };
2✔
575
}
2✔
576

577
/**
578
 * Sets the rotation of the current view
579
 * 
580
 * @export
581
 * @param {number} rotation 
582
 * @returns 
583
 */
584
export function setViewRotation(rotation: number): IMapSetViewRotationAction {
1✔
585
    return {
1✔
586
        type: ActionType.MAP_SET_VIEW_ROTATION,
1✔
587
        payload: rotation
1✔
588
    };
1✔
589
}
1✔
590

591
/**
592
 * Sets whether view rotation is enabled or not
593
 * 
594
 * @export
595
 * @param {boolean} enabled 
596
 */
597
export function setViewRotationEnabled(enabled: boolean): IMapSetViewRotationEnabledAction {
1✔
598
    return {
2✔
599
        type: ActionType.MAP_SET_VIEW_ROTATION_ENABLED,
2✔
600
        payload: enabled
2✔
601
    };
2✔
602
}
2✔
603

604
/**
605
 * Shows the selected feature on the map
606
 * 
607
 * @export
608
 * @param {string} mapName 
609
 * @param {string} layerId 
610
 * @param {string} selectionKey 
611
 * @returns {IShowSelectedFeatureAction} 
612
 */
613
export function showSelectedFeature(mapName: string, layerId: string, selectionKey: string): IShowSelectedFeatureAction {
1✔
614
    return {
×
UNCOV
615
        type: ActionType.MAP_SHOW_SELECTED_FEATURE,
×
UNCOV
616
        payload: {
×
UNCOV
617
            mapName,
×
UNCOV
618
            layerId,
×
UNCOV
619
            selectionKey
×
UNCOV
620
        }
×
UNCOV
621
    };
×
UNCOV
622
}
×
623

624
/**
625
 * NOTE: Dispatching this action does not add the layer to the map. This is a means to notify others
626
 * that a new layer has been added. It is expected to be dispatched by any component that is managing
627
 * layers
628
 * 
629
 * @export
630
 * @param {string} mapName
631
 * @param {ILayerInfo} layer
632
 * @param {IVectorLayerStyle} [defaultStyle]
633
 * @returns {IAddedLayerAction}
634
 * @since 0.13
635
 * @since 0.14 defaultStyle argument changed to IVectorLayerStyle
636
 */
637
export function mapLayerAdded(mapName: string, layer: ILayerInfo, defaultStyle?: IVectorLayerStyle): IAddedLayerAction {
1✔
638
    return {
×
UNCOV
639
        type: ActionType.LAYER_ADDED,
×
UNCOV
640
        payload: {
×
UNCOV
641
            mapName,
×
UNCOV
642
            layer,
×
UNCOV
643
            defaultStyle
×
UNCOV
644
        }
×
UNCOV
645
    };
×
UNCOV
646
}
×
647

648
/**
649
 * An action that signals the externa layers for the given map name is ready. This action
650
 * is only dispatched when there is no external layers to initially add
651
 * 
652
 * @param mapName 
653
 * @since 0.14
654
 */
655
export function externalLayersReady(mapName: string) {
1✔
656
    return {
×
UNCOV
657
        type: ActionType.EXTERNAL_LAYERS_READY,
×
UNCOV
658
        payload: {
×
UNCOV
659
            mapName
×
UNCOV
660
        }
×
UNCOV
661
    }
×
UNCOV
662
}
×
663

664
/**
665
 * Removes a given external layer for the given map
666
 * 
667
 * @export
668
 * @param {string} mapName
669
 * @param {string} layerName
670
 * @returns {IRemoveLayerAction}
671
 * @since 0.13
672
 */
673
export function removeMapLayer(mapName: string, layerName: string): IRemoveLayerAction {
1✔
674
    return {
×
UNCOV
675
        type: ActionType.REMOVE_LAYER,
×
UNCOV
676
        payload: {
×
UNCOV
677
            mapName,
×
UNCOV
678
            layerName
×
UNCOV
679
        }
×
UNCOV
680
    };
×
UNCOV
681
}
×
682

683
/**
684
 * Sets the display order index for the given external layer for the given map
685
 * 
686
 * @export
687
 * @param {string} mapName
688
 * @param {string} layerName
689
 * @param {number} index
690
 * @returns {ISetLayerIndexAction}
691
 * @since 0.13
692
 */
693
export function setMapLayerIndex(mapName: string, layerName: string, index: number): ISetLayerIndexAction {
1✔
694
    return {
×
UNCOV
695
        type: ActionType.SET_LAYER_INDEX,
×
UNCOV
696
        payload: {
×
UNCOV
697
            mapName,
×
UNCOV
698
            layerName,
×
UNCOV
699
            index
×
UNCOV
700
        }
×
UNCOV
701
    };
×
UNCOV
702
}
×
703

704
/**
705
 * Sets the opacity for the given external layer for the given map
706
 * 
707
 * @export
708
 * @param {string} mapName
709
 * @param {string} layerName
710
 * @param {number} opacity
711
 * @returns {ISetLayerOpacityAction}
712
 * @since 0.13
713
 */
714
export function setMapLayerOpacity(mapName: string, layerName: string, opacity: number): ISetLayerOpacityAction {
1✔
715
    return {
×
UNCOV
716
        type: ActionType.SET_LAYER_OPACITY,
×
UNCOV
717
        payload: {
×
UNCOV
718
            mapName,
×
UNCOV
719
            layerName,
×
UNCOV
720
            opacity
×
UNCOV
721
        }
×
UNCOV
722
    };
×
UNCOV
723
}
×
724

725
/**
726
 * Sets the heatmap blur for the given external heatmap layer for the given map
727
 * 
728
 * @param mapName 
729
 * @param layerName 
730
 * @param blur 
731
 */
732
export function setHeatmapLayerBlur(mapName: string, layerName: string, blur: number): ISetHeatmapLayerBlurAction {
1✔
733
    return {
×
UNCOV
734
        type: ActionType.SET_HEATMAP_LAYER_BLUR,
×
UNCOV
735
        payload: {
×
UNCOV
736
            mapName,
×
UNCOV
737
            layerName,
×
UNCOV
738
            blur
×
UNCOV
739
        }
×
UNCOV
740
    };
×
UNCOV
741
}
×
742

743
/**
744
 * Sets the heatmap radius for the given external heatmap layer for the given map
745
 * 
746
 * @param mapName 
747
 * @param layerName 
748
 * @param radius 
749
 */
750
export function setHeatmapLayerRadius(mapName: string, layerName: string, radius: number): ISetHeatmapLayerRadiusAction {
1✔
751
    return {
×
UNCOV
752
        type: ActionType.SET_HEATMAP_LAYER_RADIUS,
×
UNCOV
753
        payload: {
×
UNCOV
754
            mapName,
×
UNCOV
755
            layerName,
×
UNCOV
756
            radius
×
UNCOV
757
        }
×
UNCOV
758
    };
×
UNCOV
759
}
×
760

761
/**
762
 * Sets the visibility for the given external layer for the given map
763
 * 
764
 * @export
765
 * @param {string} mapName
766
 * @param {string} layerName
767
 * @param {boolean} visible
768
 * @returns {ISetLayerVisibilityAction}
769
 * @since 0.13
770
 */
771
export function setMapLayerVisibility(mapName: string, layerName: string, visible: boolean): ISetLayerVisibilityAction {
1✔
772
    return {
×
UNCOV
773
        type: ActionType.SET_LAYER_VISIBILITY,
×
UNCOV
774
        payload: {
×
UNCOV
775
            mapName,
×
UNCOV
776
            layerName,
×
UNCOV
777
            visible
×
UNCOV
778
        }
×
UNCOV
779
    };
×
UNCOV
780
}
×
781

782
/**
783
 * Sets the vector style for the given external layer for the given map
784
 * 
785
 * @export
786
 * @param {string} mapName
787
 * @param {string} layerName
788
 * @param {IVectorLayerStyle} style
789
 * @param {VectorStyleSource} which
790
 * @returns {ISetMapLayerVectorStyle}
791
 * @since 0.13
792
 * @since 0.14 style and which arguments changed to IVectorLayerStyle
793
 */
794
export function setMapLayerVectorStyle(mapName: string, layerName: string, style: IVectorLayerStyle, which: VectorStyleSource): ISetMapLayerVectorStyle {
1✔
795
    return {
×
UNCOV
796
        type: ActionType.SET_LAYER_VECTOR_STYLE,
×
UNCOV
797
        payload: {
×
UNCOV
798
            mapName,
×
UNCOV
799
            layerName,
×
UNCOV
800
            style,
×
UNCOV
801
            which
×
UNCOV
802
        }
×
UNCOV
803
    };
×
UNCOV
804
}
×
805

806
/**
807
 * Adds a busy worker for the given external layer for the given map
808
 * 
809
 * @export
810
 * @param {string} mapName
811
 * @param {string} layerName
812
 * @returns {IAddMapLayerBusyWorkerAction}
813
 * @since 0.13
814
 */
815
export function addMapLayerBusyWorker(mapName: string, layerName: string): IAddMapLayerBusyWorkerAction {
1✔
816
    return {
×
UNCOV
817
        type: ActionType.ADD_LAYER_BUSY_WORKER,
×
UNCOV
818
        payload: {
×
UNCOV
819
            mapName,
×
UNCOV
820
            layerName
×
UNCOV
821
        }
×
UNCOV
822
    }
×
UNCOV
823
}
×
824

825
/**
826
 * Removes a busy worker for the given external layer for the given map
827
 * 
828
 * @export
829
 * @param {string} mapName
830
 * @param {string} layerName
831
 * @returns {IRemoveMapLayerBusyWorkerAction}
832
 * @since 0.13
833
 */
834
export function removeMapLayerBusyWorker(mapName: string, layerName: string): IRemoveMapLayerBusyWorkerAction {
1✔
835
    return {
×
UNCOV
836
        type: ActionType.REMOVE_LAYER_BUSY_WORKER,
×
UNCOV
837
        payload: {
×
UNCOV
838
            mapName,
×
UNCOV
839
            layerName
×
UNCOV
840
        }
×
UNCOV
841
    }
×
UNCOV
842
}
×
843

844
/**
845
 * Adds a feature to the client selection set for the given map
846
 * 
847
 * @param mapName 
848
 * @param layerName 
849
 * @param feature 
850
 * @returns 
851
 * @since 0.14
852
 */
853
export function addClientSelectedFeature(mapName: string, layerName: string, feature: ClientSelectionFeature): IAddClientSelectedFeatureAction {
1✔
854
    return {
1✔
855
        type: ActionType.MAP_ADD_CLIENT_SELECTED_FEATURE,
1✔
856
        payload: {
1✔
857
            mapName,
1✔
858
            layerName,
1✔
859
            feature
1✔
860
        }
1✔
861
    }
1✔
862
}
1✔
863

864
/**
865
 * Clears the client selection set for the given map
866
 * 
867
 * @param mapName 
868
 * @since 0.14
869
 */
870
export function clearClientSelection(mapName: string): IClearClientSelectionAction {
1✔
871
    return {
1✔
872
        type: ActionType.MAP_CLEAR_CLIENT_SELECTION,
1✔
873
        payload: {
1✔
874
            mapName
1✔
875
        }
1✔
876
    }
1✔
877
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc