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

geosolutions-it / MapStore2 / 14359153796

09 Apr 2025 02:02PM UTC coverage: 76.955% (-0.03%) from 76.985%
14359153796

Pull #10950

github

web-flow
Merge c89fb6e0a into 3ad831e94
Pull Request #10950: Fix #10947 Updated dockerfile to static files for standard templates

31008 of 48285 branches covered (64.22%)

38489 of 50015 relevant lines covered (76.95%)

35.82 hits per line

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

75.0
/web/client/plugins/TOC/components/VectorLegend.jsx
1
/*
2
 * Copyright 2022, 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
import React from 'react';
9
import PropTypes from 'prop-types';
10
import get from 'lodash/get';
11
import isEmpty from 'lodash/isEmpty';
12
import { Alert } from 'react-bootstrap';
13

14
import Message from '../../../components/I18N/Message';
15
import { ButtonWithTooltip } from '../../../components/misc/Button';
16
import RuleLegendIcon from '../../../components/styleeditor/RuleLegendIcon';
17
import { INTERACTIVE_LEGEND_ID } from '../../../utils/LegendUtils';
18
import { updateLayerWFSVectorLegendFilter } from '../../../utils/FilterUtils';
19

20
/**
21
 * VectorLegend renders the legend given a valid vector style
22
 * @prop {object} style a layer style object in geostyler format
23
 * @prop {object} layer the vector layer object
24
 * @prop {boolean} interactive the indicator flag that refers if this legend is interactive or not
25
 * @prop {function} onChange the onChange layer handler
26
 */
27
function VectorLegend({ style, layer, interactive, onChange }) {
28
    const onResetLegendFilter = () => {
11✔
29
        const newLayerFilter = updateLayerWFSVectorLegendFilter(layer?.layerFilter);
×
30
        onChange({ layerFilter: newLayerFilter });
×
31
    };
32
    const filterLayerHandler = (filter) => {
11✔
33
        const newLayerFilter = updateLayerWFSVectorLegendFilter(layer?.layerFilter, filter);
×
34
        onChange({ layerFilter: newLayerFilter });
×
35
    };
36
    const checkPreviousFiltersAreValid = (rules, prevLegendFilters) => {
11✔
37
        const rulesFilters = rules.map(rule => rule?.filter?.toString());
20✔
38
        return prevLegendFilters?.every(f => rulesFilters.includes(f.id));
11✔
39
    };
40
    const renderRules = (rules) => {
11✔
41
        const layerFilter = get(layer, 'layerFilter', {});
11✔
42
        const interactiveLegendFilters = get(layerFilter, 'filters', []).find(f => f.id === INTERACTIVE_LEGEND_ID);
11✔
43
        const legendFilters = get(interactiveLegendFilters, 'filters', []);
11✔
44
        const showResetWarning = !checkPreviousFiltersAreValid(rules, legendFilters) && !layerFilter.disabled;
11✔
45
        const isNotInteractiveLegend = !(interactive && layer?.enableInteractiveLegend);
11✔
46
        return (<>
11✔
47
            {showResetWarning && !isNotInteractiveLegend ? <Alert bsStyle="warning">
23✔
48
                <div><Message msgId={"layerProperties.interactiveLegend.incompatibleWFSFilterWarning"} /></div>
49
                <ButtonWithTooltip
50
                    bsStyle="primary"
51
                    bsSize="xs"
52
                    style={{ marginTop: 4 }}
53
                    onClick={onResetLegendFilter}>
54
                    <Message msgId={"layerProperties.interactiveLegend.resetLegendFilter"} />
55
                </ButtonWithTooltip>
56
            </Alert> : null}
57
            {isEmpty(rules)
11✔
58
                ? <Message msgId={"layerProperties.interactiveLegend.noLegendData"} />
59
                : (rules || []).map((rule, idx) => {
10!
60
                    const isFilterDisabled = layer?.layerFilter?.disabled;
20✔
61
                    const activeFilter = legendFilters?.some(f => f.id === rule?.filter?.toString());
20✔
62
                    const isLegendFilterNotApplicable = isFilterDisabled || isNotInteractiveLegend || !rule?.filter;
20✔
63

64
                    return (<div key={`${rule.filter}-${idx}`}
20✔
65
                        onClick={() => {
66
                            // don't call filter handler if it is not interactive legend or filter is disabled or the filter rule is not truthy value
67
                            if (isLegendFilterNotApplicable) return;
×
68
                            filterLayerHandler(rule.filter);
×
69
                        }}
70
                        className={`ms-legend-rule ${isLegendFilterNotApplicable ? "" : "filter-enabled "} ${activeFilter && interactive ? 'active' : ''}`}>
60!
71
                        <RuleLegendIcon rule={rule} />
72
                        <span>{rule.name || ''}</span>
21✔
73
                    </div>);
74
                })}
75
        </>);
76
    };
77

78
    return <>
11✔
79
        {
80
            style.format === 'geostyler' && <div className="ms-legend">
22✔
81
                {renderRules(style.body.rules)}
82
            </div>
83
        }
84
    </>;
85
}
86

87
VectorLegend.propTypes = {
1✔
88
    style: PropTypes.object,
89
    layer: PropTypes.object,
90
    interactive: PropTypes.bool,
91
    onChange: PropTypes.func
92
};
93

94
export default VectorLegend;
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