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

geosolutions-it / MapStore2 / 18371528919

09 Oct 2025 09:16AM UTC coverage: 76.738% (-0.05%) from 76.789%
18371528919

Pull #11572

github

web-flow
Merge 62e9c9670 into 2686c544e
Pull Request #11572: Feat: #11527 Add the tabbed view for the dashboard

31855 of 49574 branches covered (64.26%)

94 of 155 new or added lines in 10 files covered. (60.65%)

3 existing lines in 2 files now uncovered.

39633 of 51647 relevant lines covered (76.74%)

37.71 hits per line

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

25.0
/web/client/components/dashboard/ViewSwitcher.jsx
1
import React, { useRef, useState } from 'react';
2
import { Button, Dropdown, Glyphicon, MenuItem } from 'react-bootstrap';
3
import Message from '../I18N/Message';
4
import withConfirm from '../misc/withConfirm';
5
import FlexBox from '../layout/FlexBox';
6
import useCheckScroll from './hooks/useCheckScroll';
7

8
const WithConfirmButton = withConfirm(MenuItem);
1✔
9

10
const View = ({ handleSelect, isSelected, id, color, name, onRemove, onMove, canDelete, onConfigure, canMoveLeft, canMoveRight, canEdit }) => {
1✔
NEW
11
    const [position, setPosition] = useState({ left: 0, bottom: 0 });
×
NEW
12
    const toggleBtnRef = useRef(null);
×
13

NEW
14
    const handleToggleClick = () => {
×
NEW
15
        handleSelect(id);
×
NEW
16
        if (toggleBtnRef.current) {
×
NEW
17
            const rect = toggleBtnRef.current.getBoundingClientRect();
×
NEW
18
            setPosition({
×
19
                left: rect.left,
20
                bottom: window.innerHeight - rect.top
21
            });
22
        }
23
    };
24

NEW
25
    return (
×
26
        <Dropdown
27
            dropup
28
            bsStyle="default"
29
            id="split-button-dropup-pull-right"
30
            className={`${isSelected ? "is-selected " : ""}layout-views _relative`}
×
31
            style={{ borderBottom: `2px solid ${color}` }}
32
        >
33
            <Button
NEW
34
                onClick={() => handleSelect(id)}
×
35
                bsStyle="default" className="layout-views-dropdown _padding-tb-sm"
36
            >
37
                {name}
38
            </Button>
39
            {canEdit && (
×
40
                <Dropdown.Toggle
41
                    onClick={handleToggleClick}
42
                    noCaret
43
                    className="square-button-md dashboard-view-actions _relative _padding-tb-sm _padding-r-sm"
44
                >
45
                    <div ref={toggleBtnRef}>
46
                        <Glyphicon glyph="option-vertical" />
47
                    </div>
48
                </Dropdown.Toggle>
49
            )}
50
            <Dropdown.Menu className="_fixed" style={{ left: `${position.left}px`, bottom: `${position.bottom}px` }}>
51
                <WithConfirmButton
52
                    confirmTitle={<Message msgId="dashboard.view.removeConfirmTitle" />}
53
                    confirmContent={<Message msgId="dashboard.view.removeConfirmContent" />}
NEW
54
                    onClick={() => onRemove(id)}
×
55
                    disabled={!canDelete}
56
                >
57
                    <Glyphicon glyph="trash" />
58
                    <Message msgId="dashboard.view.delete" />
59
                </WithConfirmButton>
60
                <MenuItem
61
                    onClick={() => {
NEW
62
                        onConfigure();
×
63
                    }}
64
                >
65
                    <Glyphicon glyph="cog" />
66
                    <Message msgId="dashboard.view.configure" />
67
                </MenuItem>
68
                <MenuItem
69
                    onClick={() => {
NEW
70
                        onMove(id, 'right');
×
71
                    }}
72
                    disabled={!canMoveRight}
73
                >
74
                    <Glyphicon glyph="arrow-right" />
75
                    <Message msgId="dashboard.view.moveRight" />
76
                </MenuItem>
77
                <MenuItem
78
                    onClick={() => {
NEW
79
                        onMove(id, 'left');
×
80
                    }}
81
                    disabled={!canMoveLeft}
82
                >
83
                    <Glyphicon glyph="arrow-left" />
84
                    <Message msgId="dashboard.view.moveLeft" />
85
                </MenuItem>
86
            </Dropdown.Menu>
87
        </Dropdown>);
88
};
89

90
const ViewSwitcher = ({ layouts = [], selectedLayoutId, onSelect, onAdd, onRemove, onMove, onConfigure, canEdit }) => {
1!
91
    const handleSelect = (id) => {
3✔
NEW
92
        onSelect?.(id);
×
93
    };
94

95
    const [scrollRef, showButtons, isLeftDisabled, isRightDisabled, scroll] = useCheckScroll({ data: layouts });
3✔
96

97
    return (
3✔
98
        <FlexBox gap="xs" centerChildrenVertically className="_margin-tb-xs _margin-r-xs view-switcher-container">
99
            {canEdit && (
3!
100
                <Button
101
                    onClick={onAdd}
102
                    className="square-button-md _margin-l-xs"
103
                    title="Add a layout view to the dashboard"
104
                >
105
                    <Glyphicon glyph="plus" />
106
                </Button>
107
            )}
108

109
            {/* Layouts Tabs */}
110
            <FlexBox centerChildrenVertically ref={scrollRef} className="_overflow-auto _fill view-switcher-tabs">
111
                {layouts.map((layout, idx) => {
NEW
112
                    const id = layout.id || idx + 1;
×
NEW
113
                    return (
×
114
                        <View
115
                            key={id}
116
                            id={id}
117
                            name={layout.name}
118
                            color={layout.color}
119
                            handleSelect={handleSelect}
120
                            isSelected={selectedLayoutId === id}
121
                            onRemove={onRemove}
122
                            onMove={onMove}
123
                            onConfigure={onConfigure}
124
                            canDelete={layouts.length > 1}
125
                            canMoveRight={idx !== layouts.length - 1}
126
                            canMoveLeft={idx !== 0}
127
                            canEdit={canEdit}
128
                        />
129
                    );
130
                })}
131
            </FlexBox>
132
            {showButtons && (
3!
133
                <FlexBox gap="xs" centerChildrenVertically className="view-scroll-buttons">
134
                    <Button
135
                        className="square-button-md"
136
                        bsStyle="primary"
NEW
137
                        onClick={() => scroll("left")}
×
138
                        disabled={isLeftDisabled}
139
                        title="Scroll left"
140
                    >
141
                        <Glyphicon glyph="chevron-left" />
142
                    </Button>
143
                    <Button
144
                        className="square-button-md"
145
                        bsStyle="primary"
NEW
146
                        onClick={() => scroll("right")}
×
147
                        disabled={isRightDisabled}
148
                        title="Scroll right"
149
                    >
150
                        <Glyphicon glyph="chevron-right" />
151
                    </Button>
152
                </FlexBox>
153
            )}
154
        </FlexBox>
155
    );
156
};
157

158
export default ViewSwitcher;
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