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

geosolutions-it / MapStore2 / 7003707267

27 Nov 2023 10:27AM UTC coverage: 78.326% (+0.03%) from 78.301%
7003707267

push

github

web-flow
updating stable branch of genova (#9748)

* Fix #9624 Point cloud shading options (#9666)

* Fix #9666 Include pointCloudShading option to saved layer config (#9670)

* #9606 Error with circle annotations + radius selection (#9607) (#9727)

Co-authored-by: Diego Vargas <diegodevelopero@gmail.com>

* Fix #9295 added better handling of format in csw service (#9712) (#9732)

* #9702: Fix - Background selector in contexts won't retain thumbnail in view mode (#9720) (#9744)

* #9567: handle functionality of zoom to record in table widgets (#9608)

* #9567: handle functionality of zoom to record in table widgets

* Fix: Correct failing test cases for zoom records issue in table widgets (#9567)
This commit addresses the failing test cases related to the issue of zoom records in table widgets.
* #9567: implement the new approach in zoom to records in table widgets + writing unit tests
* #9567: handle adding flag into config file to show/hide zoom icon for tblWidget
* #9567: reset flag enableZoomInTblWidget to be true for dashboard and map viewer
* #9567: resolve comments' review:
- put flag of zoomInTblWidget as a default prop
- add translations
- edit zoomToExtent enhancer to use internal zoom
- remove selector "getFlagOfShowingTblWidgetZoom " and use plugin prop instead

* #9683: add Details Panel for MS dashboard (#9689)

* #9683: add Details Panel for MS dashboard
-  The tool have the same options (eg. show as modal, show at startup etc.)
- The tool is defined in the same way of the corresponding one for maps.
- Edit the layout to put add widget & show/hide connection buttons to the sidebar menu

* #9683: resolve the FE test

Update DashboardEditor.jsx

* #9683: resolve review comments
* description:
- remove all dashboard selectors and pieces of code in generic components like sidebar plugin component that relevant to dashboard.
- add missing test for detailsLoaded action
- create new selectors, details uri selec... (continued)

28882 of 43902 branches covered (0.0%)

167 of 208 new or added lines in 32 files covered. (80.29%)

2 existing lines in 1 file now uncovered.

36141 of 46142 relevant lines covered (78.33%)

42.41 hits per line

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

83.87
/web/client/epics/tutorial.js
1
/*
2
 * Copyright 2017, GeoSolutions Sas.
3
 * All rights reserved.
4
 *
5
 * This source code is licensed under the BSD-style license found in the
6
 * LICENSE file in the root directory of this source tree.
7
 */
8

9
import Rx from 'rxjs';
10

11
import {
12
    START_TUTORIAL,
13
    UPDATE_TUTORIAL,
14
    CLOSE_TUTORIAL,
15
    INIT_TUTORIAL,
16
    CHANGE_PRESET,
17
    closeTutorial,
18
    setupTutorial
19
} from '../actions/tutorial';
20
import { openDetailsPanel } from '../actions/details';
21
import { CHANGE_MAP_VIEW } from '../actions/map';
22
import { MAPS_LIST_LOADED } from '../actions/maps';
23
import { modeSelector } from '../selectors/geostory';
24
import { CHANGE_MODE } from '../actions/geostory';
25
import { creationStepSelector } from '../selectors/contextcreator';
26
import { CONTEXT_TUTORIALS } from '../actions/contextcreator';
27
import { LOCATION_CHANGE } from 'connected-react-router';
28
import { isEmpty, isArray, isObject } from 'lodash';
29
import { getApi } from '../api/userPersistedStorage';
30
import {REDUCERS_LOADED} from "../actions/storemanager";
31
import { VISUALIZATION_MODE_CHANGED } from '../actions/maptype';
32
import { detailsSettingsSelector } from '../selectors/details';
33

34
const findTutorialId = path => path.match(/\/(viewer)\/(\w+)\/(\d+)/) && path.replace(/\/(viewer)\/(\w+)\/(\d+)/, "$2")
9✔
35
    || path.match(/\/(\w+)\/(\d+)/) && path.replace(/\/(\w+)\/(\d+)/, "$1")
36
    || path.match(/\/(\w+)\//) && path.replace(/\/(\w+)\//, "$1");
37

38
/**
39
 * Closes the tutorial if 3D button has been toggled
40
 * @memberof epics.tutorial
41
 * @param {external:Observable} action$ manages `START_TUTORIAL`
42
 * @return {external:Observable}
43
 */
44

45
export const closeTutorialEpic = (action$) =>
1✔
46
    action$.ofType(START_TUTORIAL)
×
47
        .audit(() => action$.ofType(VISUALIZATION_MODE_CHANGED))
×
48
        .switchMap( () => Rx.Observable.of(closeTutorial()));
×
49

50
/**
51
 * Setup new steps based on the current path
52
 * @memberof epics.tutorial
53
 * @param {external:Observable} action$ manages `LOCATION_CHANGE`, `REDUCERS_LOADED`
54
 * @param {external:Observable} store
55
 * @return {external:Observable}
56
 */
57

58
export const switchTutorialEpic = (action$, store) =>
1✔
59
    action$.ofType(LOCATION_CHANGE, REDUCERS_LOADED)
9✔
60
        .filter(action => {
61
            const state = store.getState();
9✔
62
            return (action.type === LOCATION_CHANGE && state.router?.location?.pathname)
9!
63
                    || (action.type === REDUCERS_LOADED && action.reducers.includes('tutorial'));
64
        })
65
        .switchMap( () =>
66
            action$.ofType(MAPS_LIST_LOADED, CHANGE_MAP_VIEW, INIT_TUTORIAL)
9✔
67
                .take(1)
68
                .switchMap( () => {
69
                    const state = store.getState();
9✔
70
                    const location = state.router.location;
9✔
71
                    let id = findTutorialId(location.pathname);
9✔
72
                    const presetList = state.tutorial && state.tutorial.presetList || {};
9!
73
                    const browser = state.browser;
9✔
74
                    const mobile = browser && browser.mobile ? '_mobile' : '';
9✔
75
                    const defaultName = id ? 'default' : location.pathname || 'default';
9!
76
                    const prevTutorialId = state.tutorial && state.tutorial.id;
9✔
77
                    let presetName = id + mobile + '_tutorial';
9✔
78
                    if (defaultName.indexOf("context") !== -1) {
9✔
79
                        const currentStep = creationStepSelector(state) || "general-settings";
1✔
80
                        const currentPreset = CONTEXT_TUTORIALS[currentStep];
1✔
81
                        return Rx.Observable.of(setupTutorial(currentPreset, presetList[currentPreset], null, null, null, prevTutorialId === (currentPreset)));
1✔
82
                    }
83
                    if (id && id?.indexOf("geostory") !== -1 && !isEmpty(presetList)) {
8✔
84
                        // this is needed to setup correct geostory tutorial based on the current mode and page
85
                        if (modeSelector(state) === "edit" || id && id?.indexOf("newgeostory") !== -1) {
2✔
86
                            id  = "geostory";
1✔
87
                            presetName = `geostory_edit_tutorial`;
1✔
88
                            return Rx.Observable.from([
1✔
89
                                setupTutorial(id, presetList[presetName], null, null, null, false)
90
                            ]);
91
                        }
92
                        presetName = `geostory_view_tutorial`;
1✔
93
                        return Rx.Observable.of(setupTutorial(id, presetList[presetName], null, null, null, true));
1✔
94
                    }
95
                    return !isEmpty(presetList) ? Rx.Observable.of(presetList[presetName] ?
6✔
96
                        setupTutorial(id + mobile, presetList[presetName], null, null, null, prevTutorialId === (id + mobile)) :
97
                        setupTutorial(defaultName + mobile, presetList['default' + mobile + '_tutorial'], null, null, null, prevTutorialId === (defaultName + mobile))
98
                    ) : Rx.Observable.empty();
99
                })
100
        );
101

102
/**
103
 * It changes the Geostory tutorial when changing mode only
104
 * when changing to edit the tutorial is shown if not disabled
105
*/
106
export const switchGeostoryTutorialEpic = (action$, store) =>
1✔
107
    action$.ofType(CHANGE_MODE)
5✔
108
        .switchMap( ({mode}) => {
109
            const id = "geostory";
5✔
110
            const state = store.getState();
5✔
111
            const presetList = state.tutorial && state.tutorial.presetList || {};
5!
112
            const geostoryMode = `_${mode}`;
5✔
113
            const steps = !isEmpty(presetList) ? presetList[id + geostoryMode + '_tutorial'] : null;
5!
114
            let isGeostoryTutorialDisabled = false;
5✔
115
            try {
5✔
116
                isGeostoryTutorialDisabled = getApi().getItem("mapstore.plugin.tutorial.geostory.disabled") === "true";
5✔
117
            } catch (e) {
118
                console.error(e);
1✔
119
            }
120
            // if no steps are found then do nothing
121
            return steps ? Rx.Observable.from(
5✔
122
                [
123
                    setupTutorial(id, steps, null, null, null, mode === "view" || isGeostoryTutorialDisabled)
5✔
124
                ]
125
            ) : Rx.Observable.empty();
126
        });
127

128

129
/**
130
 * Handle changePreset action
131
 * @param {external:Observable} action$ manages `CHANGE_PRESET`
132
 * @param {external:Observable} store
133
 */
134
export const changePresetEpic = (action$, store) =>
1✔
135
    action$.ofType(CHANGE_PRESET)
×
136
        .switchMap(({preset, presetGroup, ignoreDisabled}) => {
137
            const state = store.getState();
×
138
            const presetList = state.tutorial && state.tutorial.presetList || {};
×
139
            const checkbox = state.tutorial && state.tutorial.checkbox;
×
140
            const tutorial = presetList[preset];
×
141

142
            return tutorial ?
×
143
                Rx.Observable.of(setupTutorial(preset, tutorial, null, checkbox, null, false, presetGroup, ignoreDisabled)) :
144
                Rx.Observable.empty();
145
        });
146

147
/**
148
 * Get actions from tutorial steps
149
 * @memberof epics.tutorial
150
 * @param {external:Observable} action$ manages `UPDATE_TUTORIAL`
151
 * @return {external:Observable}
152
 */
153

154
export const getActionsFromStepEpic = (action$) =>
1✔
155
    action$.ofType(UPDATE_TUTORIAL)
2✔
156
        .filter(action => action.tour && action.tour.step && action.tour.step.action && action.tour.step.action[action.tour.action])
2✔
157
        .switchMap( (action) => {
158
            return isArray(action.tour.step.action[action.tour.action]) && Rx.Observable.of(...action.tour.step.action[action.tour.action])
2!
159
            || isObject(action.tour.step.action[action.tour.action]) && Rx.Observable.of(action.tour.step.action[action.tour.action])
160
            || Rx.Observable.empty();
161
        });
162

163
/**
164
 * Epics for Tutorial
165
 * @name epics.tutorial
166
 * @type {Object}
167
 */
168

169
export const openDetailsPanelEpic = (action$, store) =>
1✔
170
    action$.ofType(CLOSE_TUTORIAL)
4✔
171
        .filter(() => {
172
            const state = store.getState();
4✔
173
            let detailsSettings = detailsSettingsSelector(state);
4✔
174
            if (detailsSettings && typeof detailsSettings === 'string') {
4!
NEW
175
                detailsSettings = JSON.parse(detailsSettings);
×
176
            }
177
            return detailsSettings?.showAtStartup;
4✔
178
        })
179
        .switchMap( () => {
180
            return Rx.Observable.of(openDetailsPanel());
2✔
181
        });
182

183

184
export default {
185
    closeTutorialEpic,
186
    switchTutorialEpic,
187
    getActionsFromStepEpic,
188
    changePresetEpic,
189
    switchGeostoryTutorialEpic,
190
    openDetailsPanelEpic
191
};
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