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

geosolutions-it / MapStore2 / 14246996716

03 Apr 2025 03:34PM UTC coverage: 76.922% (-0.05%) from 76.971%
14246996716

Pull #10925

github

web-flow
Merge 775cc2f92 into 646bb6e37
Pull Request #10925: #10923, #10924: Disabling GeoFence Rules and Add filter by IP for GeoFence rules

31068 of 48387 branches covered (64.21%)

61 of 109 new or added lines in 10 files covered. (55.96%)

147 existing lines in 34 files now uncovered.

38588 of 50165 relevant lines covered (76.92%)

35.81 hits per line

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

35.94
/web/client/components/contextcreator/ConfigureMapTemplates.jsx
1
/*
2
 * Copyright 2019, 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 React from 'react';
10
import {get, isString, isObject} from 'lodash';
11
import {Glyphicon} from 'react-bootstrap';
12
import jsonlint from 'jsonlint-mod';
13

14
import {formatToGlyph, formatToText} from '../../utils/FileFormatUtils';
15
import Transfer from '../misc/transfer/Transfer';
16
import ConfirmDialog from '../layout/ConfirmDialog';
17
import Message from '../I18N/Message';
18
import SaveModal from '../resources/modals/Save';
19
import handleSaveModal from '../resources/modals/enhancers/handleSaveModal';
20

21
const SaveDialog = handleSaveModal(SaveModal);
1✔
22

23
const templateToItem = (onEditTemplate, onDelete, template) => ({
4✔
24
    id: template.id,
25
    title: template.name || template.id.toString(),
4!
26
    description: template.description,
27
    tools: [{
28
        glyph: 'pencil',
29
        tooltipId: 'contextCreator.configureTemplates.tooltips.editTemplate',
30
        onClick: () => onEditTemplate(template.id)
1✔
31
    }, {
32
        glyph: 'trash',
33
        tooltipId: 'contextCreator.configureTemplates.tooltips.deleteTemplate',
34
        onClick: () => onDelete(template)
1✔
35
    }],
36
    preview:
37
        <div className="configure-map-templates-preview">
38
            {template.thumbnail && template.thumbnail !== 'NODATA' ? <img src={template.thumbnail}/> : <Glyphicon glyph="1-map"/>}
8!
39
        </div>,
40
    infoExtra:
41
        template.format && <div className="configure-map-templates-formaticon">
4!
42
            <Glyphicon glyph={formatToGlyph[template.format]}/>
43
            <span>{formatToText[template.format]}</span>
44
        </div>
45
});
46

47
const pickIds = items => items && items.map(item => item.id);
1!
48

49
const processData = (setParsedTemplate, setFileDropStatus, onError, type, fileName, data) => {
1✔
50
    const parseJSON = () => {
×
51
        try {
×
52
            const mapConfig = jsonlint.parse(data);
×
53
            setParsedTemplate(fileName, mapConfig, 'json');
×
54
            setFileDropStatus('accepted');
×
55
            onError([]);
×
56
        } catch (e) {
57
            setFileDropStatus('clear');
×
58
            onError([{
×
59
                statusText: 'contextCreator.configureTemplates.uploadDialog.jsonParsingError',
60
                error: e.message
61
            }]);
62
        }
63
    };
64

65
    const saveXML = () => {
×
66
        setParsedTemplate(fileName, data, 'wmc');
×
67
        setFileDropStatus('accepted');
×
68
        onError([]);
×
69
    };
70

71
    if (!isString(type) || !isString(data)) {
×
72
        return;
×
73
    }
74
    if (type.indexOf('application/xml') > -1 || type.indexOf('text/xml') > -1 || data.indexOf('<?xml') === 0) {
×
75
        saveXML();
×
76
    } else {
77
        parseJSON();
×
78
    }
79
};
80

81
const onTemplateDrop = (setParsedTemplate, setFileDropStatus, onError, files) => {
1✔
82
    if (files && files.length > 0) {
×
83
        let fileReader = new FileReader;
×
84
        fileReader.onload = e => processData(setParsedTemplate, setFileDropStatus, onError, files[0].type, files[0].name, e.target.result);
×
85
        fileReader.onerror = () => {
×
86
            fileReader.abort();
×
87
            setFileDropStatus('clear');
×
88
            onError(['contextCreator.configureTemplates.uploadDialog.fileReadError']);
×
89
        };
90
        fileReader.readAsText(files[0]);
×
91
    }
92
};
93

94
export default ({
95
    user,
96
    loading,
97
    loadFlags,
98
    mapTemplates = [],
1✔
99
    availableTemplatesFilterText = "",
5✔
100
    enabledTemplatesFilterText = "",
5✔
101
    availableTemplatesFilterPlaceholder = "contextCreator.configureTemplates.templatesFilterPlaceholder",
5✔
102
    enabledTemplatesFilterPlaceholder = "contextCreator.configureTemplates.templatesFilterPlaceholder",
5✔
103
    showUploadDialog = false,
4✔
104
    parsedTemplate = {},
5✔
105
    editedTemplate,
106
    fileDropStatus,
107
    changeTemplatesKey = () => {},
5✔
108
    setSelectedTemplates = () => {},
5✔
109
    setParsedTemplate = () => {},
5✔
110
    setFileDropStatus = () => {},
5✔
111
    onSave = () => {},
5✔
112
    onDelete = () => {},
2✔
113
    onEditTemplate = () => {},
2✔
114
    onFilterAvailableTemplates = () => {},
5✔
115
    onFilterEnabledTemplates = () => {},
5✔
116
    onShowUploadDialog = () => {}
5✔
117
}) => {
118
    const [showDeleteConfirm, onShowDeleteConfirm] = React.useState(false);
5✔
119
    const [templateToDelete, setTemplateToDelete] = React.useState();
5✔
120

121
    const onDeleteTemplate = (template) => {
5✔
122
        setTemplateToDelete(template);
1✔
123
        onShowDeleteConfirm(true);
1✔
124
    };
125
    const templateToItemFunc = templateToItem.bind(null, onEditTemplate, onDeleteTemplate);
5✔
126

127
    return (<>
5✔
128
        <Transfer
129
            className="configure-map-templates-transfer"
130
            leftColumn={{
131
                items: mapTemplates.filter(template => !template.enabled).map(templateToItemFunc),
4✔
132
                title: 'contextCreator.configureTemplates.availableTemplates',
133
                tools: [{
134
                    id: 'upload-tool',
135
                    glyph: 'upload',
136
                    tooltipId: 'contextCreator.configureTemplates.tooltips.uploadTool',
137
                    onClick: () => onEditTemplate()
×
138
                }],
139
                filterText: availableTemplatesFilterText,
140
                filterPlaceholder: availableTemplatesFilterPlaceholder,
141
                emptyStateProps: {
142
                    glyph: '1-map',
143
                    title: 'contextCreator.configureTemplates.availableTemplatesEmpty'
144
                },
145
                emptyStateSearchProps: {
146
                    glyph: 'info-sign',
147
                    title: 'contextCreator.configureTemplates.searchResultsEmpty'
148
                },
149
                onFilter: onFilterAvailableTemplates
150
            }}
151
            rightColumn={{
152
                items: mapTemplates.filter(template => template.enabled).map(templateToItemFunc),
4✔
153
                title: 'contextCreator.configureTemplates.enabledTemplates',
154
                filterText: enabledTemplatesFilterText,
155
                filterPlaceholder: enabledTemplatesFilterPlaceholder,
156
                emptyStateProps: {
157
                    glyph: '1-map',
158
                    title: 'contextCreator.configureTemplates.enabledTemplatesEmpty'
159
                },
160
                emptyStateSearchProps: {
161
                    glyph: 'info-sign',
162
                    title: 'contextCreator.configureTemplates.searchResultsEmpty'
163
                },
164
                onFilter: onFilterEnabledTemplates
165
            }}
166
            allowCtrlMultiSelect
167
            selectedItems={mapTemplates.filter(template => template.selected).map(templateToItemFunc)}
4✔
168
            selectedSide={mapTemplates.reduce((result, template) => template.selected && template.enabled || result, false) ?
4!
169
                'right' :
170
                'left'
171
            }
172
            sortStrategy={items => items.slice().sort((x, y) => x.title < y.title ? -1 : x.title > y.title ? 1 : 0)}
10!
173
            filter={(text, items) => items.filter(item => item.title.toLowerCase().indexOf(text.toLowerCase()) > -1)}
10✔
174
            onSelect={items => setSelectedTemplates(pickIds(items))}
×
175
            onTransfer={(items, direction) => changeTemplatesKey(pickIds(items), 'enabled', direction === 'right')}/>
×
176
        <SaveDialog
177
            user={user}
178
            loading={loading && (loadFlags.templateSaving || loadFlags.templateLoading)}
5!
179
            resource={editedTemplate}
180
            isNewResource={!editedTemplate}
181
            clickOutEnabled={false}
182
            category="TEMPLATE"
183
            show={showUploadDialog}
184
            title={editedTemplate ? undefined : "contextCreator.configureTemplates.uploadDialog.title"}
5!
185
            data={parsedTemplate.data}
186
            additionalAttributes={{format: parsedTemplate.format}}
187
            enableFileDrop
188
            acceptedDropFileName={parsedTemplate.fileName}
189
            fileDropStatus={fileDropStatus}
190
            fileDropLabel="contextCreator.configureTemplates.fileDrop.label"
191
            fileDropClearMessage={<Message msgId="contextCreator.configureTemplates.fileDrop.clear"/>}
192
            dialogClassName=" modal-higher"
193
            onFileDrop={onTemplateDrop.bind(null, setParsedTemplate, setFileDropStatus)}
194
            onFileDropClear={() => {
195
                setParsedTemplate();
×
196
                setFileDropStatus();
×
197
            }}
198
            onSave={resource => {
199
                let resourceFormat = resource.attributes.format;
×
200

201
                // try to get format information
202
                if (!resourceFormat) {
×
203
                    if (isString(resource.data)) {
×
204
                        processData((fileName, config, type) => {
×
205
                            resourceFormat = type;
×
206
                        }, () => {}, () => {}, 'application/text', parsedTemplate.fileName, resource.data);
207
                    } else if (isObject(resource.data)) {
×
208
                        resourceFormat = 'json';
×
209
                    }
210
                }
211

212
                return onSave({
×
213
                    ...resource,
214
                    metadata: {
215
                        ...resource.metadata,
216
                        attributes: {
217
                            ...(resource.attributes.thumbnail ? {thumbnail: encodeURIComponent(resource.attributes.thumbnail)} : {}),
×
218
                            ...(resourceFormat ? {format: resourceFormat} : {})
×
219
                        }
220
                    }
221
                });
222
            }}
223
            onClose={() => onShowUploadDialog(false)}/>
×
224
        <ConfirmDialog
225
            show={showDeleteConfirm}
226
            onCancel={() => {
UNCOV
227
                setTemplateToDelete();
×
UNCOV
228
                onShowDeleteConfirm(false);
×
229
            }}
230
            onConfirm={() => {
231
                onDelete(templateToDelete);
1✔
232
                setTemplateToDelete();
1✔
233
                onShowDeleteConfirm(false);
1✔
234
            }}
235
            titleId={"contextCreator.configureTemplates.deleteConfirm"}
236
            titleParams={{templateName: get(templateToDelete, 'name')}}
237
            preventHide
238
            variant="danger"
239
            confirmId="confirm"
240
            cancelId="cancel">
241
        </ConfirmDialog>
242
    </>);
243
};
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