@geogirafe/lib-geoportal 1.0.2217896135 → 1.0.2220854497
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/search/component.d.ts +7 -7
- package/components/search/component.js +59 -100
- package/components/search-mobile/component.js +1 -1
- package/models/main.d.ts +1 -2
- package/models/main.js +0 -1
- package/models/searchresult.d.ts +3 -26
- package/models/searchresult.js +1 -6
- package/package.json +1 -1
- package/templates/public/about.json +1 -1
- package/tools/configuration/girafeconfig.d.ts +1 -0
- package/tools/configuration/girafeconfig.js +3 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
|
+
import Feature from 'ol/Feature';
|
|
1
2
|
import GirafeHTMLElement from '../../base/GirafeHTMLElement';
|
|
2
|
-
import type { AllSearchResults } from '../../models/searchresult';
|
|
3
|
-
import SearchResult from '../../models/searchresult';
|
|
4
3
|
declare class SearchComponent extends GirafeHTMLElement {
|
|
5
4
|
template: () => import("uhtml").Hole;
|
|
6
5
|
searchIcon: string;
|
|
@@ -10,9 +9,10 @@ declare class SearchComponent extends GirafeHTMLElement {
|
|
|
10
9
|
private previewLayers;
|
|
11
10
|
private previewGeoLayer;
|
|
12
11
|
private maxExtent?;
|
|
12
|
+
private readonly geoJsonFormatter;
|
|
13
13
|
private ignoreBlur;
|
|
14
|
-
groupedResults: Record<string,
|
|
15
|
-
protected allResults:
|
|
14
|
+
groupedResults: Record<string, Feature[]>;
|
|
15
|
+
protected allResults: Feature[];
|
|
16
16
|
protected forceHide: boolean;
|
|
17
17
|
private readonly searchTermPlaceholder;
|
|
18
18
|
private readonly searchLangPlaceholder;
|
|
@@ -39,7 +39,7 @@ declare class SearchComponent extends GirafeHTMLElement {
|
|
|
39
39
|
protected connectedCallback(): void;
|
|
40
40
|
protected clearSearch(purge?: boolean): void;
|
|
41
41
|
doSearch(e: Event): Promise<void>;
|
|
42
|
-
protected fetchSearch(term: string): Promise<
|
|
42
|
+
protected fetchSearch(term: string): Promise<Feature[]>;
|
|
43
43
|
/**
|
|
44
44
|
* Debounce the fetch call to API to prevent sending request at every stroke.
|
|
45
45
|
* @param e
|
|
@@ -52,14 +52,14 @@ declare class SearchComponent extends GirafeHTMLElement {
|
|
|
52
52
|
private displayCoordinates;
|
|
53
53
|
private displayResults;
|
|
54
54
|
getIcon(searchGroup: string): any;
|
|
55
|
-
onMouseOver(result:
|
|
55
|
+
onMouseOver(result: Feature): void;
|
|
56
56
|
onMouseLeave(): void;
|
|
57
57
|
private focusResultFromIndex;
|
|
58
58
|
private focusResult;
|
|
59
59
|
private preview;
|
|
60
60
|
private addFeatureToPreview;
|
|
61
61
|
clearPreview(): void;
|
|
62
|
-
onSelect(
|
|
62
|
+
onSelect(feature: Feature): void;
|
|
63
63
|
private addResultToTreeView;
|
|
64
64
|
private zoomTo;
|
|
65
65
|
onMouseMove(): void;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { html as uHtml } from 'uhtml';
|
|
2
2
|
import Collection from 'ol/Collection';
|
|
3
3
|
import Feature from 'ol/Feature';
|
|
4
|
+
import GeoJSON from 'ol/format/GeoJSON';
|
|
4
5
|
import VectorSource from 'ol/source/Vector';
|
|
5
6
|
import VectorLayer from 'ol/layer/Vector';
|
|
6
|
-
import {
|
|
7
|
+
import { Point } from 'ol/geom';
|
|
7
8
|
import { Style, Icon, Stroke, Fill } from 'ol/style';
|
|
8
9
|
import { buffer, getWidth, getHeight, getCenter, containsExtent } from 'ol/extent';
|
|
9
10
|
import GirafeColorPicker from '../../tools/utils/girafecolorpicker';
|
|
@@ -21,7 +22,7 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
21
22
|
</style><style>
|
|
22
23
|
.hidden{display:none}#searchbox{background-color:var(--bkg-color);border:1px solid #cfd6dd;border-radius:4px;flex-direction:row;width:100%;height:2.25rem;display:flex}#search{-webkit-appearance:none;width:auto;height:2.25rem;color:var(--text-color);background:0 0;border:0;outline:none;-webkit-flex:auto;-ms-flex:auto;flex:auto;margin:0 0 0 .5rem;padding-left:.8rem;font-size:1rem}.search-icon,.close-icon,.select-color-icon{width:14px;color:var(--text-color);padding:0 1rem}.close-button,.select-color-button{cursor:pointer;background-color:#0000;border:none;padding:0}#results{z-index:1000;background-color:var(--bkg-color);scrollbar-width:thin;width:36rem;max-height:31rem;margin-top:.1rem;margin-bottom:.5rem;position:absolute;top:3.5rem;overflow-x:hidden}.result,.title{width:34rem;padding:.3rem 1rem;line-height:1.3rem;display:inline-block}.title{color:var(--text-color);padding-top:1.5rem;font-size:1.3rem;font-weight:600;line-height:2.5rem}.result{cursor:pointer;text-align:left;width:100%;color:var(--text-color);background:0 0;border:none;border-top:1px solid #ccc}.title img{width:14px;margin-right:1rem}.title span{text-transform:uppercase}.result.selected{color:var(--text-color);background-color:#aaa!important}#no-result{background:var(--warning-color);opacity:.75;visibility:hidden;pointer-events:none;border-radius:6px;width:fit-content;margin:auto;padding:.5rem 0;font-size:1rem;position:absolute;top:3.5rem;left:0;right:0}#no-result>span{padding:1.3rem}@keyframes fadeOut{0%{opacity:1}80%{opacity:1}to{opacity:0}}.shown-then-fadeout{animation:2s ease-in-out forwards fadeOut;visibility:visible!important}
|
|
23
24
|
</style>
|
|
24
|
-
<link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><link rel="stylesheet" href="styles/girafecolorpicker.css"><div id="searchbox"><input tip="search_tip" id="search" class="gg-input" length="20" maxlength="1000" autocomplete="off" autocorrect="off" i18n="Search..." placeholder="Search..." oninput="${(e) => this.doSearchDebounced(e)}" onfocusin="${() => this.onFocusIn()}" onfocusout="${() => this.onFocusOut()}" onkeydown="${(e) => this.onKeyDown(e)}"> <img class="${this.allResults.length > 0 ? 'hidden' : 'search-icon'}" alt="search-icon" src="${this.searchIcon}"> <button class="${this.allResults.length > 0 ? 'close-button' : 'hidden'}" onclick="${() => this.clearSearch(true)}"><img class="close-icon" alt="close-icon" src="icons/close.svg"></button> <button tip="change_search_result_color" id="colorPickerBtn" class="${this.paintSearchResults ? 'select-color-button' : 'hidden'}"><img class="select-color-icon" alt="select-color-icon" src="${this.paintbrushIcon}"></button><div id="results" class="${Object.keys(this.groupedResults).length === 0 || this.forceHide ? 'hidden' : ''}" onmousemove="${() => this.onMouseMove()}">${Object.keys(this.groupedResults).map(group => uHtml `<div class="title"><img alt="result icon" src="${this.getIcon(group)}"> <span i18n="${group}"></span></div>${this.groupedResults[group].map(result => uHtml ` <button class="${result.selected ? 'result selected' : 'result'}" onmousedown="${() => this.onMouseDown()}" onclick="${() => this.onSelect(result)}" onmouseover="${() => this.onMouseOver(result)}" onmouseleave="${() => this.onMouseLeave()}">${result.
|
|
25
|
+
<link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><link rel="stylesheet" href="styles/girafecolorpicker.css"><div id="searchbox"><input tip="search_tip" id="search" class="gg-input" length="20" maxlength="1000" autocomplete="off" autocorrect="off" i18n="Search..." placeholder="Search..." oninput="${(e) => this.doSearchDebounced(e)}" onfocusin="${() => this.onFocusIn()}" onfocusout="${() => this.onFocusOut()}" onkeydown="${(e) => this.onKeyDown(e)}"> <img class="${this.allResults.length > 0 ? 'hidden' : 'search-icon'}" alt="search-icon" src="${this.searchIcon}"> <button class="${this.allResults.length > 0 ? 'close-button' : 'hidden'}" onclick="${() => this.clearSearch(true)}"><img class="close-icon" alt="close-icon" src="icons/close.svg"></button> <button tip="change_search_result_color" id="colorPickerBtn" class="${this.paintSearchResults ? 'select-color-button' : 'hidden'}"><img class="select-color-icon" alt="select-color-icon" src="${this.paintbrushIcon}"></button><div id="results" class="${Object.keys(this.groupedResults).length === 0 || this.forceHide ? 'hidden' : ''}" onmousemove="${() => this.onMouseMove()}">${Object.keys(this.groupedResults).map(group => uHtml `<div class="title"><img alt="result icon" src="${this.getIcon(group)}"> <span i18n="${group}"></span></div>${this.groupedResults[group].map(result => uHtml ` <button class="${result.get('selected') ? 'result selected' : 'result'}" onmousedown="${() => this.onMouseDown()}" onclick="${() => this.onSelect(result)}" onmouseover="${() => this.onMouseOver(result)}" onmouseleave="${() => this.onMouseLeave()}">${result.get('label')}</button> `)} `)}</div><div id="no-result" class="${this.showNoResultWarning ? 'shown-then-fadeout' : ''}"><span i18n="${'No match found'}"></span></div></div>`;
|
|
25
26
|
};
|
|
26
27
|
searchIcon = SearchIcon;
|
|
27
28
|
paintbrushIcon = PaintbrushIcon;
|
|
@@ -32,6 +33,7 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
32
33
|
previewLayers = [];
|
|
33
34
|
previewGeoLayer = null;
|
|
34
35
|
maxExtent;
|
|
36
|
+
geoJsonFormatter = new GeoJSON();
|
|
35
37
|
ignoreBlur = false;
|
|
36
38
|
groupedResults = {};
|
|
37
39
|
allResults = [];
|
|
@@ -56,9 +58,9 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
56
58
|
async initialSearch() {
|
|
57
59
|
const searchTerm = this.context.permalinkManager.getSearchTerm();
|
|
58
60
|
const results = await this.fetchSearch(searchTerm);
|
|
59
|
-
if (results.
|
|
61
|
+
if (results.length > 0) {
|
|
60
62
|
// Apply the first search result in the list
|
|
61
|
-
const firstResult = results
|
|
63
|
+
const firstResult = results[0];
|
|
62
64
|
this.preview(firstResult);
|
|
63
65
|
this.onSelect(firstResult);
|
|
64
66
|
}
|
|
@@ -149,13 +151,13 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
149
151
|
}
|
|
150
152
|
if (term.length > 0) {
|
|
151
153
|
try {
|
|
152
|
-
const
|
|
154
|
+
const features = await this.fetchSearch(term);
|
|
153
155
|
// If the search term is at least two charecter but yieds no result, a warning
|
|
154
156
|
// box is displayed for 2 seconds and then fades out (CSS)
|
|
155
|
-
if (
|
|
157
|
+
if (features.length === 0 && term.length >= 2) {
|
|
156
158
|
this.showNoResultWarning = true;
|
|
157
159
|
}
|
|
158
|
-
this.displayResults(
|
|
160
|
+
this.displayResults(features);
|
|
159
161
|
}
|
|
160
162
|
catch (error) {
|
|
161
163
|
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
@@ -172,7 +174,11 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
172
174
|
.replace(this.searchLangPlaceholder, this.state.language);
|
|
173
175
|
const response = await fetch(url, { signal: this.abortController.signal });
|
|
174
176
|
const data = await response.json();
|
|
175
|
-
|
|
177
|
+
const features = this.geoJsonFormatter.readFeatures(data, {
|
|
178
|
+
dataProjection: this.context.configManager.getDefaultConfigValue('search.resultsSrid'),
|
|
179
|
+
featureProjection: this.map.getView().getProjection()
|
|
180
|
+
});
|
|
181
|
+
return features;
|
|
176
182
|
}
|
|
177
183
|
/**
|
|
178
184
|
* Debounce the fetch call to API to prevent sending request at every stroke.
|
|
@@ -206,40 +212,32 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
206
212
|
if (!east_coord || !north_coord) {
|
|
207
213
|
return;
|
|
208
214
|
}
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
label: `${coord1} ${coord2}`,
|
|
217
|
-
layer_name: 'recenter_map'
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
this.allResults = [result];
|
|
221
|
-
this.groupedResults.recenter_map = [result];
|
|
215
|
+
const feature = new Feature({
|
|
216
|
+
geometry: new Point([east_coord, north_coord]),
|
|
217
|
+
label: `${coord1} ${coord2}`,
|
|
218
|
+
layer_name: 'recenter_map'
|
|
219
|
+
});
|
|
220
|
+
this.allResults = [feature];
|
|
221
|
+
this.groupedResults.recenter_map = [feature];
|
|
222
222
|
super.render();
|
|
223
223
|
super.girafeTranslate();
|
|
224
224
|
}
|
|
225
|
-
displayResults(
|
|
225
|
+
displayResults(features) {
|
|
226
226
|
// First, group the results
|
|
227
|
-
for (const result of
|
|
227
|
+
for (const result of features) {
|
|
228
228
|
// results.features.forEach((result) => {
|
|
229
229
|
let type = 'Unknown layer type';
|
|
230
|
-
if (result.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
type = 'add_layer';
|
|
242
|
-
}
|
|
230
|
+
if (result.get('layer_name')) {
|
|
231
|
+
type = result.get('layer_name');
|
|
232
|
+
}
|
|
233
|
+
else if (result.get('actions')[0].action.startsWith('add_theme')) {
|
|
234
|
+
type = 'add_theme';
|
|
235
|
+
}
|
|
236
|
+
else if (result.get('actions')[0].action.startsWith('add_group')) {
|
|
237
|
+
type = 'add_group';
|
|
238
|
+
}
|
|
239
|
+
else if (result.get('actions')[0].action.startsWith('add_layer')) {
|
|
240
|
+
type = 'add_layer';
|
|
243
241
|
}
|
|
244
242
|
let resultList;
|
|
245
243
|
if (type in this.groupedResults) {
|
|
@@ -284,12 +282,12 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
284
282
|
// Clear old selection and preview
|
|
285
283
|
this.clearPreview();
|
|
286
284
|
if (this.focusedResult) {
|
|
287
|
-
this.focusedResult.selected
|
|
285
|
+
this.focusedResult.set('selected', false);
|
|
288
286
|
}
|
|
289
287
|
// Set new selected object, and activate preview
|
|
290
288
|
this.focusedResultIndex = this.allResults.findIndex((r) => r === result);
|
|
291
289
|
this.focusedResult = this.allResults[this.focusedResultIndex];
|
|
292
|
-
this.focusedResult.selected
|
|
290
|
+
this.focusedResult.set('selected', true);
|
|
293
291
|
this.render();
|
|
294
292
|
this.preview(result);
|
|
295
293
|
// Scroll to selected div
|
|
@@ -297,14 +295,12 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
297
295
|
resultHtmlElement.scrollIntoView({ block: 'nearest' });
|
|
298
296
|
}
|
|
299
297
|
preview(result) {
|
|
300
|
-
if (result.
|
|
298
|
+
if (result.getGeometry() && this.context.configManager.Config.search.objectPreview) {
|
|
301
299
|
// Result with geometry
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
this.updatePreviewLayerStyle();
|
|
305
|
-
}
|
|
300
|
+
this.addFeatureToPreview(result);
|
|
301
|
+
this.updatePreviewLayerStyle();
|
|
306
302
|
}
|
|
307
|
-
const firstAction = result.
|
|
303
|
+
const firstAction = result.get('actions')?.[0];
|
|
308
304
|
if (firstAction?.action.startsWith('add_layer') && this.context.configManager.Config.search.layerPreview) {
|
|
309
305
|
const layer = this.context.themesHelper.findLayerByName(firstAction.data);
|
|
310
306
|
if (layer) {
|
|
@@ -317,47 +313,8 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
317
313
|
}
|
|
318
314
|
}
|
|
319
315
|
}
|
|
320
|
-
addFeatureToPreview(
|
|
321
|
-
|
|
322
|
-
case 'Point': {
|
|
323
|
-
const feature = new Feature(new Point(geometry.coordinates));
|
|
324
|
-
this.previewFeaturesCollection.push(feature);
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
case 'MultiPoint': {
|
|
328
|
-
const feature = new Feature(new MultiPoint(geometry.coordinates));
|
|
329
|
-
this.previewFeaturesCollection.push(feature);
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
case 'MultiLineString': {
|
|
333
|
-
const feature = new Feature(new MultiLineString(geometry.coordinates));
|
|
334
|
-
this.previewFeaturesCollection.push(feature);
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
case 'LineString': {
|
|
338
|
-
const feature = new Feature(new LineString(geometry.coordinates));
|
|
339
|
-
this.previewFeaturesCollection.push(feature);
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
case 'Polygon': {
|
|
343
|
-
const feature = new Feature(new Polygon(geometry.coordinates));
|
|
344
|
-
this.previewFeaturesCollection.push(feature);
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
case 'MultiPolygon': {
|
|
348
|
-
const feature = new Feature(new MultiPolygon(geometry.coordinates));
|
|
349
|
-
this.previewFeaturesCollection.push(feature);
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
case 'GeometryCollection': {
|
|
353
|
-
for (const geom of geometry.geometries) {
|
|
354
|
-
this.addFeatureToPreview(geom);
|
|
355
|
-
}
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
default:
|
|
359
|
-
throw new Error('Geometry type of search result is not being supported.');
|
|
360
|
-
}
|
|
316
|
+
addFeatureToPreview(feature) {
|
|
317
|
+
this.previewFeaturesCollection.push(feature);
|
|
361
318
|
}
|
|
362
319
|
clearPreview() {
|
|
363
320
|
// Clear preview search result
|
|
@@ -366,46 +323,48 @@ class SearchComponent extends GirafeHTMLElement {
|
|
|
366
323
|
this.context.themesHelper.removeLayersFromLayerTree(this.previewLayers);
|
|
367
324
|
this.previewLayers = [];
|
|
368
325
|
}
|
|
369
|
-
onSelect(
|
|
370
|
-
this.selectedResult =
|
|
326
|
+
onSelect(feature) {
|
|
327
|
+
this.selectedResult = feature;
|
|
371
328
|
this.ignoreBlur = false;
|
|
372
329
|
this.forceHide = true;
|
|
373
330
|
this.previewLayers = [];
|
|
374
331
|
super.render();
|
|
375
|
-
|
|
332
|
+
const geom = feature.getGeometry();
|
|
333
|
+
if (geom) {
|
|
376
334
|
// Result with geometry
|
|
377
|
-
this.zoomTo(
|
|
335
|
+
this.zoomTo(geom.getExtent());
|
|
378
336
|
}
|
|
379
337
|
else {
|
|
380
|
-
this.addResultToTreeView(
|
|
338
|
+
this.addResultToTreeView(feature);
|
|
381
339
|
}
|
|
382
340
|
this.onFocusOut();
|
|
383
341
|
// Update searchbox with result
|
|
384
|
-
if (this.searchInput &&
|
|
385
|
-
this.searchInput.value =
|
|
342
|
+
if (this.searchInput && feature.get('label')) {
|
|
343
|
+
this.searchInput.value = feature.get('label');
|
|
386
344
|
}
|
|
387
345
|
}
|
|
388
|
-
addResultToTreeView(
|
|
346
|
+
addResultToTreeView(feature) {
|
|
389
347
|
let clonedTheme;
|
|
390
|
-
|
|
348
|
+
const actions = feature.get('actions');
|
|
349
|
+
if (!actions || actions.length === 0) {
|
|
391
350
|
// Nothing to add
|
|
392
351
|
return;
|
|
393
352
|
}
|
|
394
353
|
let activate = false;
|
|
395
|
-
if (
|
|
396
|
-
const theme = this.context.themesHelper.findThemeByName(
|
|
354
|
+
if (actions[0].action.startsWith('add_theme')) {
|
|
355
|
+
const theme = this.context.themesHelper.findThemeByName(actions[0].data);
|
|
397
356
|
if (theme) {
|
|
398
357
|
clonedTheme = theme.clone();
|
|
399
358
|
}
|
|
400
359
|
}
|
|
401
|
-
else if (
|
|
402
|
-
const group = this.context.themesHelper.findGroupByName(
|
|
360
|
+
else if (actions[0].action.startsWith('add_group')) {
|
|
361
|
+
const group = this.context.themesHelper.findGroupByName(actions[0].data);
|
|
403
362
|
if (group) {
|
|
404
363
|
clonedTheme = this.context.themesHelper.getMinimalClonedThemeForLayer(group);
|
|
405
364
|
}
|
|
406
365
|
}
|
|
407
|
-
else if (
|
|
408
|
-
const layer = this.context.themesHelper.findLayerByName(
|
|
366
|
+
else if (actions[0].action.startsWith('add_layer')) {
|
|
367
|
+
const layer = this.context.themesHelper.findLayerByName(actions[0].data);
|
|
409
368
|
if (layer) {
|
|
410
369
|
clonedTheme = this.context.themesHelper.getMinimalClonedThemeForLayer(layer);
|
|
411
370
|
activate = true;
|
|
@@ -7,7 +7,7 @@ class MobileSearchComponent extends SearchComponent {
|
|
|
7
7
|
</style><style>
|
|
8
8
|
.hidden{display:none}#searchbox{background-color:var(--bkg-color);z-index:101;border:none;border-radius:4px;flex-direction:row;width:100%;display:flex;position:absolute;box-shadow:0 0 10px 1px #0003}#search{z-index:2;-webkit-appearance:none;width:100%;color:var(--text-color);background:0 0;border:0;outline:none;-webkit-flex:auto;-ms-flex:auto;flex:auto;margin:0 0 0 .5rem;padding-left:.8rem;font-size:1.8em;line-height:1.8em}#search::placeholder{color:inherit;opacity:.4}#search:focus::placeholder{opacity:0;color:#0000;transition:opacity .3s}.search-icon,.close-icon,.select-color-icon{width:17px;color:var(--text-color);opacity:.7;padding:0 1rem}.close-button,.select-color-button{cursor:pointer;background-color:#0000;border:none;padding:0}#results{z-index:100;background-color:var(--bkg-color);scrollbar-width:thin;padding-top:7vh;position:fixed;inset:0;overflow-x:hidden}.result,.title{width:34rem;padding:.3rem 1rem;line-height:1.3rem;display:inline-block}.title{color:var(--text-color);padding-top:1.5rem;font-size:1.3rem;font-weight:600;line-height:2.5rem}.result{cursor:pointer;text-align:left;width:100%;color:var(--text-color);background:0 0;border:none;border-top:1px solid #ccc}.title img{width:14px;margin-right:1rem}.title span{text-transform:uppercase}.result.selected{color:var(--text-color);background-color:#aaa!important}#no-result{background:var(--warning-color);opacity:.75;visibility:hidden;pointer-events:none;border-radius:6px;width:fit-content;margin:auto;padding:.5rem 0;font-size:1rem;position:absolute;top:3rem;left:0;right:0}#no-result>span{padding:1.3rem}@keyframes fadeOut{0%{opacity:1}80%{opacity:1}to{opacity:0}}.shown-then-fadeout{animation:2s ease-in-out forwards fadeOut;visibility:visible!important}
|
|
9
9
|
</style>
|
|
10
|
-
<link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><div id="searchbox"><input id="search" class="gg-input" length="20" maxlength="1000" autocomplete="off" autocorrect="off" i18n="Search" placeholder="Search..." oninput="${(e) => this.doSearchDebounced(e)}" onkeydown="${(e) => this.onKeyDown(e)}"> <img class="${this.allResults.length > 0 ? 'hidden' : 'search-icon'}" alt="search-icon" src="${this.searchIcon}"> <button class="${this.allResults.length > 0 ? 'close-button' : 'hidden'}" onclick="${() => this.clearSearch(true)}"><img class="close-icon" alt="close-icon" src="icons/close.svg"></button></div><div id="results" class="${Object.keys(this.groupedResults).length === 0 || this.forceHide ? 'hidden' : ''}">${Object.keys(this.groupedResults).map(group => uHtml `<div class="title"><img alt="result icon" src="${this.getIcon(group)}"> <span i18n="${group}"></span></div>${this.groupedResults[group].map(result => uHtml ` <button class="${result.selected ? 'result selected' : 'result'}" onmousedown="${() => this.onMouseDown()}" onclick="${() => this.onSelect(result)}">${result.
|
|
10
|
+
<link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><div id="searchbox"><input id="search" class="gg-input" length="20" maxlength="1000" autocomplete="off" autocorrect="off" i18n="Search" placeholder="Search..." oninput="${(e) => this.doSearchDebounced(e)}" onkeydown="${(e) => this.onKeyDown(e)}"> <img class="${this.allResults.length > 0 ? 'hidden' : 'search-icon'}" alt="search-icon" src="${this.searchIcon}"> <button class="${this.allResults.length > 0 ? 'close-button' : 'hidden'}" onclick="${() => this.clearSearch(true)}"><img class="close-icon" alt="close-icon" src="icons/close.svg"></button></div><div id="results" class="${Object.keys(this.groupedResults).length === 0 || this.forceHide ? 'hidden' : ''}">${Object.keys(this.groupedResults).map(group => uHtml `<div class="title"><img alt="result icon" src="${this.getIcon(group)}"> <span i18n="${group}"></span></div>${this.groupedResults[group].map(result => uHtml ` <button class="${result.get('selected') ? 'result selected' : 'result'}" onmousedown="${() => this.onMouseDown()}" onclick="${() => this.onSelect(result)}">${result.get('label')}</button> `)} `)}</div><div id="no-result" class="${this.showNoResultWarning ? 'shown-then-fadeout' : ''}"><span i18n="${'No match found'}"></span></div>`;
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
export default MobileSearchComponent;
|
package/models/main.d.ts
CHANGED
|
@@ -31,8 +31,7 @@ export { default as ThemeLayer } from './layers/themelayer';
|
|
|
31
31
|
export { default as ThemeLayerExternal } from './layers/themelayerexternal';
|
|
32
32
|
export type { TimeAwareLayer } from './layers/timeawarelayer';
|
|
33
33
|
export { isTimeAwareLayer } from './layers/timeawarelayer';
|
|
34
|
-
export type {
|
|
35
|
-
export { default as SearchResult } from './searchresult';
|
|
34
|
+
export type { SearchResultsActions } from './searchresult';
|
|
36
35
|
export type { SelectionTool, SelectionMode } from './selection';
|
|
37
36
|
export { default as SelectionParam } from './selectionparam';
|
|
38
37
|
export { default as ServerOgc } from './serverogc';
|
package/models/main.js
CHANGED
|
@@ -21,7 +21,6 @@ export { isSnappableLayer } from './layers/snappablelayer';
|
|
|
21
21
|
export { default as ThemeLayer } from './layers/themelayer';
|
|
22
22
|
export { default as ThemeLayerExternal } from './layers/themelayerexternal';
|
|
23
23
|
export { isTimeAwareLayer } from './layers/timeawarelayer';
|
|
24
|
-
export { default as SearchResult } from './searchresult';
|
|
25
24
|
export { default as SelectionParam } from './selectionparam';
|
|
26
25
|
export { default as ServerOgc } from './serverogc';
|
|
27
26
|
export { default as ServerOgcApi, OgcApiDefaultEncoding } from './serverogcapi';
|
package/models/searchresult.d.ts
CHANGED
|
@@ -1,27 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type: 'Point' | 'MultiPoint' | 'LineString' | 'MultiLineString' | 'Polygon' | 'MultiPolygon';
|
|
5
|
-
coordinates: Coordinate | Coordinate[] | Coordinate[][] | Coordinate[][][];
|
|
1
|
+
export type SearchResultsActions = {
|
|
2
|
+
action: string;
|
|
3
|
+
data: string;
|
|
6
4
|
};
|
|
7
|
-
export type GeometryCollectionResult = {
|
|
8
|
-
type: 'GeometryCollection';
|
|
9
|
-
geometries: GeometryCollectionResult[] | GeometryResult[];
|
|
10
|
-
};
|
|
11
|
-
export type AllSearchResults = {
|
|
12
|
-
type: string;
|
|
13
|
-
features: SearchResult[];
|
|
14
|
-
};
|
|
15
|
-
export default class SearchResult {
|
|
16
|
-
bbox?: Extent;
|
|
17
|
-
geometry?: GeometryResult | GeometryCollectionResult;
|
|
18
|
-
properties?: {
|
|
19
|
-
label: string;
|
|
20
|
-
layer_name: string;
|
|
21
|
-
actions: {
|
|
22
|
-
action: string;
|
|
23
|
-
data: string;
|
|
24
|
-
}[];
|
|
25
|
-
};
|
|
26
|
-
selected: boolean;
|
|
27
|
-
}
|
package/models/searchresult.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.0.
|
|
1
|
+
{"version":"1.0.2220854497", "build":"2220854497", "date":"17/12/2025"}
|
|
@@ -73,7 +73,8 @@ class GirafeConfig {
|
|
|
73
73
|
// We just display a warning in the console
|
|
74
74
|
console.warn(e);
|
|
75
75
|
this.search = {
|
|
76
|
-
url: ''
|
|
76
|
+
url: '',
|
|
77
|
+
resultsSrid: config.map.srid
|
|
77
78
|
};
|
|
78
79
|
}
|
|
79
80
|
try {
|
|
@@ -192,6 +193,7 @@ class GirafeConfig {
|
|
|
192
193
|
}
|
|
193
194
|
return {
|
|
194
195
|
url: config.search.url,
|
|
196
|
+
resultsSrid: config.search.resultsSrid ?? config.map.srid,
|
|
195
197
|
objectPreview: config.search.objectPreview ?? false,
|
|
196
198
|
layerPreview: config.search.layerPreview ?? false,
|
|
197
199
|
minResolution: config.search.minResolution ?? 0.5,
|