• 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

42.5
/web/client/components/dashboard/WidgetViewWrapper.jsx
1
import React from 'react';
2
import WidgetsView from '../widgets/view/WidgetsView';
3
import ViewSwitcher from './ViewSwitcher';
4
import uuidv1 from 'uuid/v1';
5
import { getNextAvailableName } from '../../utils/WidgetsUtils';
6
import ConfigureView from './ConfigureView';
7
import FlexBox from '../layout/FlexBox';
8

9
const WidgetViewWrapper = props => {
1✔
10
    const { layouts = [], onLayoutViewReplace, selectedLayoutId, onLayoutViewSelected, active, setActive, widgets = [], onWidgetsReplace } = props;
3!
11

12
    const getSelectedLayout = () => {
3✔
13
        if (Array.isArray(layouts)) {
3!
14
            return layouts.find(l => l?.id === selectedLayoutId) || {};
3✔
15
        }
16
        // fallback for old object format
NEW
17
        return layouts;
×
18
    };
19

20
    const handleSelectLayout = (id) => {
3✔
NEW
21
        onLayoutViewSelected(id);
×
22
    };
23

24
    // strip out "properties" before passing
25
    const selectedLayout = getSelectedLayout();
3✔
26
    const { id, name, color, order, ...layoutForWidgets } = selectedLayout;
3✔
27

28
    const filteredProps = {...props};
3✔
29
    if (props.widgets) {
3!
30
        filteredProps.widgets = props.widgets.filter(widget => widget.layoutId === selectedLayoutId);
3✔
31
    }
32

33
    const handleAddLayout = () => {
3✔
NEW
34
        const newLayout = {
×
35
            id: uuidv1(),
36
            name: getNextAvailableName(layouts),
37
            color: null,
38
            md: [],
39
            xxs: []
40
        };
NEW
41
        const finalLayout = [...layouts, newLayout];
×
NEW
42
        onLayoutViewReplace?.(finalLayout);
×
NEW
43
        onLayoutViewSelected(newLayout.id);
×
44
    };
45

46
    const handleRemoveLayout = (layoutId) => {
3✔
NEW
47
        const updatedLayouts = layouts.filter(layout => layout.id !== layoutId);
×
NEW
48
        onLayoutViewReplace(updatedLayouts);
×
NEW
49
        onLayoutViewSelected(updatedLayouts?.[updatedLayouts.length - 1]?.id);
×
50

NEW
51
        const updatedWidgets = widgets.filter(w => w.layoutId !== layoutId);
×
NEW
52
        onWidgetsReplace(updatedWidgets);
×
53
    };
54

55
    const handleMoveLayout = (layoutId, direction) => {
3✔
NEW
56
        const index = layouts.findIndex(layout => layout.id === layoutId);
×
NEW
57
        if (index === -1) return; // Layout not found
×
58

59
        // Clone the array to avoid mutating state directly
NEW
60
        const updatedLayouts = [...layouts];
×
61

NEW
62
        if (direction === "left" && index > 0) {
×
63
            // Swap with the previous layout
NEW
64
            [updatedLayouts[index - 1], updatedLayouts[index]] = [updatedLayouts[index], updatedLayouts[index - 1]];
×
NEW
65
        } else if (direction === "right" && index < updatedLayouts.length - 1) {
×
66
            // Swap with the next layout
NEW
67
            [updatedLayouts[index], updatedLayouts[index + 1]] = [updatedLayouts[index + 1], updatedLayouts[index]];
×
68
        }
NEW
69
        onLayoutViewReplace(updatedLayouts);
×
70
    };
71

72
    const handleToggle = () => setActive(false);
3✔
73

74
    const handleSave = (data) => {
3✔
NEW
75
        const updatedLayouts = layouts.map(layout => layout.id === id
×
76
            ? { ...layout, name: data.name, color: data.color }
77
            : layout
78
        );
NEW
79
        onLayoutViewReplace(updatedLayouts);
×
NEW
80
        setActive(false);
×
81
    };
82

83
    return (
3✔
84
        <FlexBox column classNames={["_relative", "_fill"]}>
85
            <FlexBox.Fill classNames={["_relative", "_overflow-auto"]}>
86
                <WidgetsView
87
                    {...filteredProps}
88
                    layouts={layoutForWidgets} // only selected layout without properties
89
                />
90
            </FlexBox.Fill>
91
            <ViewSwitcher
92
                layouts={Array.isArray(layouts) ? layouts : [layouts]}
3!
93
                selectedLayoutId={selectedLayoutId}
94
                onSelect={handleSelectLayout}
95
                onAdd={handleAddLayout}
96
                onRemove={handleRemoveLayout}
97
                onMove={handleMoveLayout}
NEW
98
                onConfigure={() => setActive(true)}
×
99
                canEdit={props.canEdit}
100
            />
101
            <ConfigureView
102
                active={active}
103
                onToggle={handleToggle}
104
                onSave={handleSave}
105
                name={name}
106
                color={color}
107
            />
108
        </FlexBox>
109
    );
110
};
111

112
export default WidgetViewWrapper;
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