@geogirafe/lib-geoportal 1.1.0-dev.2631714424 → 1.1.0-dev.2636580374
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/menubutton/component.js +1 -1
- package/components/menubutton/style.css +0 -1
- package/package.json +1 -1
- package/templates/public/about.json +1 -1
- package/tools/geometrytools.d.ts +6 -0
- package/tools/geometrytools.js +14 -0
- package/tools/main.d.ts +1 -1
- package/tools/main.js +1 -1
- package/tools/search/abstractsearchclient.js +2 -9
- package/tools/search/searchmanager.d.ts +4 -1
- package/tools/search/searchmanager.js +31 -12
|
@@ -8,7 +8,7 @@ class MenuButtonComponent extends GirafeHTMLElement {
|
|
|
8
8
|
return uHtml `<style>
|
|
9
9
|
.hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}button,input,select,textarea{font:inherit}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height) / 1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad1);background-color:var(--bkg-color-grad2)}.gg-button:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed;border:none}.gg-button:disabled img{filter:opacity(.6)}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height) / 1.2);min-height:calc(var(--app-standard-height) / 1.2);max-height:calc(var(--app-standard-height) / 1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height) / 2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height) / 2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height) / 2);min-height:calc(var(--app-standard-height) / 2);max-height:calc(var(--app-standard-height) / 2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height) / 3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height) / 3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover:not(:disabled),.gg-select:hover:not(:disabled),.gg-input:hover:not(:disabled),.gg-textarea:hover:not(:disabled),.gg-icon-button:hover:not(:disabled){background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height) / 2);height:calc(var(--app-standard-height) / 2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}
|
|
10
10
|
</style><style>
|
|
11
|
-
.container{position:relative}.menu-content{border:var(--app-standard-border);background:var(--bkg-color);z-index:1000;box-shadow:var(--bx-shdw);border-width:2px;border-radius:4px;margin-right:.2rem;
|
|
11
|
+
.container{position:relative}.menu-content{border:var(--app-standard-border);background:var(--bkg-color);z-index:1000;box-shadow:var(--bx-shdw);border-width:2px;border-radius:4px;margin-right:.2rem;display:flex;position:absolute}.open-bottom{flex-direction:column;width:fit-content;height:max-content;top:100%;left:0}.open-bottom-left{flex-direction:row;width:fit-content;height:max-content;top:100%;right:0}.open-up{flex-direction:column;width:fit-content;height:max-content;bottom:100%;right:0}.open-up-right{flex-direction:column;width:fit-content;height:max-content;bottom:100%;left:0}.open-left{flex-direction:row;width:max-content;height:fit-content;top:0;right:100%}
|
|
12
12
|
</style>
|
|
13
13
|
<style>${this.customStyle}</style>
|
|
14
14
|
<div class="container"><slot name="menu-button" onclick="${() => this.toggleMenu()}" onkeydown="${(e) => this.simulateClick(e)}"></slot><div class="${this.getClass()}"><slot name="menu-content"></slot></div></div>
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.1.0-dev.
|
|
1
|
+
{"version":"1.1.0-dev.2636580374", "build":"2636580374", "date":"29/06/2026"}
|
package/tools/geometrytools.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Extent } from 'ol/extent.js';
|
|
2
|
+
import Feature from 'ol/Feature.js';
|
|
1
3
|
export declare function formatCoordinates(coords: number[], locale: string): string[];
|
|
2
4
|
/**
|
|
3
5
|
* Will check if given coords can be mapped to a max extent
|
|
@@ -9,3 +11,7 @@ export declare function formatCoordinates(coords: number[], locale: string): str
|
|
|
9
11
|
export declare function parseCoordinates(coords: number[], extent: number[] | undefined, srid: string): number[];
|
|
10
12
|
export declare function decimalToDMS(coordinate: number[]): string[];
|
|
11
13
|
export declare function printCoordinate(coordinate: [number, number], format: 'dms' | 'decimal', precision: number): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Returns a bbox around the geometry that is x percent larger than the geometry.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createBufferedExtentFromFeature(feature: Feature, percentageBuffer?: number): Extent | undefined;
|
package/tools/geometrytools.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { buffer, getHeight, getWidth } from 'ol/extent.js';
|
|
2
3
|
import { fromLonLat } from 'ol/proj.js';
|
|
3
4
|
export function formatCoordinates(coords, locale) {
|
|
4
5
|
const east = (Math.round(coords[0] * 100) / 100).toLocaleString(locale, { minimumFractionDigits: 2 });
|
|
@@ -69,3 +70,16 @@ export function printCoordinate(coordinate, format, precision) {
|
|
|
69
70
|
}
|
|
70
71
|
return coordString;
|
|
71
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns a bbox around the geometry that is x percent larger than the geometry.
|
|
75
|
+
*/
|
|
76
|
+
export function createBufferedExtentFromFeature(feature, percentageBuffer = 50) {
|
|
77
|
+
const geom = feature.getGeometry();
|
|
78
|
+
if (geom) {
|
|
79
|
+
const extent = geom.getExtent();
|
|
80
|
+
// We create a buffer around the extent from a specified percentage of the width/height
|
|
81
|
+
const bufferValue = Math.max((getWidth(extent) * percentageBuffer) / 100, (getHeight(extent) * percentageBuffer) / 100);
|
|
82
|
+
return buffer(extent, bufferValue);
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
package/tools/main.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export { default as FeedbackManager } from './feedback/feedbackmanager.js';
|
|
|
31
31
|
export { BaseFilterCondition } from './filter/basefilter.js';
|
|
32
32
|
export { KNOWN_FUNCTIONALITIES } from './functionalities.js';
|
|
33
33
|
export { default as GeoConsts } from './geoconsts.js';
|
|
34
|
-
export { formatCoordinates, parseCoordinates, decimalToDMS, printCoordinate } from './geometrytools.js';
|
|
34
|
+
export { formatCoordinates, parseCoordinates, decimalToDMS, printCoordinate, createBufferedExtentFromFeature } from './geometrytools.js';
|
|
35
35
|
export type { TranslationsDict } from './i18n/i18nmanager.js';
|
|
36
36
|
export { default as I18nManager } from './i18n/i18nmanager.js';
|
|
37
37
|
export { default as LayerManager } from './layers/layermanager.js';
|
package/tools/main.js
CHANGED
|
@@ -26,7 +26,7 @@ export { default as FeedbackManager } from './feedback/feedbackmanager.js';
|
|
|
26
26
|
export { BaseFilterCondition } from './filter/basefilter.js';
|
|
27
27
|
export { KNOWN_FUNCTIONALITIES } from './functionalities.js';
|
|
28
28
|
export { default as GeoConsts } from './geoconsts.js';
|
|
29
|
-
export { formatCoordinates, parseCoordinates, decimalToDMS, printCoordinate } from './geometrytools.js';
|
|
29
|
+
export { formatCoordinates, parseCoordinates, decimalToDMS, printCoordinate, createBufferedExtentFromFeature } from './geometrytools.js';
|
|
30
30
|
export { default as I18nManager } from './i18n/i18nmanager.js';
|
|
31
31
|
export { default as LayerManager } from './layers/layermanager.js';
|
|
32
32
|
export { default as SimpleMaskLayer } from './layers/simplemasklayer.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GeoJSON } from 'ol/format.js';
|
|
2
2
|
import GirafeSingleton from '../../base/GirafeSingleton.js';
|
|
3
|
-
import {
|
|
3
|
+
import { createBufferedExtentFromFeature } from '../geometrytools.js';
|
|
4
4
|
// The default provider is a container for search results that do not result from a provider search (e.g. map re-centering)
|
|
5
5
|
export const SEARCH_PROVIDER_DEFAULT = 'default';
|
|
6
6
|
// The default search group contains search results that do not belong to a specific category
|
|
@@ -72,14 +72,7 @@ class AbstractSearchClient extends GirafeSingleton {
|
|
|
72
72
|
* Returns a bbox around the geometry that is 50% larger than the geometry.
|
|
73
73
|
*/
|
|
74
74
|
getZoomToBbox(feature) {
|
|
75
|
-
|
|
76
|
-
if (geom) {
|
|
77
|
-
const extent = geom.getExtent();
|
|
78
|
-
// We create a buffer around the extent from 50% of the width/height
|
|
79
|
-
const bufferValue = Math.max((getWidth(extent) * 50) / 100, (getHeight(extent) * 50) / 100);
|
|
80
|
-
return buffer(extent, bufferValue);
|
|
81
|
-
}
|
|
82
|
-
return undefined;
|
|
75
|
+
return createBufferedExtentFromFeature(feature);
|
|
83
76
|
}
|
|
84
77
|
}
|
|
85
78
|
export default AbstractSearchClient;
|
|
@@ -10,6 +10,8 @@ export type SearchProviderConfig = {
|
|
|
10
10
|
declare class SearchManager extends GirafeSingleton {
|
|
11
11
|
private readonly clients;
|
|
12
12
|
private abortController;
|
|
13
|
+
private defaultSrid;
|
|
14
|
+
private defaultMaxExtent?;
|
|
13
15
|
readonly minSearchTermLength = 3;
|
|
14
16
|
constructor(context: IGirafeContext);
|
|
15
17
|
initializeSingleton(): void;
|
|
@@ -27,7 +29,8 @@ declare class SearchManager extends GirafeSingleton {
|
|
|
27
29
|
* using different separators such as `;`, `/`, `,`, or whitespace.
|
|
28
30
|
*/
|
|
29
31
|
detectCoordinatesInTerm(term: string): [number, number] | null;
|
|
30
|
-
private
|
|
32
|
+
private parseCoordinateFromString;
|
|
33
|
+
private isCoordinatePairValid;
|
|
31
34
|
getZoomToBbox(feature: Feature): Extent | undefined;
|
|
32
35
|
}
|
|
33
36
|
export default SearchManager;
|
|
@@ -4,11 +4,14 @@ import GeoAdminChSearchClient from './geoadminchsearchclient.js';
|
|
|
4
4
|
import GmfSearchClient from './gmfsearchclient.js';
|
|
5
5
|
import GirafeSingleton from '../../base/GirafeSingleton.js';
|
|
6
6
|
import Feature from 'ol/Feature.js';
|
|
7
|
-
import { parseCoordinates } from '../geometrytools.js';
|
|
7
|
+
import { createBufferedExtentFromFeature, parseCoordinates } from '../geometrytools.js';
|
|
8
|
+
import { transform, transformExtent } from 'ol/proj.js';
|
|
8
9
|
import { Point } from 'ol/geom.js';
|
|
9
10
|
class SearchManager extends GirafeSingleton {
|
|
10
11
|
clients = new Map();
|
|
11
12
|
abortController = new AbortController();
|
|
13
|
+
defaultSrid;
|
|
14
|
+
defaultMaxExtent;
|
|
12
15
|
minSearchTermLength = 3;
|
|
13
16
|
constructor(context) {
|
|
14
17
|
super(context);
|
|
@@ -18,6 +21,8 @@ class SearchManager extends GirafeSingleton {
|
|
|
18
21
|
for (const providerConfig of this.context.configManager.Config.search.providers ?? []) {
|
|
19
22
|
this.createClient(providerConfig);
|
|
20
23
|
}
|
|
24
|
+
this.defaultSrid = this.context.configManager.getDefaultConfigValue('map.srid');
|
|
25
|
+
this.defaultMaxExtent = this.context.configManager.Config.map.maxExtent?.split(',').map(Number);
|
|
21
26
|
}
|
|
22
27
|
createClient(providerConfig) {
|
|
23
28
|
switch (providerConfig.type) {
|
|
@@ -60,16 +65,25 @@ class SearchManager extends GirafeSingleton {
|
|
|
60
65
|
return searchResults;
|
|
61
66
|
}
|
|
62
67
|
createCoordinateSearchResult(coordinates) {
|
|
63
|
-
const [coord1, coord2] = coordinates;
|
|
64
68
|
const currentSrid = this.context.mapManager.getMap().getView().getProjection().getCode();
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
let parsedCoordinates;
|
|
70
|
+
// Checks if the coordinates are within the default SRID max extent or geographic
|
|
71
|
+
parsedCoordinates = parseCoordinates(coordinates, this.defaultMaxExtent, this.defaultSrid);
|
|
72
|
+
if (this.isCoordinatePairValid(parsedCoordinates) && this.defaultSrid !== currentSrid) {
|
|
73
|
+
parsedCoordinates = transform(parsedCoordinates, this.defaultSrid, currentSrid);
|
|
74
|
+
parsedCoordinates = parsedCoordinates.map((number) => Math.round(number * 100) / 100);
|
|
75
|
+
}
|
|
76
|
+
// Try to parse the coordinates in the current map projection
|
|
77
|
+
if (!this.isCoordinatePairValid(parsedCoordinates) && this.defaultMaxExtent) {
|
|
78
|
+
const currentMaxExtent = transformExtent(this.defaultMaxExtent, this.defaultSrid, currentSrid);
|
|
79
|
+
parsedCoordinates = parseCoordinates(coordinates, currentMaxExtent, currentSrid);
|
|
80
|
+
}
|
|
81
|
+
if (!this.isCoordinatePairValid(parsedCoordinates)) {
|
|
68
82
|
return null;
|
|
69
83
|
}
|
|
70
84
|
const resultFeature = new Feature({
|
|
71
|
-
geometry: new Point(
|
|
72
|
-
label: `${
|
|
85
|
+
geometry: new Point(parsedCoordinates),
|
|
86
|
+
label: `${parsedCoordinates[0]} ${parsedCoordinates[1]}`
|
|
73
87
|
});
|
|
74
88
|
// Return this result grouped by the default provider and as part of the `recenter_map` group
|
|
75
89
|
return { [SEARCH_PROVIDER_DEFAULT]: { [SEARCH_GROUP_RECENTER_MAP]: [resultFeature] } };
|
|
@@ -105,26 +119,31 @@ class SearchManager extends GirafeSingleton {
|
|
|
105
119
|
if (parts.length !== 2) {
|
|
106
120
|
return null;
|
|
107
121
|
}
|
|
108
|
-
const first = this.
|
|
109
|
-
const second = this.
|
|
122
|
+
const first = this.parseCoordinateFromString(parts[0]);
|
|
123
|
+
const second = this.parseCoordinateFromString(parts[1]);
|
|
110
124
|
return first === null || second === null ? null : [first, second];
|
|
111
125
|
}
|
|
112
|
-
|
|
126
|
+
parseCoordinateFromString(value) {
|
|
113
127
|
const normalized = value
|
|
114
128
|
// Remove coordinate prefix and thousand separator
|
|
115
129
|
.replace(/[NESW']/g, '')
|
|
116
|
-
//
|
|
130
|
+
// Replace decimal separator
|
|
117
131
|
.replace(',', '.')
|
|
118
132
|
.trim();
|
|
119
133
|
const number = Number(normalized);
|
|
120
134
|
return Number.isFinite(number) ? number : null;
|
|
121
135
|
}
|
|
136
|
+
isCoordinatePairValid(coordinates) {
|
|
137
|
+
return !!coordinates && coordinates.length === 2 && coordinates.every((coordinate) => Number.isFinite(coordinate));
|
|
138
|
+
}
|
|
122
139
|
getZoomToBbox(feature) {
|
|
123
140
|
const provider = feature.get('provider');
|
|
124
141
|
if (this.clients.has(provider)) {
|
|
125
142
|
return this.clients.get(provider)?.getZoomToBbox(feature);
|
|
126
143
|
}
|
|
127
|
-
|
|
144
|
+
else {
|
|
145
|
+
return createBufferedExtentFromFeature(feature);
|
|
146
|
+
}
|
|
128
147
|
}
|
|
129
148
|
}
|
|
130
149
|
export default SearchManager;
|