@geogirafe/lib-geoportal 1.3.0-dev.2938077459 → 1.3.0-dev.2966299016
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/selectionpanel-mobile/component.d.ts +1 -1
- package/components/selectionpanel-mobile/component.js +3 -2
- package/components/selectionwindow/component.d.ts +7 -0
- package/components/selectionwindow/component.js +9 -2
- package/package.json +1 -1
- package/templates/public/about.json +1 -1
- package/tools/app/geogirafeapp.d.ts +2 -0
- package/tools/app/geogirafeapp.js +44 -1
|
@@ -3,7 +3,7 @@ import GirafeHTMLElement from '../../base/GirafeHTMLElement.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Create a link to a page or an email if the pattern matches
|
|
5
5
|
*/
|
|
6
|
-
export declare function getLinkFriendlyString(
|
|
6
|
+
export declare function getLinkFriendlyString(value: unknown): string;
|
|
7
7
|
export default class SelectionPanelMobile extends GirafeHTMLElement {
|
|
8
8
|
protected templateUrl: string | null;
|
|
9
9
|
protected styleUrls: string[] | null;
|
|
@@ -6,12 +6,13 @@ import { isValidEmail } from '../../tools/utils/utils.js';
|
|
|
6
6
|
/**
|
|
7
7
|
* Create a link to a page or an email if the pattern matches
|
|
8
8
|
*/
|
|
9
|
-
export function getLinkFriendlyString(
|
|
9
|
+
export function getLinkFriendlyString(value) {
|
|
10
|
+
const inputStr = String(value);
|
|
10
11
|
// Create a link if starting with http
|
|
11
12
|
if (inputStr.startsWith('http')) {
|
|
12
13
|
return `<a href="${inputStr}" target="_blank" rel="noreferrer">${inputStr}</a>`;
|
|
13
14
|
}
|
|
14
|
-
// Create an
|
|
15
|
+
// Create an email link if has email form
|
|
15
16
|
if (isValidEmail(inputStr)) {
|
|
16
17
|
return `<a href="mailto:${inputStr}">${inputStr}</a>`;
|
|
17
18
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type OlFeature from 'ol/Feature.js';
|
|
2
2
|
import GirafeDraggableElement from '../../base/GirafeDraggableElement.js';
|
|
3
3
|
import type { GridDataById } from '../../tools/featuretogriddatabyid.js';
|
|
4
|
+
import type GirafeConfig from '../../tools/configuration/girafeconfig.js';
|
|
4
5
|
/**
|
|
5
6
|
* Represents a Feature displayed in the SelectionWindowComponent.
|
|
6
7
|
*/
|
|
@@ -135,5 +136,11 @@ declare class SelectionWindowComponent extends GirafeDraggableElement {
|
|
|
135
136
|
* @static
|
|
136
137
|
*/
|
|
137
138
|
static createWindowFeatures(gridDataById: GridDataById): WindowFeature[];
|
|
139
|
+
/**
|
|
140
|
+
* Converts a feature property value (string, number, boolean...) to a linkified and sanitized html string.
|
|
141
|
+
* @returns The html string to display.
|
|
142
|
+
* @static
|
|
143
|
+
*/
|
|
144
|
+
static formatDisplayedValue(value: unknown, config: GirafeConfig): string;
|
|
138
145
|
}
|
|
139
146
|
export default SelectionWindowComponent;
|
|
@@ -182,8 +182,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
182
182
|
});
|
|
183
183
|
this.displayedProperties.forEach((keyValue) => {
|
|
184
184
|
keyValue[0] = this.context.i18nManager.getTranslation(this.columnAliasHelper.getColumnAlias(windowFeature.id, keyValue[0]));
|
|
185
|
-
keyValue[1] =
|
|
186
|
-
keyValue[1] = sanitize(keyValue[1], this.context.configManager.Config);
|
|
185
|
+
keyValue[1] = SelectionWindowComponent.formatDisplayedValue(keyValue[1], this.context.configManager.Config);
|
|
187
186
|
});
|
|
188
187
|
// Render and translate data.
|
|
189
188
|
this.render();
|
|
@@ -312,5 +311,13 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
312
311
|
});
|
|
313
312
|
return windowFeatures;
|
|
314
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Converts a feature property value (string, number, boolean...) to a linkified and sanitized html string.
|
|
316
|
+
* @returns The html string to display.
|
|
317
|
+
* @static
|
|
318
|
+
*/
|
|
319
|
+
static formatDisplayedValue(value, config) {
|
|
320
|
+
return sanitize(linkify(String(value)), config);
|
|
321
|
+
}
|
|
315
322
|
}
|
|
316
323
|
export default SelectionWindowComponent;
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.3.0-dev.
|
|
1
|
+
{"version":"1.3.0-dev.2966299016", "build":"2966299016", "date":"20/10/2026"}
|
|
@@ -217,13 +217,19 @@ export default class GeoGirafeApp {
|
|
|
217
217
|
}
|
|
218
218
|
async waitForServiceWorkerControl() {
|
|
219
219
|
const sw = navigator.serviceWorker;
|
|
220
|
-
const registration = await
|
|
220
|
+
const registration = await this.registerServiceWorker();
|
|
221
221
|
// If a service worker already controls the current page, everything is ready.
|
|
222
222
|
// `registration.active` only tells us that a service worker is active for the registration;
|
|
223
223
|
// `sw.controller` tells us that it actually controls this page.
|
|
224
224
|
if (sw.controller) {
|
|
225
225
|
return sw.controller;
|
|
226
226
|
}
|
|
227
|
+
// If the page is still outside of the service worker scope (see registerServiceWorker),
|
|
228
|
+
// the `controllerchange` event will never be fired, so we only wait for the service worker to be activated.
|
|
229
|
+
if (!globalThis.location.href.startsWith(registration.scope)) {
|
|
230
|
+
console.warn(`The current page is outside of the service worker scope (${registration.scope}), it won't be controlled by the service worker.`);
|
|
231
|
+
return this.waitForServiceWorkerActivation(registration);
|
|
232
|
+
}
|
|
227
233
|
// The page is not currently controlled by a service worker.
|
|
228
234
|
// This can happen, for example, after a force refresh (Ctrl+F5), even though
|
|
229
235
|
// an active service worker already exists. In that case, the service worker's
|
|
@@ -247,4 +253,41 @@ export default class GeoGirafeApp {
|
|
|
247
253
|
}, { once: true });
|
|
248
254
|
});
|
|
249
255
|
}
|
|
256
|
+
async registerServiceWorker() {
|
|
257
|
+
// The default scope of the service worker is the folder of service-worker.js (resolved against <base href>).
|
|
258
|
+
// When the application page is served from another path than its static files
|
|
259
|
+
// (e.g. page at /iframe and files at /static/), the page is outside of this scope and can't be controlled.
|
|
260
|
+
// In that case, try to register the service worker at path of the page as scope.
|
|
261
|
+
// This is only allowed by the browser if the server sends the "Service-Worker-Allowed" header.
|
|
262
|
+
const scriptUrl = new URL('service-worker.js', document.baseURI);
|
|
263
|
+
const defaultScope = new URL('./', scriptUrl).href;
|
|
264
|
+
if (!globalThis.location.href.startsWith(defaultScope)) {
|
|
265
|
+
const pageScope = new URL('./', globalThis.location.href).href;
|
|
266
|
+
try {
|
|
267
|
+
return await navigator.serviceWorker.register(scriptUrl, { type: 'module', scope: pageScope });
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
console.warn(`Service worker could not be registered with the scope ${pageScope}. ` +
|
|
271
|
+
`Check that the server sends the header "Service-Worker-Allowed" with the service worker script.`, err);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return navigator.serviceWorker.register(scriptUrl, { type: 'module' });
|
|
275
|
+
}
|
|
276
|
+
async waitForServiceWorkerActivation(registration) {
|
|
277
|
+
if (registration.active) {
|
|
278
|
+
return registration.active;
|
|
279
|
+
}
|
|
280
|
+
const sw = registration.installing ?? registration.waiting;
|
|
281
|
+
if (!sw) {
|
|
282
|
+
throw new Error('No service worker is installing or waiting.');
|
|
283
|
+
}
|
|
284
|
+
return new Promise((resolve) => {
|
|
285
|
+
sw.addEventListener('statechange', function onStateChange() {
|
|
286
|
+
if (sw.state === 'activated') {
|
|
287
|
+
sw.removeEventListener('statechange', onStateChange);
|
|
288
|
+
resolve(sw);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
}
|
|
250
293
|
}
|