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

geosolutions-it / MapStore2 / 13963485182

20 Mar 2025 06:43AM UTC coverage: 77.003% (+0.02%) from 76.985%
13963485182

Pull #10945

github

web-flow
Merge 9e0a83af3 into 0067596fe
Pull Request #10945: Fix: #10819 Manager menu merged into User menu.

30989 of 48228 branches covered (64.26%)

57 of 62 new or added lines in 3 files covered. (91.94%)

5 existing lines in 1 file now uncovered.

38521 of 50025 relevant lines covered (77.0%)

35.76 hits per line

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

88.1
/web/client/components/security/UserMenu.jsx
1
import PropTypes from 'prop-types';
2

3
/**
4
 * Copyright 2016, GeoSolutions Sas.
5
 * All rights reserved.
6
 *
7
 * This source code is licensed under the BSD-style license found in the
8
 * LICENSE file in the root directory of this source tree.
9
 */
10

11
import React from 'react';
12

13
import { DropdownButton, MenuItem, NavDropdown, Glyphicon } from 'react-bootstrap';
14
import Message from '../I18N/Message';
15
import ConfirmModal from '../misc/ResizableModal';
16
import tooltip from "../misc/enhancers/tooltip";
17

18
const TNavDropdown = tooltip(NavDropdown);
1✔
19
const TDropdownButton = tooltip(DropdownButton);
1✔
20

21
function UserMenuItem({
22
    href,
23
    glyph,
24
    msgId,
25
    text,
26
    onClick
27
}) {
NEW
28
    return (<>
×
29
        <MenuItem {...(href ? { href } : {})} onClick={onClick}>
×
30
            <Glyphicon glyph={glyph} />{  msgId ? <Message msgId={msgId} /> : text}
×
31
        </MenuItem>
32
    </>
33
    );
34
}
35

36
UserMenuItem.propTypes = {
1✔
37
    href: PropTypes.string,
38
    glyph: PropTypes.string,
39
    msgId: PropTypes.string,
40
    text: PropTypes.string,
41
    onClick: PropTypes.func
42
};
43

44
const UserMenu = ({
1✔
45
    user,
46
    displayName,
47
    providers,
48
    showAccountInfo,
49
    showPasswordChange,
50
    showLogout,
51
    hidden,
52
    displayUnsavedDialog,
53
    bsStyle,
54
    tooltipPosition,
55
    renderButtonText,
56
    nav,
57
    menuProps,
58
    renderButtonContent,
59
    onShowAccountInfo,
60
    onShowChangePassword,
61
    onShowLogin,
62
    onLogout,
63
    onCheckMapChanges,
64
    className,
65
    renderUnsavedMapChangesDialog,
66
    onCloseUnsavedDialog,
67
    isAdmin,
68
    managerItems
69
}) => {
70

71
    const logout = () => {
19✔
72
        onCloseUnsavedDialog();
1✔
73
        onLogout();
1✔
74
    };
75

76
    const checkUnsavedChanges = () => {
19✔
NEW
77
        if (renderUnsavedMapChangesDialog) {
×
NEW
78
            onCheckMapChanges(onLogout);
×
79
        } else {
NEW
80
            logout();
×
81
        }
82
    };
83

84
    const renderButtonText_ = () => {
19✔
85
        return renderButtonContent
19!
86
            ? renderButtonContent({ user, renderButtonText, displayName })
87
            : [
88
                <Glyphicon key="icon" glyph="user" />,
89
                renderButtonText ? (user?.[displayName] || "Guest") : null
×
90
            ];
91
    };
92

93
    const renderGuestTools = () => {
19✔
94
        const DropDown = nav ? TNavDropdown : TDropdownButton;
6!
95
        return (
6✔
96
            <DropDown
97
                className={className}
98
                pullRight
99
                bsStyle={bsStyle}
100
                title={renderButtonText_()}
101
                id="dropdown-basic-primary"
102
                tooltipId="user.login"
103
                tooltipPosition={tooltipPosition}
104
                {...menuProps}>
105
                <MenuItem onClick={() => onShowLogin(providers)}>
1✔
106
                    <Glyphicon glyph="log-in" />
107
                    <Message msgId="user.login"/>
108
                </MenuItem>
109
            </DropDown>
110
        );
111
    };
112

113
    const renderLoggedTools = () => {
19✔
114
        const DropDown = nav ? TNavDropdown : TDropdownButton;
13!
115
        const itemArray = [];
13✔
116

117
        if (showAccountInfo) {
13✔
118
            itemArray.push(
11✔
119
                <MenuItem key="accountInfo" onClick={onShowAccountInfo}>
120
                    <Glyphicon glyph="user" />
121
                    <Message msgId="user.info"/>
122
                </MenuItem>
123
            );
124
        }
125

126
        if (showPasswordChange) {
13✔
127
            itemArray.push(
8✔
128
                <MenuItem key="passwordChange" onClick={onShowChangePassword}>
129
                    <Glyphicon glyph="asterisk" />
130
                    <Message msgId="user.changePwd"/>
131
                </MenuItem>
132
            );
133
        }
134

135
        if (isAdmin) {
13✔
136
            if (managerItems.length > 0) {
1!
137
                itemArray.push(<MenuItem key="1-divider" divider />);
1✔
138
            }
139

140
            managerItems?.forEach((item, key) => {
1✔
141
                if (item.Component) {
2!
NEW
142
                    (
×
143
                        itemArray.push(
144
                            <item.Component
145
                                key={item.name || key}
×
146
                                itemComponent={UserMenuItem}
147
                            />
148
                        ));
149
                } else {
150
                    const href = item.path ? `#${item.path}` : null;
2✔
151
                    itemArray.push(
2✔
152
                        <MenuItem href={href} key={item.name || key} onClick={item.onClick}>
2!
153
                            <Glyphicon glyph={item.glyph} />
154
                            <Message msgId={item.msgId}/>
155
                        </MenuItem>
156
                    );
157
                }
158

159
            });
160

161
        }
162

163
        if (showLogout) {
13!
164
            if (itemArray.length > 0) {
13✔
165
                itemArray.push(<MenuItem key="2-divider" divider />);
11✔
166
            }
167
            itemArray.push(
13✔
168
                <MenuItem key="logout" onClick={checkUnsavedChanges}>
169
                    <Glyphicon glyph="log-out" />
170
                    <Message msgId="user.logout"/>
171
                </MenuItem>
172
            );
173
        }
174
        return (
13✔
175
            <React.Fragment>
176
                <DropDown
177
                    id="loginButton"
178
                    className={className}
179
                    pullRight
180
                    bsStyle="success"
181
                    title={renderButtonText_()}
182
                    tooltipId="user.userMenu"
183
                    tooltipPosition={tooltipPosition}
184
                    {...menuProps}
185
                >
186
                    <span key="logged-user">
187
                        <MenuItem header>{user.name}</MenuItem>
188
                    </span>
189
                    {itemArray}
190
                </DropDown>
191
                <ConfirmModal
192
                    show={displayUnsavedDialog || false}
24✔
193
                    onClose={onCloseUnsavedDialog}
194
                    title={<Message msgId="resources.maps.unsavedMapConfirmTitle" />}
195
                    buttons={[{
196
                        bsStyle: "primary",
197
                        text: <Message msgId="resources.maps.unsavedMapConfirmButtonText" />,
198
                        onClick: logout
199
                    }, {
200
                        text: <Message msgId="resources.maps.unsavedMapCancelButtonText" />,
201
                        onClick: onCloseUnsavedDialog
202
                    }]}
203
                    fitContent
204
                >
205
                    <div className="ms-detail-body">
206
                        <Message msgId="resources.maps.unsavedMapConfirmMessage" />
207
                    </div>
208
                </ConfirmModal>
209
            </React.Fragment>
210
        );
211
    };
212

213
    if (hidden) return null;
19!
214
    return user?.[displayName] ? renderLoggedTools() : renderGuestTools();
19✔
215
};
216

217
UserMenu.propTypes = {
1✔
218
    user: PropTypes.object,
219
    displayName: PropTypes.string,
220
    providers: PropTypes.array,
221
    showAccountInfo: PropTypes.bool,
222
    showPasswordChange: PropTypes.bool,
223
    showLogout: PropTypes.bool,
224
    hidden: PropTypes.bool,
225
    displayUnsavedDialog: PropTypes.bool,
226
    displayAttributes: PropTypes.func,
227
    bsStyle: PropTypes.string,
228
    tooltipPosition: PropTypes.string,
229
    renderButtonText: PropTypes.bool,
230
    nav: PropTypes.bool,
231
    menuProps: PropTypes.object,
232
    renderButtonContent: PropTypes.func,
233
    onShowAccountInfo: PropTypes.func,
234
    onShowChangePassword: PropTypes.func,
235
    onShowLogin: PropTypes.func,
236
    onLogout: PropTypes.func,
237
    onCheckMapChanges: PropTypes.func,
238
    className: PropTypes.string,
239
    renderUnsavedMapChangesDialog: PropTypes.bool,
240
    onLogoutConfirm: PropTypes.func,
241
    onCloseUnsavedDialog: PropTypes.func
242
};
243

244

245
UserMenu.defaultProps = {
1✔
246
    displayName: "name",
247
    showAccountInfo: true,
248
    showPasswordChange: true,
249
    showLogout: true,
250
    hidden: false,
251
    displayUnsavedDialog: false,
252
    displayAttributes: () => {},
253
    bsStyle: "primary",
254
    tooltipPosition: 'bottom',
255
    renderButtonText: false,
256
    nav: false,
257
    menuProps: { noCaret: true },
258
    renderButtonContent: () => {},
259
    onShowAccountInfo: () => {},
260
    onShowChangePassword: () => {},
261
    onShowLogin: () => {},
262
    onLogout: () => {},
263
    onCheckMapChanges: () => {},
264
    className: "user-menu",
265
    renderUnsavedMapChangesDialog: true,
266
    onCloseUnsavedDialog: () => {}
267
};
268

269
export default UserMenu;
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