diff --git a/build/buildConfig.js b/build/buildConfig.js index 4e4b98f01bd..6732a25f8ed 100644 --- a/build/buildConfig.js +++ b/build/buildConfig.js @@ -243,8 +243,21 @@ module.exports = (...args) => mapArgumentsToObject(args, ({ 'less-loader' ] }, + { + // theme text fonts stay separate files, so the browser downloads only the subsets + // matched by the unicode-range of each @font-face, after the stylesheet + test: /themes[\\\/]default[\\\/]fonts[\\\/].+\.woff2$/, + type: 'asset/resource', + generator: { + filename: '[name].[contenthash:8][ext]', + outputPath: 'themes/fonts/', + // relative to the theme stylesheets, emitted in themes/ + publicPath: 'fonts/' + } + }, { test: /\.woff(2)?(\?v=[0-9].[0-9].[0-9])?$/, + exclude: /themes[\\\/]default[\\\/]fonts[\\\/]/, use: [{ loader: 'url-loader', options: { diff --git a/docs/developer-guide/mapstore-migration-guide.md b/docs/developer-guide/mapstore-migration-guide.md index 8926906f05a..b274b991bb0 100644 --- a/docs/developer-guide/mapstore-migration-guide.md +++ b/docs/developer-guide/mapstore-migration-guide.md @@ -22,6 +22,55 @@ This is a list of things to check if you want to update from a previous version ## Migration from 2026.02.02 to 2026.03.00 +### Privacy settings and standard sharing + +Vanilla enables the common privacy panel of the `Cookie` plugin. + +Until the installation configures its own policy pages, the panel links the template pages shipped with MapStore in `product/assets/privacy`, shows a warning visible to every user, and writes a warning in the browser console. The template pages are not the policy of the installation. To remove the warning, do one of the following: + +- Disable the privacy panel with `"privacy": {"enabled": false}`, for example outside the European Union or when a custom plugin manages consent. MapStore then shows no cookie or privacy notice. +- Install a privacy settings extension. +- Configure `privacy.links`, also to copies of the template pages edited for the installation. + +To complete the migration: + +- Provide the policy pages of the installation: a Cookie Policy, a Privacy Policy when personal data are processed, and optionally Terms of Use. See [Which pages to provide](privacy-settings.md#which-pages-to-provide). +- Link them: in a project, in `privacy.links` of `localConfig.json`, from the project assets or as external urls; in a product installation, upload a privacy settings extension, created from the [mapstore-privacy-settings-extension](https://github.com/geosolutions-it/mapstore-privacy-settings-extension) template, which sets the links by itself. See [Policy pages](privacy-settings.md#policy-pages). +- Configure optional categories only for the optional tools actually used, and register their integrations before enabling them. + +**MapStore projects**: the template pages are part of the MapStore submodule, so the project WAR must copy them, otherwise the default links return 404 until `privacy.links` is configured. Add this execution to the `maven-resources-plugin` of `web/pom.xml`, after the `config files` one: + +```xml + + privacy template pages + process-classes + + copy-resources + + + ${basedir}/target/mapstore/product/assets + UTF-8 + + + ${basedir}/../MapStore2/web/client/product/assets + + privacy/* + img/logo.png + + + + + +``` + +Other changes: + +- The Social tab of the `Share` plugin is deprecated and disabled by default, and it no longer shows share counters. It will be removed in the 2027.01 series. To show it again, set `"socialPanel": true` in the `cfg` of the `Share` plugin, and update the Cookie Policy of the installation accordingly. Link and embed sharing retain their existing resource permissions. +- The old cookie notice (Accept, More details and Leave) is removed, with its `externalCookieUrl` and `declineUrl` options and the `translations/fragments/cookie` pages. Remove these options from custom configurations. A `localConfig.json` without the `privacy` section shows no notice: copy the `privacy` section of the standard `localConfig.json` to show the privacy panel. +- The default theme includes the Noto Sans font, so the pages no longer download it from Google Fonts. Projects should remove the Google Fonts links from their HTML templates and replace the Bowser script with the inline Internet Explorer check of the standard templates. Custom themes that do not import the default theme must import `themes/default/fonts.less` to keep the same font. + +See [Privacy and Consent Configuration](privacy-settings.md#privacy-and-consent-configuration) for browser storage, configuration and adapter requirements. + ### Default users removed: initial administrator password MapStore does not create the sample users `admin`/`admin` and `user`/`user` anymore (the `sample_users.xml` file is no longer shipped with the bundled GeoStore). On the first start with an empty database the `admin` user is created with the password taken from the `INITIAL_ADMIN_PASSWORD` environment variable; if the variable is not set, no administrator is created and start-up continues with a warning in the log. On a database that still contains an `admin` using the former default password, setting `INITIAL_ADMIN_PASSWORD` resets it to that value. See [Initial Administrator Password](initial-admin-password.md) for the details. diff --git a/docs/developer-guide/privacy-settings.md b/docs/developer-guide/privacy-settings.md new file mode 100644 index 00000000000..864737ef020 --- /dev/null +++ b/docs/developer-guide/privacy-settings.md @@ -0,0 +1,242 @@ +# Privacy and Consent Configuration + +The `Cookie` plugin supports shared privacy settings and an optional-integration lifecycle. Vanilla enables the privacy panel on the home page, Maps, Dashboards, GeoStories and embedded resources. Custom applications must include the plugin in each relevant plugin registry and route configuration. + +## Default configuration + +The top-level `privacy` object in `configs/localConfig.json` controls the panel: + +```json +{ + "privacy": { + "enabled": true, + "policyVersion": "vanilla-2026.03-consent-1", + "retentionDays": 180, + "categories": [] + } +} +``` + +The default configuration does not configure `privacy.links`, so the panel links the template pages shipped with MapStore. Each template page says that it is not the policy of the installation. The panel shows a warning to every user, with a link to this documentation, and the plugin writes a warning in the browser console. The warning disappears when the installation configures its own pages or disables the panel with `"enabled": false`. Replace them with the pages of the installation, as described in [Policy pages](#policy-pages). + +An empty category list means that no optional tools are configured. The first-visit panel is informational, with a Close action. Its dismissal is distinct from consent. Do not add optional categories merely because the application requests a remote map service. + +The plugin contributes an entry to `Footer` and `MapFooter`. Where neither footer exists, it provides a bottom bar. Embedded maps position `MapFooter` in the `footer` container so that its controls remain accessible above the map canvas. + +## Configure optional categories + +Supported optional IDs are `functional`, `statistics` and `marketing`. Configure only categories that are actually used, with descriptions of their purposes: + +```json +{ + "categories": [ + { + "id": "functional", + "description": { + "en-US": "Describe the optional feature and the data it uses.", + "it-IT": "Descrivere la funzione opzionale e i dati utilizzati." + } + } + ] +} +``` + +This object belongs to `privacy`. Categories are off before a valid choice. Adding a category does not automatically control a plugin, script, iframe or service: its implementation must use the consent lifecycle, with `registerConsentIntegration` in MapStore code or with the `SET_PRIVACY_CHOICE` action in an extension (see [Optional integrations in an extension](#optional-integrations-in-an-extension)). + +## Register an optional integration + +Use `registerConsentIntegration` from `web/client/utils/ConsentManager.js`. Register an inert factory, with no optional requests or storage writes at module load time. The factory runs only when its category is allowed. + +```javascript +import { registerConsentIntegration } from '../utils/ConsentManager'; + +const unregister = registerConsentIntegration( + 'optional-feature', + 'functional', + ({signal, isAllowed}) => { + const feature = createOptionalFeature({signal, isAllowed}); + return () => feature.destroy(); + } +); + +// Call when the integration is removed or its owning component unmounts. +unregister(); +``` + +`createOptionalFeature` represents the application's own adapter. It must honour the `AbortSignal`, check `isAllowed()` before further work, and return a synchronous teardown. Teardown must stop timers and listeners, detach optional content and remove any storage the integration owns where technically possible. Integrations need unique IDs. Policy changes, refusal, expiry and withdrawal disable unsupported or unconsented categories. + +Withdrawal cannot undo transmitted requests, remote logs or browser caches, and cannot remove cookies owned by another domain. An integration that cannot stop cleanly needs an explicit implementation and documented limits before it is enabled. + +## Browser storage + +Storage keys use MapStore's application namespace: + +| Key | Meaning and lifecycle | +| --- | --- | +| `mapstore.privacy.choices` | Schema 2: policy version, decision time, expiry and boolean category choices. Written after an optional choice, including refusal. | +| `mapstore.privacy.notice` | Schema 1: policy version, dismissal time and expiry for necessary-only information. It grants no optional consent. | + +The baseline validity is 180 days. Invalid, expired or superseded privacy records are removed on their next read when storage permits. Optional records are removed when no optional categories are configured. Valid applicable choices and necessary-only dismissals are retained. Cleanup compares the stored value before removal to avoid deleting a newer decision from another tab. + +Storage read or write failures do not enable optional tools. When a choice cannot be saved, the panel stays open with the error and optional tools stay off on the page, even if an older consent can still be read; MapStore also tries to remove that older record. A storage-removal failure also leaves an invalid record inactive. + +Update `policyVersion` when the purposes, integrations or material notice conditions change. Review the configured retention and the choice mechanism for the actual deployment. Setting `privacy.enabled` to `false` hides the panel and its footer entry: MapStore shows no cookie or privacy notice. Without the `privacy` section the panel is hidden too, unless an installed extension enables it. + +## Policy pages + +The panel links up to three pages: Cookie Policy, Privacy Policy and Terms of Use. Each installation must provide its own pages, because their content depends on who operates it and on the services it uses. + +The panel takes the links from the first of these sources that configures at least one page: + +1. `privacy.links` in `localConfig.json`, see [Configure the links](#configure-the-links). +2. An installed privacy settings extension, see [Privacy settings extension](#privacy-settings-extension). +3. The template pages shipped with MapStore, in `product/assets/privacy`. They are in English and describe the cookies and browser storage of MapStore with the default configuration. A notice at the top of each page says that it is a template and links this section. Use them as a starting point, never as the published policy. + +### Which pages to provide + +| Key | Page | When it is needed | +| --- | --- | --- | +| `cookie` | Cookie Policy: cookies and browser storage used by the installation, their purpose and duration | Every installation, because MapStore always uses technical browser storage (authentication, privacy choices, user settings). | +| `privacy` | Privacy Policy: personal data processed by the operator, purposes, legal bases, recipients, retention and rights | When the installation processes personal data, for example user accounts, saved content or server logs. Usually it is needed. | +| `terms` | Terms of Use: conditions of the service | Optional. Leave it out when the installation has no specific conditions. | + +Every link is optional: the panel shows only the links that are configured, and a missing key does not break the panel. A page can also be a single document that covers more topics, for example one page for both the Cookie Policy and the Privacy Policy: link the same url, or link it only once. The content of the pages is the responsibility of the operator of the installation; **the templates are a starting point, not legal advice**. + +### Configure the links + +Each link is a url, relative to the MapStore application or absolute. It can be a single url, used for every language, or an object of urls by locale for pages translated in more languages. The keys of the object are the locale codes of MapStore, for example `en-US` and `it-IT`. When the current locale has no url, the panel uses the first one configured, so a page in one language is enough. + +```json +{ + "privacy": { + "links": { + "cookie": { + "en-US": "extensions/PrivacySettings/assets/en-US/cookie.html", + "it-IT": "extensions/PrivacySettings/assets/it-IT/cookie.html" + }, + "privacy": "https://www.example.com/privacy-policy", + "terms": "extensions/PrivacySettings/assets/en-US/terms.html" + } + } +} +``` + +### Where to keep the pages + +- **External pages**: when the operator already publishes its policies, for example on its corporate website, link their absolute urls. No file is added to MapStore. +- **MapStore project**: version the pages in the project assets, for example `assets/privacy/cookie.html`, and link them in the project `localConfig.json`. +- **MapStore product installation**: publish the pages with the privacy settings extension and upload it from the context creator. No configuration file needs to change, and the pages are kept when MapStore is upgraded, because extensions are stored in the [data directory](externalized-configuration.md). + +### Privacy settings extension + +The [mapstore-privacy-settings-extension](https://github.com/geosolutions-it/mapstore-privacy-settings-extension) repository is an extension template for privacy settings. Create a repository from it for each operator: it contains the pages to complete a `privacy.config.json` with the privacy configuration and a build that checks them and creates the zip to upload. Its pages can also be copied into the assets of a project. + +The pages of the template are in English, in `assets/en-US`, with the MapStore logo in `assets/logo.png`: + +- `cookie.html`: prefilled cookie and browser-storage inventory for the inspected Vanilla baseline, including conditional features and external demo services. +- `privacy.html`: personal-data processing information, with operator-specific fields for purposes, legal bases, recipients, transfers, retention and rights. +- `terms.html`: installation-specific service conditions, separate from privacy information and optional consent. + +To publish the pages in more languages, list the locales in `locales` of `privacy.config.json` and add one folder for each locale in `assets`, with the same pages, for example `assets/it-IT/cookie.html`. The build checks that every locale has all the pages. The extension links the page of the current language of MapStore, and the page of the first locale of the list when that language has no pages. + +```json +{ + "locales": ["en-US", "it-IT"], + "pages": ["cookie", "privacy", "terms"] +} +``` + +Complete the highlighted fields and verify all providers, plugins, authentication, server logs and infrastructure before publication: the build refuses pages that still contain them. The software vendor is not automatically the data controller. Browser-storage durations do not establish server or provider retention policies. + +GeoSolutions OSM Bright is distinct from `tile.openstreetmap.org`. The observed GeoServer `GS_FLOW_CONTROL` cookie supports technical request/load control; it is not described as statistics. Browser blocking does not mean that a service did not emit a cookie. Review actual headers and purposes for the deployed services. + +### Configuration from an extension + +MapStore loads every installed extension when the application starts, before the first render. An extension can set the privacy configuration by dispatching at that moment: + +```javascript +setControlProperty('privacy', 'defaults', { + enabled: true, + policyVersion: 'operator-1', + retentionDays: 180, + categories: [], + links: { + cookie: {'en-US': 'extensions/PrivacySettings/assets/en-US/cookie.html'}, + privacy: {'en-US': 'extensions/PrivacySettings/assets/en-US/privacy.html'}, + terms: {'en-US': 'extensions/PrivacySettings/assets/en-US/terms.html'} + } +}); +``` + +The `Cookie` plugin uses this configuration only when `localConfig.json` does not configure `privacy.links`: when it does, the operator manages the privacy configuration in `localConfig.json` and the extension is ignored. Otherwise: + +| Key | Effect | +| --- | --- | +| `links`, `policyVersion`, `retentionDays`, `categories` | Replace the values of `localConfig.json`. | +| `enabled` | Used only when `localConfig.json` has no `privacy` section. | + +Change `policyVersion` every time the content of the pages changes, so that users are asked for their choices again. Removing the extension restores the configuration of `localConfig.json`. + +To link other pages without changing the extension, add `privacy.links` to the `localConfig.json.patch` of the data directory: + +```json +[{ + "op": "add", + "path": "/privacy/links", + "value": { + "cookie": "extensions/PrivacySettings/assets/en-US/cookie.html", + "privacy": "https://www.example.com/privacy-policy" + } +}] +``` + +### Optional integrations in an extension + +`registerConsentIntegration` is not available to extensions, which do not share the modules of MapStore. An extension follows the consent of the user through the `SET_PRIVACY_CHOICE` action instead: MapStore dispatches it every time the choice changes (start, save, withdrawal, another tab, expiry, new policy version), with the validated choice or `null`, and keeps the last one in `state.cookie.privacyChoice`. + +```javascript +// epic of an extension: starts the integration with the consent to "statistics", stops it otherwise +action$.ofType('SET_PRIVACY_CHOICE') + .map(({choice}) => choice?.categories?.statistics === true) + .distinctUntilChanged() + .do(allowed => allowed ? start() : stop()) + .filter(() => false); +``` + +The template of the privacy settings extension implements this in its `src/integrations.js`. + +### Texts of the panel + +The texts of the panel are the `privacySettings` messages of the MapStore translation files. They can be replaced from the extension or from the configuration, with `data..json` files that contain only the messages to change, for example: + +```json +{ + "locale": "en-US", + "messages": { + "privacySettings": { + "required": "Authentication, security and your privacy settings. See the Cookie Policy for details." + } + } +} +``` + +- **Extension**: put the files in the `translations` folder of the extension. The messages of extensions are applied after the ones of MapStore. +- **Configuration**: put the files in a folder of the [data directory](externalized-configuration.md), for example `extensions/customizations/translations`, and add the folder to `translationsPath` with the `localConfig.json.patch` of the data directory. The folders are read in order, so the messages of the last one replace the previous ones. + +```json +[{ + "op": "add", + "path": "/translationsPath", + "value": ["translations", "extensions/customizations/translations"] +}] +``` + +In a MapStore project, add the folder of the project to `translationsPath` in the same way, as described in [Customize configuration, assets and translations](advanced-project-customization.md#customize-configuration-assets-and-translations). + +In both cases, languages without a file keep the MapStore texts. + +## Verification + +Run `npm test`, `npm run i18n`, `npm run jsdoc:build` and `npm run fe:build` using the repository's supported environment. Tests cover consent activation and teardown, migration, expiry, storage failures, sharing and embedded plugin registration. + +For browser validation, exercise first entry and footer access on every configured route, necessary-only dismissal, optional refusal and granular choices, withdrawal across two tabs, reload, login/logout, saved-map sharing and embeds. Test any real optional adapter with network and storage inspection; use synthetic services during development. Do not ship a test fixture as an active optional service in the default configuration. diff --git a/docs/user-guide/footer.md b/docs/user-guide/footer.md index aea84692c49..445cdf4bb03 100644 --- a/docs/user-guide/footer.md +++ b/docs/user-guide/footer.md @@ -52,3 +52,7 @@ In this panel, the user can: !!! Note [MapStore](https://mapstore.geosolutionsgroup.com/mapstore/#/) can be configured to connect to a GeoServer endpoint exposing thousands of standard CRS definitions. This enables users to search for the desired CRS and its definition dynamically by fetching ti from GeoServer instead of manually defining it and so without redeploying the application or editing configuration files. This capability is disabled by default and requires additional configuration of the CRS plugin. For details on how to enable it, refer to the online [plugin documentation](https://mapstore.geosolutionsgroup.com/mapstore/docs/api/plugins#plugins.CRSSelector). + +## Privacy Settings + +Use **Privacy settings** in the footer to reopen privacy information and, where configured, change optional consent choices. See [Privacy Settings](privacy-settings.md#privacy-settings) for the available actions. diff --git a/docs/user-guide/privacy-settings.md b/docs/user-guide/privacy-settings.md new file mode 100644 index 00000000000..4c5fd1f0f79 --- /dev/null +++ b/docs/user-guide/privacy-settings.md @@ -0,0 +1,25 @@ +# Privacy Settings + +**Privacy settings** are available from the footer on the MapStore home page, Maps, Dashboards, GeoStories and embedded resources. On routes without a native footer, MapStore provides a bottom bar with the same entry point. + +## First visit + +The common panel opens on the first visit, including when a resource is opened directly. It links to the installation's Cookie Policy, Privacy Policy and Terms of Use. Until the installation configures its own pages, the links open the MapStore template pages, and the panel shows a warning that they are templates. + +The standard Vanilla configuration uses necessary tools only. The panel provides information and a **Close** action. Closing this information does not express consent or accept the Terms of Use. MapStore remembers the dismissal separately from optional consent choices. + +Categories that the installation does not use display **Not used** and have no switches. The necessary category remains active for the requested service. + +## Optional tools + +If the operator configures optional integrations, the panel provides **Reject optional**, **Accept optional** and **Customize** actions. Optional categories are off before a choice. + +Use **Customize** to select categories, then **Save choices**. Closing an initial optional-choice panel keeps optional tools off and records that refusal. You can continue using MapStore after refusing optional tools. + +## Change or withdraw a choice + +Reopen **Privacy settings** from the footer to change a selection or withdraw all optional consent. Changes are shared with other tabs on the same application origin. Expired choices and choices for an older policy version do not enable optional tools. + +Withdrawal stops registered integrations and cancels supported active requests. It cannot retract data already transmitted or delete cookies belonging to another domain. Contact the installation operator for requests concerning account or server-side data. + +The policy templates are a starting point for the installation operator. Their content and the available categories depend on the actual services configured for the installation. diff --git a/docs/user-guide/share.md b/docs/user-guide/share.md index 8c8d2d77329..420666c48da 100644 --- a/docs/user-guide/share.md +++ b/docs/user-guide/share.md @@ -14,7 +14,7 @@ From the *Share panel* the user is allowed to share a resource in different ways * With a **Direct Link** -* Through a **Social Network** +* Through a **Social Network** (deprecated, disabled by default) * Through a **Permalink** to shares current user session (only available from the [Side Toolbar](mapstore-toolbars.md#side-toolbar)) @@ -34,6 +34,9 @@ The **Social** section allows the user to share the resource on the most common +!!! Warning + The **Social** section is deprecated and will be removed in the 2027.01 series. It is disabled by default because sharing on a social network sends the resource link to that service, which can set its own cookies. An administrator who enables it with the `socialPanel` option of the `Share` plugin must update the Cookie Policy of the installation accordingly. + ## Permalink The **Permalink** section allows to save the current overall viewer state of the resource and share it as a permalink. diff --git a/mkdocs.yml b/mkdocs.yml index 4522f9119ed..6e42527e309 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -71,6 +71,7 @@ nav: - Overview: 'user-guide/managing-users-and-groups.md' - Managing Users: 'user-guide/managing-users.md' - Managing Groups: 'user-guide/managing-groups.md' + - Privacy Settings: 'user-guide/privacy-settings.md' - Managing Tags: 'user-guide/tags.md' - Managing IP Ranges: 'user-guide/ip-ranges.md' - Managing Access Rules: 'user-guide/rule-manager.md' @@ -164,6 +165,7 @@ nav: - Configuration: - Configuration Files: 'developer-guide/configuration-files.md' - Application Configuration: 'developer-guide/local-config.md' + - Privacy and Consent: 'developer-guide/privacy-settings.md' - Configuring plugins: 'developer-guide/plugins-documentation.md' - Configuration Expressions: 'developer-guide/expressions.md' - Map Configuration: 'developer-guide/maps-configuration.md' diff --git a/product/pom.xml b/product/pom.xml index 9d17544a56a..555d1c71da3 100644 --- a/product/pom.xml +++ b/product/pom.xml @@ -166,6 +166,7 @@ **/*.json **/img/* product/assets/symbols/* + product/assets/privacy/* **/*.less diff --git a/project/standard/templates/api.html b/project/standard/templates/api.html index 3778c0edcc8..f6dd67b9c90 100644 --- a/project/standard/templates/api.html +++ b/project/standard/templates/api.html @@ -5,8 +5,6 @@ __PROJECTDESCRIPTION__ - - - - - diff --git a/project/standard/templates/dashboard-embedded.html b/project/standard/templates/dashboard-embedded.html index dec64c1ba4e..91ea787a227 100644 --- a/project/standard/templates/dashboard-embedded.html +++ b/project/standard/templates/dashboard-embedded.html @@ -93,8 +93,6 @@ height: 100%; } - - diff --git a/project/standard/templates/embedded.html b/project/standard/templates/embedded.html index 473ebd665fc..f3156ca39c7 100644 --- a/project/standard/templates/embedded.html +++ b/project/standard/templates/embedded.html @@ -82,8 +82,6 @@ 100%{opacity: 0} } - - diff --git a/project/standard/templates/embeddedTemplate.html b/project/standard/templates/embeddedTemplate.html index a9bd9c02c5e..57e80497024 100644 --- a/project/standard/templates/embeddedTemplate.html +++ b/project/standard/templates/embeddedTemplate.html @@ -82,26 +82,12 @@ 100%{opacity: 0} } - - - diff --git a/project/standard/templates/geostory-embedded-template.html b/project/standard/templates/geostory-embedded-template.html index 27da0cd9cfb..d8a5704980e 100644 --- a/project/standard/templates/geostory-embedded-template.html +++ b/project/standard/templates/geostory-embedded-template.html @@ -92,25 +92,11 @@ height: 100%; } - - - diff --git a/project/standard/templates/geostory-embedded.html b/project/standard/templates/geostory-embedded.html index 8183a08c315..a44c3abe61d 100644 --- a/project/standard/templates/geostory-embedded.html +++ b/project/standard/templates/geostory-embedded.html @@ -92,8 +92,6 @@ height: 100%; } - - diff --git a/project/standard/templates/index.html b/project/standard/templates/index.html index c11b8990cb6..19745606151 100644 --- a/project/standard/templates/index.html +++ b/project/standard/templates/index.html @@ -82,8 +82,6 @@ 100%{opacity: 0} } - - diff --git a/project/standard/templates/indexTemplate.html b/project/standard/templates/indexTemplate.html index ac778108e52..d288aa729db 100644 --- a/project/standard/templates/indexTemplate.html +++ b/project/standard/templates/indexTemplate.html @@ -82,27 +82,13 @@ 100%{opacity: 0} } - - - +
diff --git a/project/standard/templates/unsupportedBrowser.html b/project/standard/templates/unsupportedBrowser.html index 297e6e5c3eb..b924baa2858 100644 --- a/project/standard/templates/unsupportedBrowser.html +++ b/project/standard/templates/unsupportedBrowser.html @@ -10,7 +10,7 @@ margin: 0; } #container { - font-family: 'Noto Sans', sans-serif; + font-family: 'Noto Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; display: flex; flex-direction: column; align-items: center; @@ -20,8 +20,6 @@ justify-content: center; } - -
diff --git a/project/standard/templates/web/pom.xml b/project/standard/templates/web/pom.xml index b43317774f9..cf56654e782 100644 --- a/project/standard/templates/web/pom.xml +++ b/project/standard/templates/web/pom.xml @@ -344,6 +344,26 @@ + + privacy template pages + process-classes + + copy-resources + + + ${basedir}/target/mapstore/product/assets + UTF-8 + + + ${basedir}/../MapStore2/web/client/product/assets + + privacy/* + img/logo.png + + + + + diff --git a/web/client/actions/__tests__/cookie-test.js b/web/client/actions/__tests__/cookie-test.js index 5a9a3f85f28..1fccf73dd4c 100644 --- a/web/client/actions/__tests__/cookie-test.js +++ b/web/client/actions/__tests__/cookie-test.js @@ -10,9 +10,7 @@ import expect from 'expect'; import { SET_COOKIE_VISIBILITY, - setCookieVisibility, - SET_MORE_DETAILS_VISIBILITY, - setMoreDetailsVisibility + setCookieVisibility } from '../cookie'; @@ -26,13 +24,5 @@ describe('Test correctness of the cookies actions', () => { expect(retval.status).toBeTruthy(); }); - it('setMoreDetailsVisibility', () => { - let status = true; - var retval = setMoreDetailsVisibility(status); - expect(retval).toExist(); - expect(retval.type).toBe(SET_MORE_DETAILS_VISIBILITY); - expect(retval.status).toBeTruthy(); - }); - }); diff --git a/web/client/actions/cookie.js b/web/client/actions/cookie.js index 29da60068fe..09b57669191 100644 --- a/web/client/actions/cookie.js +++ b/web/client/actions/cookie.js @@ -7,8 +7,6 @@ */ export const SET_COOKIE_VISIBILITY = 'SET_COOKIE_VISIBILITY'; -export const SET_MORE_DETAILS_VISIBILITY = 'SET_MORE_DETAILS_VISIBILITY'; -export const SET_DETAILS_COOKIE_HTML = 'SET_DETAILS_COOKIE_HTML'; export function setCookieVisibility(status) { return { @@ -16,16 +14,6 @@ export function setCookieVisibility(status) { status }; } -export function setMoreDetailsVisibility(status) { - return { - type: SET_MORE_DETAILS_VISIBILITY, - status - }; -} -export function setDetailsCookieHtml(html, lang) { - return { - type: SET_DETAILS_COOKIE_HTML, - html, - lang - }; -} + +export const SET_PRIVACY_CHOICE = 'SET_PRIVACY_CHOICE'; +export const setPrivacyChoice = choice => ({type: SET_PRIVACY_CHOICE, choice}); diff --git a/web/client/api.html b/web/client/api.html index 0ea4e0b000f..5586c49d8c7 100644 --- a/web/client/api.html +++ b/web/client/api.html @@ -5,8 +5,6 @@ Page with MapStore API - - - - - + diff --git a/web/client/dashboard-embedded.html b/web/client/dashboard-embedded.html index 003e7592517..ba4989be67d 100644 --- a/web/client/dashboard-embedded.html +++ b/web/client/dashboard-embedded.html @@ -93,8 +93,6 @@ height: 100%; } - - diff --git a/web/client/embedded.html b/web/client/embedded.html index 18846a0de6d..7379c144107 100644 --- a/web/client/embedded.html +++ b/web/client/embedded.html @@ -82,8 +82,6 @@ 100%{opacity: 0} } - - diff --git a/web/client/embeddedTemplate.html b/web/client/embeddedTemplate.html index da48ceb365f..e942631ce3d 100644 --- a/web/client/embeddedTemplate.html +++ b/web/client/embeddedTemplate.html @@ -82,26 +82,13 @@ 100%{opacity: 0} } - - - + diff --git a/web/client/epics/__tests__/cookies-test.js b/web/client/epics/__tests__/cookies-test.js index 9107c033b6f..3288c291642 100644 --- a/web/client/epics/__tests__/cookies-test.js +++ b/web/client/epics/__tests__/cookies-test.js @@ -11,31 +11,54 @@ import { testEpic, TEST_TIMEOUT, addTimeoutEpic} from './epicTestUtils'; import { LOCATION_CHANGE } from 'connected-react-router'; import { cookiePolicyChecker } from '../cookies'; import { SET_COOKIE_VISIBILITY } from '../../actions/cookie'; -import { setApi, getApi } from '../../api/userPersistedStorage'; +import { setApi, getApi, getItemKey } from '../../api/userPersistedStorage'; +import ConfigUtils from '../../utils/ConfigUtils'; describe('Cookies epics', () => { - it('test cookiePolicyChecker and enable cookie msg', done => { - const NUM_ACTIONS = 1; - testEpic(cookiePolicyChecker, NUM_ACTIONS, {type: LOCATION_CHANGE}, (actions) => { - expect(actions.length).toBe(NUM_ACTIONS); - const [action] = actions; - expect(action.type).toBe(SET_COOKIE_VISIBILITY); - expect(action.status).toBe(true); + const privacy = {enabled: true, policyVersion: 'epic-test', categories: []}; + beforeEach(() => { + ConfigUtils.setConfigProp('privacy', privacy); + }); + afterEach(() => { + ConfigUtils.removeConfigProp('privacy'); + setApi("localStorage"); + }); + it('opens the privacy panel on the first visit', done => { + setApi("memoryStorage"); + testEpic(cookiePolicyChecker, 1, {type: LOCATION_CHANGE}, (actions) => { + expect(actions).toEqual([{type: SET_COOKIE_VISIBILITY, status: true}]); done(); }, {}); }); - it('test cookiePolicyChecker and trigger error for accessing localStorage', done => { + it('opens the privacy panel when storage access fails', done => { setApi("memoryStorage"); getApi().setAccessDenied(true); - const NUM_ACTIONS = 1; - testEpic(addTimeoutEpic(cookiePolicyChecker, 40), NUM_ACTIONS, {type: LOCATION_CHANGE}, (actions) => { - expect(actions.length).toBe(NUM_ACTIONS); - const [action] = actions; - expect(action.type).toBe(TEST_TIMEOUT); + testEpic(cookiePolicyChecker, 1, {type: LOCATION_CHANGE}, (actions) => { + expect(actions).toEqual([{type: SET_COOKIE_VISIBILITY, status: true}]); getApi().setAccessDenied(false); - setApi("localStorage"); done(); }, {}); }); + it('opens the privacy panel and removes an approval of the old cookie notice', done => { + setApi("memoryStorage"); + getApi().setItem(getItemKey('cookie', 'approved'), 'true'); + testEpic(cookiePolicyChecker, 1, {type: LOCATION_CHANGE}, (actions) => { + expect(actions).toEqual([{type: SET_COOKIE_VISIBILITY, status: true}]); + expect(getApi().getItem(getItemKey('cookie', 'approved'))).toBe(null); + done(); + }, {}); + }); + it('shows nothing when the privacy configuration is disabled or missing', done => { + setApi("memoryStorage"); + ConfigUtils.setConfigProp('privacy', {...privacy, enabled: false}); + testEpic(addTimeoutEpic(cookiePolicyChecker, 40), 1, {type: LOCATION_CHANGE}, (disabled) => { + expect(disabled[0].type).toBe(TEST_TIMEOUT); + ConfigUtils.removeConfigProp('privacy'); + testEpic(addTimeoutEpic(cookiePolicyChecker, 40), 1, {type: LOCATION_CHANGE}, (missing) => { + expect(missing[0].type).toBe(TEST_TIMEOUT); + done(); + }, {}); + }, {}); + }); }); diff --git a/web/client/epics/cookies.js b/web/client/epics/cookies.js index 039e11449bf..845df655da4 100644 --- a/web/client/epics/cookies.js +++ b/web/client/epics/cookies.js @@ -9,15 +9,9 @@ import { LOCATION_CHANGE } from 'connected-react-router'; import Rx from 'rxjs'; -import { SET_MORE_DETAILS_VISIBILITY, setCookieVisibility, setDetailsCookieHtml } from '../actions/cookie'; -import { CHANGE_LOCALE } from '../actions/locale'; -import axios from '../libs/ajax'; -import { getApi, getItemKey } from '../api/userPersistedStorage'; - -const checkCookiesPolicyApproved = () => { - return getApi().getItem(getItemKey('cookie', 'approved')) - || getApi().getItem("cookies-policy-approved"); // legacy old item key -}; +import { setCookieVisibility } from '../actions/cookie'; +import { isCookieNoticeAcknowledged } from '../utils/CookieNoticeUtils'; +import { privacyConfigSelector } from '../utils/PrivacyChoices'; /** * Show the cookie policy notification @@ -26,38 +20,19 @@ const checkCookiesPolicyApproved = () => { * @memberof epics.cookies * @return {external:Observable} the steam of actions to trigger to display the noitification. */ -export const cookiePolicyChecker = (action$) => +export const cookiePolicyChecker = (action$, store) => action$.ofType(LOCATION_CHANGE ) .take(1) - .filter( () => { - try { - return !checkCookiesPolicyApproved(); - } catch (e) { - console.error(e); - return false; - } - }) + .filter(() => !isCookieNoticeAcknowledged(privacyConfigSelector(store.getState()))) .switchMap(() => Rx.Observable.of(setCookieVisibility(true)) ); -export const loadCookieDetailsPage = (action$, store) => - action$.ofType(SET_MORE_DETAILS_VISIBILITY, CHANGE_LOCALE ) - .filter( () => !checkCookiesPolicyApproved() && store.getState().cookie.seeMore && !store.getState().cookie.html[store.getState().locale.current]) - .switchMap(() => Rx.Observable.fromPromise( - axios.get("translations/fragments/cookie/cookieDetails-" + store.getState().locale.current + ".html", null, { - timeout: 60000, - headers: {'Accept': 'text/html', 'Content-Type': 'text/html'} - }).then(res => res.data) - )) - .switchMap(html => Rx.Observable.of(setDetailsCookieHtml(html, store.getState().locale.current ))); - /** * Epics for cookies policy informations * @name epics.cookies * @type {Object} */ export default { - cookiePolicyChecker, - loadCookieDetailsPage + cookiePolicyChecker }; diff --git a/web/client/geostory-embedded-template.html b/web/client/geostory-embedded-template.html index 91b027a7d6e..009c708da1f 100644 --- a/web/client/geostory-embedded-template.html +++ b/web/client/geostory-embedded-template.html @@ -92,25 +92,12 @@ height: 100%; } - - - + diff --git a/web/client/geostory-embedded.html b/web/client/geostory-embedded.html index bed22bfc3ce..9512fa3f51e 100644 --- a/web/client/geostory-embedded.html +++ b/web/client/geostory-embedded.html @@ -92,8 +92,6 @@ height: 100%; } - - diff --git a/web/client/index.html b/web/client/index.html index 08e0e9035e5..9975c834d9a 100644 --- a/web/client/index.html +++ b/web/client/index.html @@ -82,8 +82,6 @@ 100%{opacity: 0} } - - diff --git a/web/client/indexTemplate.html b/web/client/indexTemplate.html index 3c1a36a5d9b..702a7998288 100644 --- a/web/client/indexTemplate.html +++ b/web/client/indexTemplate.html @@ -82,26 +82,13 @@ 100%{opacity: 0} } - - - + diff --git a/web/client/plugins/Cookie.jsx b/web/client/plugins/Cookie.jsx index c4a4380bbef..d1b5fb99bf2 100644 --- a/web/client/plugins/Cookie.jsx +++ b/web/client/plugins/Cookie.jsx @@ -8,33 +8,45 @@ import { connect } from 'react-redux'; -import { setCookieVisibility, setMoreDetailsVisibility } from '../actions/cookie'; +import { setCookieVisibility, setPrivacyChoice } from '../actions/cookie'; import CookieComp from '../components/cookie/Cookie'; import cookies from '../epics/cookies'; import cookie from '../reducers/cookie'; +import { privacyConfigSelector } from '../utils/PrivacyChoices'; +import { MapFooterPrivacyAccess, FooterPrivacyAccess } from '../components/cookie/PrivacyAccessButton'; /** - * Plugin for cookie policy. - * By default it links to MapStore's cookie information page, but you can customize the - * links to point to your own cookie information page. + * Provides privacy information and optional consent management when the top-level + * privacy configuration is enabled. Contributes access to Footer and MapFooter, + * with a bottom bar on routes without a native footer. + * With privacy disabled, or without a privacy configuration, it shows nothing. + * See the privacy settings section of the developer guide for the configuration. * @name Cookie * @memberof plugins * @class * @classdesc - * @prop {string} externalCookieUrl if provided then it link to that url otherwise it will opens a section with more details. - * @prop {string} declineUrl The url associated with the leave button */ const Cookie = connect((state) => ({ show: state.cookie && state.cookie.showCookiePanel, - html: state.cookie && state.cookie.html && state.cookie.html[state.locale && state.locale.current], - seeMore: state.cookie && state.cookie.seeMore + privacyChoice: state.cookie && state.cookie.privacyChoice, + privacy: privacyConfigSelector(state), + locale: state.locale && state.locale.current }), { onSetCookieVisibility: setCookieVisibility, - onMoreDetails: setMoreDetailsVisibility + onPrivacyChoice: setPrivacyChoice })(CookieComp); export default { - CookiePlugin: Cookie, + CookiePlugin: Object.assign(Cookie, { + MapFooter: { + name: 'privacyAccess', target: 'right-footer', position: 10, + Component: MapFooterPrivacyAccess + }, + Footer: { + name: 'privacyAccess', target: 'menu', position: 10, + Component: FooterPrivacyAccess + } + }), reducers: {cookie: cookie}, epics: cookies }; diff --git a/web/client/plugins/Share.jsx b/web/client/plugins/Share.jsx index dca8598a8a5..981d351cb40 100644 --- a/web/client/plugins/Share.jsx +++ b/web/client/plugins/Share.jsx @@ -30,14 +30,13 @@ import { mapTypeSelector } from "../selectors/maptype"; import { dashboardResource } from '../selectors/dashboard'; /** * Share Plugin allows to share the current URL (location.href) in some different ways. - * You can share it on socials networks(facebook,twitter,google+,linkedIn) * copying the direct link * copying the embedded code * using the QR code with mobile apps * @class * @memberof plugins * @prop {node|string} [title] the title of the page - * @prop {boolean} [socialPanel] if false, hide the social tab. Default true + * @prop {boolean} [socialPanel] deprecated. If true, shows the social tab, with links to share on social networks. Default false * @prop {boolean} [embedPanel] if false, hide the embed tab. Default true * @prop {string} [shareUrlRegex] reqular expression to parse the shareUrl to generate the final url, using shareUrlReplaceString * @prop {string} [shareUrlReplaceString] expression to be replaced by groups of the shareUrlRegex to get the final shareUrl to use for the iframe @@ -45,7 +44,6 @@ import { dashboardResource } from '../selectors/dashboard'; * @prop {boolean} [embedOptions.showTOCToggle] true by default, set to false to hide the "show TOC" toggle. * @prop {boolean} [showAPI] default true, if false, hides the API entry of embed. * @prop {function} [onClose] function to call on close window event. - * @prop {function} [getCount] function used to get the count for social links. * @prop {object} [cfg.advancedSettings] show advanced settings (bbox param, centerAndZoom param or home button) f.e {bbox: true, homeButton: true, centerAndZoom: true} * @prop {boolean} [cfg.advancedSettings.bbox] if true, the share url is generated with the bbox param * @prop {boolean} [cfg.advancedSettings.centerAndZoom] if true, the share url is generated with the center and zoom params diff --git a/web/client/plugins/__tests__/CookieExtensionContract-test.jsx b/web/client/plugins/__tests__/CookieExtensionContract-test.jsx new file mode 100644 index 00000000000..c1433780842 --- /dev/null +++ b/web/client/plugins/__tests__/CookieExtensionContract-test.jsx @@ -0,0 +1,79 @@ +/* + * Copyright 2026, GeoSolutions Sas. + * All rights reserved. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import ReactDOM from 'react-dom'; +import ReactTestUtils from 'react-dom/test-utils'; +import expect from 'expect'; +import Cookie from '../../components/cookie/Cookie'; +import cookie from '../../reducers/cookie'; +import controls from '../../reducers/controls'; +import ConfigUtils from '../../utils/ConfigUtils'; +import { getApi } from '../../api/userPersistedStorage'; +import { privacyConfigSelector, privacyChoiceKey, makePrivacyChoice } from '../../utils/PrivacyChoices'; + +// Actions exchanged with the privacy settings extension +// (https://github.com/geosolutions-it/mapstore-privacy-settings-extension), which does not import +// MapStore modules: their shape must not change. +describe('Privacy settings contract with extensions', () => { + beforeEach(() => { + document.body.innerHTML = '
'; + }); + afterEach(() => { + ReactDOM.unmountComponentAtNode(document.getElementById('container')); + document.body.innerHTML = ''; + ConfigUtils.removeConfigProp('privacy'); + getApi().removeItem(privacyChoiceKey()); + }); + it('the configuration dispatched by an extension is used by the privacy panel', () => { + ConfigUtils.setConfigProp('privacy', {enabled: true, policyVersion: 'vanilla', retentionDays: 180, categories: []}); + const state = {controls: controls(undefined, { + type: 'SET_CONTROL_PROPERTY', + control: 'privacy', + property: 'defaults', + value: { + enabled: true, + policyVersion: 'extension-1', + retentionDays: 30, + categories: [{id: 'statistics', description: {'en-US': 'Statistics'}}], + links: {cookie: {'en-US': 'extensions/PrivacySettings/assets/en-US/cookie.html'}} + } + })}; + expect(privacyConfigSelector(state)).toEqual({ + enabled: true, + policyVersion: 'extension-1', + retentionDays: 30, + categories: [{id: 'statistics', description: {'en-US': 'Statistics'}}], + links: {cookie: {'en-US': 'extensions/PrivacySettings/assets/en-US/cookie.html'}} + }); + }); + it('SET_PRIVACY_CHOICE carries the validated choice, or null when the stored one is not valid', () => { + const privacy = {enabled: true, policyVersion: 'contract-1', categories: [{id: 'statistics'}]}; + getApi().setItem(privacyChoiceKey(), JSON.stringify(makePrivacyChoice(privacy, {statistics: true}))); + let state = cookie(undefined, {type: 'INIT'}); + const actions = []; + const onPrivacyChoice = choice => { + const action = {type: 'SET_PRIVACY_CHOICE', choice}; + actions.push(action); + state = cookie(state, action); + }; + ReactTestUtils.act(() => { + ReactDOM.render(, document.getElementById('container')); + }); + expect(actions.length).toBe(1); + expect(actions[0].choice.categories).toEqual({statistics: true}); + expect(actions[0].choice.policyVersion).toBe('contract-1'); + expect(state.privacyChoice).toBe(actions[0].choice); + ReactDOM.unmountComponentAtNode(document.getElementById('container')); + // a new policy version makes the stored choice invalid + ReactTestUtils.act(() => { + ReactDOM.render(, document.getElementById('container')); + }); + expect(actions.length).toBe(2); + expect(actions[1].choice).toBe(null); + expect(state.privacyChoice).toBe(null); + }); +}); diff --git a/web/client/product/__tests__/embedded-cookie-registry-test.js b/web/client/product/__tests__/embedded-cookie-registry-test.js new file mode 100644 index 00000000000..efbd8e0d059 --- /dev/null +++ b/web/client/product/__tests__/embedded-cookie-registry-test.js @@ -0,0 +1,22 @@ +/* + * Copyright 2026, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +import expect from 'expect'; +import apiPlugins from '../apiPlugins'; +import geostoryPlugins from '../pluginsGeostoryEmbedded'; +import dashboardPlugins from '../pluginsDashboardEmbedded'; + +describe('Cookie plugin availability in embedded registries', () => { + it('provides the configured plugin in map embeds', () => { + expect(apiPlugins.plugins.CookiePlugin).toExist(); + }); + it('provides the plugin for geostory and dashboard embeds', () => { + expect(geostoryPlugins.plugins.CookiePlugin).toExist(); + expect(dashboardPlugins.plugins.CookiePlugin).toExist(); + }); +}); diff --git a/web/client/product/apiPlugins.js b/web/client/product/apiPlugins.js index 55bfc58d2c8..4c8528eed3b 100644 --- a/web/client/product/apiPlugins.js +++ b/web/client/product/apiPlugins.js @@ -9,6 +9,7 @@ export default { plugins: { // framework plugins + CookiePlugin: require('../plugins/Cookie').default, DetailsPlugin: require('../plugins/Details').default, DrawerMenuPlugin: require('../plugins/DrawerMenu').default, FeedbackMaskPlugin: require('../plugins/FeedbackMask').default, diff --git a/web/client/product/assets/css/viewer.css b/web/client/product/assets/css/viewer.css index fb66444ef1b..56a865c6d85 100644 --- a/web/client/product/assets/css/viewer.css +++ b/web/client/product/assets/css/viewer.css @@ -45,11 +45,11 @@ html, body, #container, .fill { .map-logo{ position:absolute; - width:90px; - height:27px; + width:36px; + height:36px; bottom:36px; left:5px; - background-image:url(../img/mapstore2_logo.png); + background-image:url(../img/logo.png); background-repeat:no-repeat; background-size:contain; cursor: pointer; diff --git a/web/client/product/assets/privacy/cookie.html b/web/client/product/assets/privacy/cookie.html new file mode 100644 index 00000000000..693ae52fcf2 --- /dev/null +++ b/web/client/product/assets/privacy/cookie.html @@ -0,0 +1,379 @@ + + + + + + + Cookie Policy · MapStore template + + + + +
+ +

MapStore template

+

Cookie Policy

+ +

+ Operator: + [OPERATOR LEGAL NAME AND CONTACT] + · Effective date: + [DATE / NOTICE VERSION]. +

+

About cookies and browser storage

+

+ Cookies are small files stored by a browser. LocalStorage and + SessionStorage are separate browser storage mechanisms. This + template describes the tools identified in the default + configuration of MapStore, including conditional features. No + analytics or advertising tools are configured in it. + [OPERATOR: VERIFY THE LIST, HOSTNAMES, PURPOSES AND + DURATIONS FOR YOUR INSTALLATION; ADD OR REMOVE ENTRIES AS + NEEDED]. +

+

+ The list below was checked on a MapStore installation with the default configuration: sign-in with MapStore's own user database, the default "OSM Bright" background map and no optional services enabled. Storage used by MapStore itself and cookies set by the external demo services are listed in separate tables. Plugins or services added by the operator are not covered and must be checked separately. +

+

Your choices

+

+ The same privacy panel opens on a first visit to the home page + or a direct Map, Dashboard, GeoStory or embed resources. You can + reopen the privacy settings from the bottom bar on every + supported route. Opening or closing the settings does not mean + accepting Terms or consenting to data processing. +

+

Categories:

+
    +
  • + Necessary: always active for the requested + operations described below. These technical tools do not + require consent: the panel provides information and a Close + action. Closing the panel records dismissal separately and + does not express consent. +
  • +
  • + Optional functional, statistics and marketing: + not used by this configuration, so no consent switch is + shown. If optional services are added, the operator must + describe them here and provide the corresponding choices + before activating them. +
  • +
+

When optional tools are configured, from Privacy settings you can:

+
    +
  • refuse optional tools: refusal keeps them inactive;
  • +
  • save a selection;
  • +
  • withdraw consent.
  • +
+

+ Closing an initial optional-choice panel also keeps optional + tools off. + [ADD ANY OPTIONAL SERVICES, PURPOSES AND PROVIDER NOTICES, + OR REMOVE THIS INSTRUCTION IF NONE ARE USED]. +

+

Cookie and browser storage inventory

+

+ Conditional entries are used only when the relevant feature is + active. LocalStorage is scoped to the application origin; + cookies follow their domain and path scope. Browser session + restoration can extend session cookies. “No explicit expiry” + means that an application or browser action is needed to remove + the value. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name / originPurpose and useDuration and removal
+ mapstore.persistence.security
LocalStorage; installation origin +
+ Necessary for sign-in/session continuity. Key + may exist anonymously with no authenticated + user. Holds authentication state after local + login. + + The storage entry has no fixed expiry. Access + and refresh tokens have separate validity set by + the authentication service; the local baseline + returns a 24-hour access token. Logout clears + user and token values; an empty security entry + may remain. + [VERIFY YOUR AUTHENTICATION PROVIDER]. +
+ mapstore.privacy.choices
LocalStorage; installation origin +
+ Necessary to remember an optional consent + decision, including refusal. Not written merely + by opening settings when only necessary tools are used. + + 180 days from an explicit choice in this + baseline; schema/policy version changes + invalidate the record. Expired, malformed or + superseded records are removed on the next read + when storage access permits. No optional choice + is retained when no optional categories are + configured. +
+ mapstore.privacy.notice
LocalStorage; installation origin +
+ Necessary to remember dismissal of the + first-visit privacy information when only + necessary tools are configured. This is not a + consent record, grants no optional category and + contains no user identifier. + + Written only when closing the information panel; + 180-day logical validity in this configuration. + A changed policy version or expiry shows the + information again. Expired, malformed or + superseded records are removed on the next read + when storage access permits. If storage is + unavailable the notice can reappear on another + visit. +
+ mapstore.cookie.approved; + cookies-policy-approved
LocalStorage; installation origin +
+ Old notice acknowledgement, never optional + consent. Removed when the new privacy panel is + enabled; not converted into a new consent or + dismissal. + + No expiry in versions older than v2026.03.00; removed on the next + privacy-state check when browser storage + permits. +
+ mapstore.usersession.<host_path>.<name>
LocalStorage; installation origin +
+ Conditional editing-session recovery; inactive + in this standard configuration. + [IF ENABLED, ASSESS ITS PURPOSE, CHOICE + MECHANISM AND RETENTION BEFORE USE]. + + No explicit expiry; removed by the + session-management feature or browser clearing. +
+ mapstore.plugin.tutorial.<id>.disabled
LocalStorage; installation origin +
+ Remembers an explicit request not to show a + tutorial again, when that feature is used. + No explicit expiry.
+ loglevel
LocalStorage, or first-party cookie when + LocalStorage is unavailable; installation origin +
+ Written by the DXF parsing library when the user + imports a DXF file. Not used by MapStore. + + Removed, or restored to its previous value, + right after the library is loaded. +
+ credentialStorage
SessionStorage; installation origin +
+ Necessary when the user supplies credentials for + a protected service. Separate from local + login. + Tab session; application/browser clearing.
+ queryParams; queryParams-<id>
SessionStorage; installation origin +
+ Necessary handoff of user-requested POST/embed + parameters, consumed and removed as parameters + are read. + + Consumed entries removed; otherwise tab session. +
+ mapstore.loginRedirectHash
SessionStorage; installation origin +
+ Conditional return route for an external sign-in + flow. See actual constant in source; no SSO + provider is configured here. + + Removed when consumed; otherwise tab session. +
+ exportDataResults_<id>
First-party JavaScript cookie; current + application path +
+ Necessary handoff of results for an explicitly + requested layer export; used only by that + workflow. + + No Max-Age/Expires in writer: session cookie. +
+ GS_FLOW_CONTROL
Third-party + Set-Cookie; maps1…maps6.geosolutionsgroup.com, + path /geoserver +
+ Technical request concurrency/load control and + abuse protection for the requested map service; + not classified as statistics or marketing. + Distinct from product-origin storage. + + Session in observed headers: no Max-Age/Expires. + No Domain, Secure, HttpOnly or SameSite + attributes observed. Browser policy may block + it. +
+
+

External requests and cookie handling

+

+ OSM Bright is served by six GeoSolutions WMS hosts. It is + distinct from tile.openstreetmap.org, which is used + only when that basemap is selected. A request to a map service + is not evidence of an optional tracking purpose. The WMS emits + GS_FLOW_CONTROL even if a browser blocks its + storage; a blocked cookie is still an emitted cookie. Whether + the browser stores or sends it also depends on browser settings. + MapStore cannot delete cookies belonging to another domain. +

+

+ Map imagery, geocoding searches and catalogue operations send connection metadata and requested coordinates, text or resources to their destination. With the default configuration, no cookies are set by the separate public OSM tile service, the Nominatim search service or the configured catalogue sources and added layers (e.g. WMS ones). + [VERIFY ACTUAL PROVIDERS AND LINK THEIR NOTICES]. Information about recipients and personal-data processing + belongs in the Privacy Policy. +

+ +

Retention and withdrawal limits

+

+ The preference record uses a configured 180-day lifetime, + distinct from provider cookie lifetimes and from any in-memory + concurrency timeout in GeoServer. Read access, consent updates, + focus and periodic checks validate it. Withdrawal prevents + further work by registered integrations and requests + cancellation where supported. Requests already transmitted, + browser caches, remote logs and cookies controlled by other + domains cannot be erased by MapStore. Use browser privacy + controls for third-party storage. +

+

+ Further information: + Garante: cookies and other tracking tools. +

+

Back to MapStore

+
+
+ Installation template · complete and review before publication +
+ + diff --git a/web/client/product/assets/privacy/privacy-docs.css b/web/client/product/assets/privacy/privacy-docs.css new file mode 100644 index 00000000000..afb19d16e08 --- /dev/null +++ b/web/client/product/assets/privacy/privacy-docs.css @@ -0,0 +1,37 @@ +:root { color-scheme: light; } +* { box-sizing: border-box; } +body { margin: 0; color: #273746; background: #f7f9fa; font: 15px/1.6 "Noto Sans", "Helvetica Neue", Arial, sans-serif; } +a { color: #17678c; } +a:hover, a:focus { color: #0f4c6b; } +a:focus-visible { outline: 3px solid #e39b29; outline-offset: 3px; } +.site-header { background: #fff; border-bottom: 1px solid #dce3e7; } +.header-inner { max-width: 1040px; margin: auto; padding: 10px 20px; display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; } +.brand { display: inline-flex; align-items: center; min-height: 40px; } +.brand img { display: block; width: auto; height: 54px; } +.site-nav { display: flex; gap: 16px; flex-wrap: wrap; font-size: 14px; } +.site-nav a { text-decoration: none; } +.site-nav a[aria-current="page"] { font-weight: 700; border-bottom: 2px solid #17678c; } +.document { max-width: 900px; margin: 28px auto 48px; padding: 28px 34px; background: #fff; border: 1px solid #dce3e7; border-radius: 3px; } +.eyebrow { margin: 0 0 2px; color: #557180; font-size: 12px; letter-spacing: .07em; text-transform: uppercase; font-weight: 700; } +h1 { font-size: 28px; line-height: 1.2; margin: 0 0 18px; font-weight: 600; } +h2 { font-size: 18px; margin: 25px 0 8px; padding-bottom: 5px; border-bottom: 1px solid #e7ecef; font-weight: 600; } +p, ul { margin: 10px 0; } +ul { padding-left: 24px; } +.template-note { background: #f2f7fa; border-left: 4px solid #2c769b; padding: 12px 15px; margin: 16px 0 22px; } +.template-note strong { display: block; } +.template-warning { background: #fff4df; border: 1px solid #e39b29; border-left-width: 4px; padding: 12px 15px; margin: 0 0 22px; } +.template-warning strong { display: block; } +.placeholder { background: #fff4df; padding: 1px 4px; font-weight: 600; } +.fineprint { color: #52616b; font-size: 13px; } +code { color: #354b5b; background: #f1f3f5; padding: 2px 4px; overflow-wrap: anywhere; } +.table-scroll { overflow-x: auto; } +table { width: 100%; border-collapse: collapse; font-size: 13px; } +th, td { padding: 8px; border: 1px solid #dce3e7; text-align: left; vertical-align: top; } +th { background: #f2f7fa; } +footer { max-width: 900px; margin: 0 auto 30px; padding: 0 18px; color: #52616b; font-size: 12px; } +@media (max-width: 640px) { + .header-inner { padding: 8px 14px; } + .brand img { height: 44px; } + .document { margin: 10px 0 20px; padding: 20px 16px; border-left: 0; border-right: 0; } + h1 { font-size: 23px; } +} diff --git a/web/client/product/assets/privacy/privacy.html b/web/client/product/assets/privacy/privacy.html new file mode 100644 index 00000000000..6fa2913100f --- /dev/null +++ b/web/client/product/assets/privacy/privacy.html @@ -0,0 +1,238 @@ + + + + + + Privacy Policy · MapStore template + + + + +
+ +

MapStore template

+

Privacy Policy

+ +

+ This notice explains how personal data are processed when you + visit or use + [SERVICE NAME AND WEBSITE], + including its Maps, Dashboards, GeoStories and related services. +

+

+ Data controller: + [LEGAL NAME, ADDRESS AND CONTACT DETAILS].
Data protection contact / DPO, where applicable: + [CONTACT DETAILS OR REMOVE IF NOT APPLICABLE].
Effective date: + [DATE / VERSION]. +

+

Personal data we process

+

+ Depending on the features you use, personal data may include + connection and usage information such as IP address, browser + details, requested resources and security logs; account and + contact details; and information you provide in searches, + uploaded files, saved content or support requests. Geographic + content may contain personal data where it relates to an + identifiable person. + [SPECIFY THE DATA ACTUALLY COLLECTED AND THEIR SOURCES, + INCLUDING DATA OBTAINED FROM OTHERS WHERE APPLICABLE]. +

+

Why we process data and our legal bases

+

+ We process personal data for the purposes and on the legal bases + set out below. Each basis must correspond to the actual service + and processing operation. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
PurposeApplicable legal basis
+ Provide access to the service, manage accounts + and deliver requested features or content. + + [IDENTIFY THE APPLICABLE BASIS AND RELEVANT + CONTRACT, LAW OR PUBLIC TASK] +
+ Protect the service, prevent misuse and + investigate technical or security incidents. + + [IDENTIFY THE BASIS; DESCRIBE THE INTEREST + IF RELYING ON LEGITIMATE INTERESTS] +
+ Respond to enquiries and comply with applicable + legal obligations. + + [SPECIFY THE BASIS AND RELEVANT + OBLIGATIONS] +
+ [ADD ANY OTHER ACTUAL PURPOSE, OR REMOVE + THIS ROW] + + [SPECIFY ITS BASIS; WHERE CONSENT IS USED, + EXPLAIN THE CHOICE AND WITHDRAWAL] +
+
+

+ Providing some information may be necessary to use a requested + feature or to meet a legal or contractual requirement. + [IDENTIFY REQUIRED AND OPTIONAL INFORMATION AND THE + CONSEQUENCES OF NOT PROVIDING IT]. +

+

Who receives personal data

+

+ Access is limited to the people and organisations involved in + the relevant processing. These may include authorised staff, + hosting and support providers, identity providers and providers + of geographic or other connected services. Sharing content can + make that content available to the audience selected by its + author. + [IDENTIFY ACTUAL RECIPIENTS OR CATEGORIES, THEIR ROLES AND + ANY OTHER DISCLOSURES]. The operator of this installation is responsible for + identifying the controller and the roles of its providers; use + of MapStore software does not by itself determine those roles. +

+

International transfers

+

+ [STATE WHETHER PERSONAL DATA ARE TRANSFERRED OUTSIDE THE + EEA. WHERE APPLICABLE, IDENTIFY DESTINATIONS, THE TRANSFER + MECHANISM AND HOW TO OBTAIN INFORMATION ABOUT THE + SAFEGUARDS]. +

+

How long we keep data

+

+ Personal data are retained for the periods needed for their + stated purposes and any applicable obligations. + [SPECIFY PERIODS OR MEANINGFUL CRITERIA FOR EACH DATA + CATEGORY, INCLUDING ACCOUNTS, SAVED CONTENT, LOGS, ENQUIRIES + AND BACKUPS]. Details of cookies and browser storage, including their + durations, are provided separately in the + Cookie Policy. +

+

Your rights

+

+ Subject to the applicable conditions, you may request access to, + rectification or erasure of your personal data, restriction of + processing or data portability, and you may object to + processing. Where processing relies on consent, you can withdraw + that consent at any time without affecting the lawfulness of + processing before withdrawal. Contact + [CONTACT AND REQUEST PROCEDURE] + to exercise your rights. You also have the right to lodge a + complaint with a supervisory authority: + [RELEVANT AUTHORITY AND CONTACT OR WEBSITE]. +

+

Automated decisions

+

+ [STATE WHETHER AUTOMATED DECISION-MAKING, INCLUDING + PROFILING WITH LEGAL OR SIMILARLY SIGNIFICANT EFFECTS, IS + USED. IF APPLICABLE, EXPLAIN ITS LOGIC, SIGNIFICANCE AND + EXPECTED CONSEQUENCES]. +

+

Updates and related information

+

+ Changes to this notice will be published here with an updated + effective date. + [DESCRIBE ANY ADDITIONAL NOTIFICATION FOR MATERIAL + CHANGES]. The Cookie Policy describes + cookies, browser storage and related choices. The + Terms of Use describe service + conditions. This privacy notice provides information; it does + not request acceptance or consent. +

+

+ Legal reference: + General Data Protection Regulation (EU) 2016/679. +

+

Back to MapStore

+
+
+ Installation template · complete and review before publication +
+ + diff --git a/web/client/product/assets/privacy/terms.html b/web/client/product/assets/privacy/terms.html new file mode 100644 index 00000000000..eb2c0cf5f36 --- /dev/null +++ b/web/client/product/assets/privacy/terms.html @@ -0,0 +1,118 @@ + + + + + + Terms of Use · MapStore template + + + + +
+ +

MapStore template

+

Terms of Use

+ +

+ Service operator: + [LEGAL NAME, ADDRESS AND CONTACT].
Service / territory / effective version: + [COMPLETE]. +

+

Service covered

+

+ This installation provides MapStore tools for viewing, creating, + saving and sharing geographic resources, subject to the features + and permissions configured by its operator. + [OPERATOR: DESCRIBE SERVICE SCOPE, ELIGIBILITY, ACCOUNT + RULES AND SUPPORT CHANNEL]. +

+

Accounts, content and sharing

+

+ [OPERATOR: DEFINE PERMITTED USE, ACCOUNT RESPONSIBILITIES, + UPLOAD RULES, CONTENT RIGHTS AND COMPLAINT/REMOVAL + PROCESS]. Before publishing maps or embeds, check layer permissions, + service terms, copyright, attribution and whether the content + discloses personal or confidential information. A share link + does not automatically grant access to a protected map. +

+

Map data and external services

+

+ Configured layers are supplied by their respective data/service + providers. Their licenses, attribution and usage policies apply + to their resources. + [IDENTIFY RELEVANT DATA LICENSES, ATTRIBUTION AND EXTERNAL + SERVICE CONDITIONS]. MapStore software licensing remains distinct from the + operator's service terms. +

+

Availability and allocation of responsibility

+

+ [OPERATOR / LEGAL REVIEW: DEFINE AVAILABILITY, MAINTENANCE, + SUPPORT, FEES IF ANY, SUSPENSION/TERMINATION, LIABILITY AND + MANDATORY CONSUMER RIGHTS AS APPLICABLE]. This template makes no service-level, data-accuracy or + contractual commitment on the operator's behalf. +

+

Applicable law and changes

+

+ [OPERATOR / LEGAL REVIEW: COMPLETE APPLICABLE LAW, DISPUTE + PROCESS, CHANGE NOTIFICATION AND ANY REQUIRED ACCEPTANCE + MECHANISM]. No acceptance mechanism for Terms is implemented by the + privacy widget. +

+

Privacy is separate

+

+ See the Privacy Policy for processing information and the Cookie + Policy for storage and optional tools. Closing privacy settings, + refusing optional tools or reading these documents does not + constitute acceptance of these Terms. +

+

Back to MapStore

+
+
+ Installation template · complete and review before publication +
+ + diff --git a/web/client/product/pluginsDashboardEmbedded.js b/web/client/product/pluginsDashboardEmbedded.js index c71c91110a0..c3985e31885 100644 --- a/web/client/product/pluginsDashboardEmbedded.js +++ b/web/client/product/pluginsDashboardEmbedded.js @@ -8,9 +8,11 @@ import DashboardPlugin from '../plugins/Dashboard'; import FeedbackMaskPlugin from '../plugins/FeedbackMask'; +import CookiePlugin from '../plugins/Cookie'; export default { plugins: { + CookiePlugin, DashboardPlugin, FeedbackMaskPlugin }, diff --git a/web/client/product/pluginsGeostoryEmbedded.js b/web/client/product/pluginsGeostoryEmbedded.js index de9fc1a142b..0aa41f4b4e9 100644 --- a/web/client/product/pluginsGeostoryEmbedded.js +++ b/web/client/product/pluginsGeostoryEmbedded.js @@ -8,11 +8,13 @@ import GeoStoryPlugin from '../plugins/GeoStory'; import GeoStoryNavigationPlugin from '../plugins/GeoStoryNavigation'; import FeedbackMaskPlugin from '../plugins/FeedbackMask'; +import CookiePlugin from '../plugins/Cookie'; import ReactSwipe from 'react-swipeable-views'; import SwipeHeader from '../components/data/identify/SwipeHeader'; export default { plugins: { + CookiePlugin, GeoStoryPlugin, GeoStoryNavigationPlugin, FeedbackMaskPlugin diff --git a/web/client/reducers/__tests__/cookie-test.js b/web/client/reducers/__tests__/cookie-test.js index 7d12b727b00..2d992f553b3 100644 --- a/web/client/reducers/__tests__/cookie-test.js +++ b/web/client/reducers/__tests__/cookie-test.js @@ -8,7 +8,7 @@ import expect from 'expect'; import cookie from '../cookie'; -import { SET_COOKIE_VISIBILITY, SET_MORE_DETAILS_VISIBILITY } from '../../actions/cookie'; +import { SET_COOKIE_VISIBILITY } from '../../actions/cookie'; describe('Test the cookie reducer', () => { it('cookie visibility', () => { @@ -19,12 +19,4 @@ describe('Test the cookie reducer', () => { expect(state.showCookiePanel).toBeTruthy(); }); - it('cookie seeMore section', () => { - const state = cookie(undefined, { - type: SET_MORE_DETAILS_VISIBILITY, - status: true - }); - expect(state.seeMore).toBeTruthy(); - }); - }); diff --git a/web/client/reducers/cookie.js b/web/client/reducers/cookie.js index 4de40c85cdf..adf7bb8298b 100644 --- a/web/client/reducers/cookie.js +++ b/web/client/reducers/cookie.js @@ -8,22 +8,16 @@ import { SET_COOKIE_VISIBILITY, - SET_MORE_DETAILS_VISIBILITY, - SET_DETAILS_COOKIE_HTML + SET_PRIVACY_CHOICE } from '../actions/cookie'; -function cookie(state = { - html: {} -}, action) { +function cookie(state = {}, action) { switch (action.type) { case SET_COOKIE_VISIBILITY: { return Object.assign({}, state, {showCookiePanel: action.status}); } - case SET_MORE_DETAILS_VISIBILITY: { - return Object.assign({}, state, {seeMore: action.status}); - } - case SET_DETAILS_COOKIE_HTML: { - return Object.assign({}, state, {html: { ...state.html, [action.lang]: action.html}}); + case SET_PRIVACY_CHOICE: { + return {...state, privacyChoice: action.choice}; } default: return state; diff --git a/web/client/themes/default/fonts.less b/web/client/themes/default/fonts.less new file mode 100644 index 00000000000..13bfaebea16 --- /dev/null +++ b/web/client/themes/default/fonts.less @@ -0,0 +1,28 @@ +// Noto Sans regular, bundled with the theme so that the browser does not download it from a third-party service. +// Files from @fontsource/noto-sans 5.3.0, licensed under the SIL Open Font License (fonts/OFL.txt). +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-display: swap; + font-weight: 400; + src: url("fonts/noto-sans-vietnamese-400-normal.woff2") format("woff2"); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} + +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-display: swap; + font-weight: 400; + src: url("fonts/noto-sans-latin-ext-400-normal.woff2") format("woff2"); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +@font-face { + font-family: 'Noto Sans'; + font-style: normal; + font-display: swap; + font-weight: 400; + src: url("fonts/noto-sans-latin-400-normal.woff2") format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/web/client/themes/default/fonts/OFL.txt b/web/client/themes/default/fonts/OFL.txt new file mode 100644 index 00000000000..e5cab84f0cf --- /dev/null +++ b/web/client/themes/default/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic) NotoSans-Italic[wdth,wght].ttf: Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/web/client/themes/default/fonts/noto-sans-latin-400-normal.woff2 b/web/client/themes/default/fonts/noto-sans-latin-400-normal.woff2 new file mode 100644 index 00000000000..f9e0a65f880 Binary files /dev/null and b/web/client/themes/default/fonts/noto-sans-latin-400-normal.woff2 differ diff --git a/web/client/themes/default/fonts/noto-sans-latin-ext-400-normal.woff2 b/web/client/themes/default/fonts/noto-sans-latin-ext-400-normal.woff2 new file mode 100644 index 00000000000..3a572bef5ab Binary files /dev/null and b/web/client/themes/default/fonts/noto-sans-latin-ext-400-normal.woff2 differ diff --git a/web/client/themes/default/fonts/noto-sans-vietnamese-400-normal.woff2 b/web/client/themes/default/fonts/noto-sans-vietnamese-400-normal.woff2 new file mode 100644 index 00000000000..05d7b161c18 Binary files /dev/null and b/web/client/themes/default/fonts/noto-sans-vietnamese-400-normal.woff2 differ diff --git a/web/client/themes/default/less/cookie.less b/web/client/themes/default/less/cookie.less index 7db1ac8ba24..fb6ef4910a5 100644 --- a/web/client/themes/default/less/cookie.less +++ b/web/client/themes/default/less/cookie.less @@ -11,18 +11,11 @@ // ************** #ms-components-theme(@theme-vars) { - .mapstore-cookie-panel, - .cookie-body-container { + .mapstore-privacy-panel, + .mapstore-privacy-access { .color-var(@theme-vars[main-color]); .background-color-var(@theme-vars[main-bg]); - } - - .cookie-title, - .cookie-header { - .color-var(@theme-vars[primary-contrast]); - .cookie-close-btn { - .color-var(@theme-vars[main-color]); - } + .border-color-var(@theme-vars[main-border-color]); } } @@ -30,125 +23,72 @@ // ************** // Layout // ************** -.mapstore-cookie-panel { - height: 100%; - overflow: auto; - display: block; - font-family: inherit; +// The privacy profile is opt-in through localConfig. Keep controls available +// after a choice so refusal and withdrawal remain possible. +.mapstore-privacy-access { position: fixed; - width: auto; - box-shadow: 0 0 5px 1px #5e5e5e; - z-index: 9998; - box-sizing: border-box; - top: auto; - bottom: 0px; - left: 0px; - right: auto; -} - - -@media (max-width: @screen-md) { - .mapstore-cookie-panel.see-more { - width: 80%; - left: 10%; - height: 100%; - } -} -@media (min-width: @screen-md) { - .mapstore-cookie-panel.see-more { - width: 50%; - left: 25%; - height: 100%; - } -} -@media (max-width: @screen-sm) { - .mapstore-cookie-panel.see-more { - width: 100%; - left: 0%; - height: 100%; - } -} -@media (max-width: 420px) { - .mapstore-cookie-panel.not-see-more { - width: 100%; - left: auto; - height: auto; - } - .cookie-action .action-button{ - width: 70%; - margin-right: 15%; - margin-left: 15%; - } - .mapstore-cookie-panel.see-more { - width: 100%; - left: 0%; - height: 100%; - } + z-index: 12; + left: 0; + right: 0; + bottom: 0; + min-height: 38px; + display: flex; + align-items: center; + justify-content: flex-end; + border-top: 1px solid; + padding: 3px 12px; } - -@media (min-width: 421px) { - .mapstore-cookie-panel.not-see-more { - width: 420px; - left: auto; - height: auto; - } - .cookie-action .action-button{ - width: 33%; - margin-left: 0%; - margin-right: 0%; - } +.mapstore-privacy-open.btn { + border: 0; + background: transparent; + box-shadow: none; + color: inherit; + font-size: 12px; + padding: 4px 7px; + white-space: nowrap; } -@media (max-width: 250px) { - .cookie-action .action-button{ - width: 100%; - margin-left: 0%; - } +.mapstore-privacy-open.btn:hover, +.mapstore-privacy-open.btn:focus { + background: rgba(127, 127, 127, .12); + color: inherit; } - -.cookie-body-container { - height: 100%; - position: relative; - width: 100%; - border-radius: 2px; +.mapstore-privacy-panel { + position: fixed; + z-index: 9998; + left: 10px; + bottom: 48px; + width: min(92vw, 540px); + max-height: min(78vh, 650px); + overflow-y: auto; + padding: 16px 18px; + border: 1px solid; + border-radius: 3px; + box-shadow: 0 3px 12px #0003; font-size: 13px; - padding: 10px; - display: block; - box-sizing: border-box; - opacity: 1; - transition: 0.3s ease-in-out; - transform: translate3d(0px, 0px, 0px); - will-change: transform, opacity; - left: 0px; - text-align: justify; + line-height: 1.45; + text-align: left; + h2 { font-size: 18px; margin: 0 0 8px; } + // the title gets the focus only from code, when the panel opens, so that screen readers announce it + h2:focus { outline: none; } + p { margin: 7px 0; } + a { text-decoration: underline; } + button:focus-visible, a:focus-visible, input:focus-visible { outline: 3px solid #d99419; outline-offset: 2px; } } - -.cookie-title { - font-size: 14px; - margin: 0px 0px 5px; - padding: 0px; - font-weight: bold; +.mapstore-privacy-warning { border-left: 4px solid #c08514; background: #fff8e8; padding: 7px 9px; } +.mapstore-privacy-categories label { display: flex; gap: 10px; padding: 8px; border: 1px solid #ccc; margin: 5px 0; cursor: pointer; } +.mapstore-privacy-categories input { align-self: flex-start; margin-top: 5px; } +.mapstore-privacy-links { display: flex; flex-wrap: wrap; gap: 12px; margin: 10px 0; } +.mapstore-privacy-actions { display: flex; flex-wrap: wrap; gap: 7px; } +.mapstore-privacy-actions button { font-weight: 600; } +@media (max-width: 640px) { + .mapstore-privacy-access { padding-right: 8px; } + .mapstore-privacy-panel { left: 4px; right: 4px; bottom: 44px; width: auto; max-height: calc(100vh - 52px); } + .mapstore-privacy-actions button { flex: 1 1 40%; } } - -.cookie-action, .cookie-message { - margin: 0px; - padding: 0px; -} - -.cookie-button { - border-radius: 2px; - font-weight: bold; - margin: 10px 0px 0px; - border: 0px; - width: 100% -} - -.cookie-header { - height: 44px; -} - -.cookie-header > .cookie-close-btn { - float: right; - cursor: pointer; - font-size: 40px; - width: 44px; +.mapstore-privacy-category { + padding: 8px 0; + border-bottom: 1px solid #ddd; + > span { float: right; font-weight: normal; } + > label { display: flex; align-items: center; gap: 8px; margin: 0; cursor: pointer; } + p { margin-bottom: 0; font-size: 12px; } } diff --git a/web/client/themes/default/theme.less b/web/client/themes/default/theme.less index 49bb474a5c3..380aa0dce90 100644 --- a/web/client/themes/default/theme.less +++ b/web/client/themes/default/theme.less @@ -1,3 +1,4 @@ +@import "fonts.less"; @import "base.less"; @import "icons.less"; @import "bootstrap-theme.less"; diff --git a/web/client/translations/data.ca-ES.json b/web/client/translations/data.ca-ES.json index ff61ad0d67d..bd896ab73ed 100644 --- a/web/client/translations/data.ca-ES.json +++ b/web/client/translations/data.ca-ES.json @@ -285,11 +285,35 @@ "tooltipDeactivate": "Sortiu del mode 3D", "tooltipActivate": "Introdu\u00efu el mode 3D" }, - "cookie": { - "info": "Aquest lloc web utilitza cookies per millorar la vostra experi\u00e8ncia. Suposem que esteu b\u00e9 amb aix\u00f2,per\u00f2 podeu desactivar-lo si voleu.", - "moreDetailsButton": "M\u00e9s detalls", - "leave": "Deixar", - "accept": "Acceptar" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Fons", "language": "Llengua", diff --git a/web/client/translations/data.da-DK.json b/web/client/translations/data.da-DK.json index d9306d11521..5b567f53cca 100644 --- a/web/client/translations/data.da-DK.json +++ b/web/client/translations/data.da-DK.json @@ -350,11 +350,35 @@ "tooltipDeactivate": "Forlad 3D-visning", "tooltipActivate": "Skift til 3D-visning" }, - "cookie": { - "info": "Denne hjemmeside bruger cookies for at forbedre din oplevelse. Vi antager, at du accepterer dette, men du kan fravælge det, hvis du ønsker det.", - "moreDetailsButton": "Flere detaljer", - "leave": "Forlad", - "accept": "Acceptér" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Baggrund", "language": "Sprog", diff --git a/web/client/translations/data.de-DE.json b/web/client/translations/data.de-DE.json index 47b0264f439..82c2aede52c 100644 --- a/web/client/translations/data.de-DE.json +++ b/web/client/translations/data.de-DE.json @@ -380,11 +380,35 @@ "tooltipDeactivate": "Beenden Sie den 3D-Modus", "tooltipActivate": "Starten Sie den 3D-Modus" }, - "cookie": { - "info": "Diese Webseite verwendet Cookies damit Sie diese einwandfrei nutzen können. Wir gehen davon aus, dass sie damit einverstanden sind, andernfalls können Sie die Webseite verlassen.", - "moreDetailsButton": "Mehr Details", - "leave": "Verlassen", - "accept": "Annehmen" + "privacySettings": { + "title": "Datenschutzeinstellungen", + "settings": "Datenschutzeinstellungen", + "necessary": "Funktional und notwendig", + "always": "Immer aktiv", + "functional": "Optionale Funktionen", + "statistics": "Statistik", + "marketing": "Marketing", + "unused": "Nicht verwendet", + "on": "An", + "off": "Aus", + "reject": "Optionale ablehnen", + "accept": "Optionale akzeptieren", + "customize": "Anpassen", + "save": "Auswahl speichern", + "close": "Schließen", + "withdraw": "Alle optionalen Einwilligungen widerrufen", + "baseline": "Diese Konfiguration verwendet nur notwendige technische Mittel, für die keine Einwilligung erforderlich ist. Das Schließen dieses Hinweises ist keine Einwilligung.", + "optional": "Optionale Mittel bleiben deaktiviert, bis Sie eine Wahl treffen. Sie können sie ablehnen und MapStore weiter verwenden.", + "required": "Authentifizierung bei der Anmeldung, Sicherheit und Speicherung Ihrer Datenschutzeinstellungen. Zwecke und Dauer finden Sie in der Cookie-Richtlinie.", + "status": "Sie können Ihre Einwilligung jederzeit über die untere Leiste ändern oder widerrufen. Der Widerruf beendet registrierte Integrationen; bereits gesendete Daten oder Cookies Dritter werden dadurch nicht entfernt.", + "storageError": "Ihre Auswahl konnte nicht gespeichert werden. Optionale Mittel bleiben deaktiviert. Prüfen Sie den Browserspeicher und versuchen Sie es erneut.", + "fixture": "LOKALE TESTUMGEBUNG: synthetische optionale Mittel, nicht in Vanilla enthalten.", + "templateWarning": "Die Richtlinienseiten müssen noch konfiguriert werden! Die aktuellen Seiten sind noch die Vorlagen von MapStore: Der Betreiber dieser Installation hat noch keine eigenen Seiten konfiguriert.", + "templateWarningLink": "So werden sie konfiguriert", + "policies": "Richtlinien", + "cookie": "Cookie-Richtlinie", + "privacy": "Datenschutzerklärung", + "terms": "Nutzungsbedingungen" }, "background": "Hintergrund", "language": "Sprache", diff --git a/web/client/translations/data.en-US.json b/web/client/translations/data.en-US.json index 0daaf55948b..830dabdda90 100644 --- a/web/client/translations/data.en-US.json +++ b/web/client/translations/data.en-US.json @@ -380,11 +380,35 @@ "tooltipDeactivate": "Exit 3D Mode", "tooltipActivate": "Enter 3D Mode" }, - "cookie": { - "info": "This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.", - "moreDetailsButton": "More Details", - "leave": "Leave", - "accept": "Accept" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Background", "language": "Language", diff --git a/web/client/translations/data.es-ES.json b/web/client/translations/data.es-ES.json index cd3d84b9d8f..57e351b46b0 100644 --- a/web/client/translations/data.es-ES.json +++ b/web/client/translations/data.es-ES.json @@ -380,11 +380,35 @@ "tooltipDeactivate": "Salir del modo 3D", "tooltipActivate": "Entrar en el modo 3D" }, - "cookie": { - "info": "Esta sitio utiliza cookies para mejorar su experiencia. Asumiremos que está de acuerdo, si no puede optar por salir.", - "moreDetailsButton": "Más detalles", - "leave": "Abandonar", - "accept": "Aceptar" + "privacySettings": { + "title": "Configuración de privacidad", + "settings": "Configuración de privacidad", + "necessary": "Funcionales y necesarias", + "always": "Siempre activas", + "functional": "Funcionales opcionales", + "statistics": "Estadísticas", + "marketing": "Marketing", + "unused": "No utilizadas", + "on": "Activadas", + "off": "Desactivadas", + "reject": "Rechazar opcionales", + "accept": "Aceptar opcionales", + "customize": "Personalizar", + "save": "Guardar selección", + "close": "Cerrar", + "withdraw": "Retirar todos los consentimientos opcionales", + "baseline": "Esta configuración utiliza solo herramientas técnicas necesarias, que no requieren consentimiento. Cerrar este aviso no expresa consentimiento.", + "optional": "Las herramientas opcionales permanecen desactivadas hasta que usted elija. Puede rechazarlas y seguir usando MapStore.", + "required": "Autenticación al iniciar sesión, seguridad y memorización de su configuración de privacidad. Consulte la Política de cookies para conocer las finalidades y la duración.", + "status": "Puede cambiar o retirar el consentimiento en cualquier momento desde la barra inferior. La retirada detiene las integraciones registradas; no recupera datos ya enviados ni elimina cookies de terceros.", + "storageError": "No se pudo guardar su elección. Las herramientas opcionales siguen desactivadas. Compruebe el almacenamiento del navegador e inténtelo de nuevo.", + "fixture": "ENTORNO DE PRUEBA LOCAL: herramientas opcionales sintéticas, no incluidas en Vanilla.", + "templateWarning": "¡Las políticas todavía deben configurarse! Las páginas actuales siguen siendo las plantillas de MapStore: el operador de esta instalación todavía no ha configurado sus propias páginas.", + "templateWarningLink": "Cómo configurarlas", + "policies": "Políticas", + "cookie": "Política de cookies", + "privacy": "Política de privacidad", + "terms": "Condiciones de uso" }, "background": "Fondo", "language": "Idioma", diff --git a/web/client/translations/data.fi-FI.json b/web/client/translations/data.fi-FI.json index e2cffc5fedd..66acc509dda 100644 --- a/web/client/translations/data.fi-FI.json +++ b/web/client/translations/data.fi-FI.json @@ -128,11 +128,35 @@ "tooltipDeactivate": "Poistu 3D-tilasta", "tooltipActivate": "Siirry 3D-tilaan" }, - "cookie": { - "info": "Tämä verkkosivusto käyttää evästeitä käyttökokemuksen parantamiseksi. Oletamme, että tämä käy, mutta voit halutessasi poistua sivulta.", - "moreDetailsButton": "Lisätietoja", - "leave": "Jätä", - "accept": "Hyväksy" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Tausta", "language": "Kieli", diff --git a/web/client/translations/data.fr-FR.json b/web/client/translations/data.fr-FR.json index 37ff4db0bf0..ef6a9e375fc 100644 --- a/web/client/translations/data.fr-FR.json +++ b/web/client/translations/data.fr-FR.json @@ -380,11 +380,35 @@ "tooltipDeactivate": "Sortir du mode 3D", "tooltipActivate": "Entrer en mode 3D" }, - "cookie": { - "info": "Ce site utilise des cookies pour améliorer votre expérience. Nous supposons que vous êtes d'accord, mais vous êtes libre de les refuser.", - "moreDetailsButton": "Plus de détails", - "leave": "Quitter", - "accept": "Accepter" + "privacySettings": { + "title": "Paramètres de confidentialité", + "settings": "Paramètres de confidentialité", + "necessary": "Fonctionnels et nécessaires", + "always": "Toujours actifs", + "functional": "Fonctionnels optionnels", + "statistics": "Statistiques", + "marketing": "Marketing", + "unused": "Non utilisés", + "on": "Activés", + "off": "Désactivés", + "reject": "Refuser les optionnels", + "accept": "Accepter les optionnels", + "customize": "Personnaliser", + "save": "Enregistrer les choix", + "close": "Fermer", + "withdraw": "Retirer tous les consentements optionnels", + "baseline": "Cette configuration n'utilise que des outils techniques nécessaires, qui ne requièrent pas de consentement. Fermer cet avis ne vaut pas consentement.", + "optional": "Les outils optionnels restent désactivés jusqu'à votre choix. Vous pouvez les refuser et continuer à utiliser MapStore.", + "required": "Authentification lors de la connexion, sécurité et mémorisation de vos paramètres de confidentialité. Les finalités et la durée sont indiquées dans la Politique de cookies.", + "status": "Vous pouvez modifier ou retirer votre consentement à tout moment depuis la barre inférieure. Le retrait arrête les intégrations enregistrées ; il ne récupère pas les données déjà envoyées et ne supprime pas les cookies tiers.", + "storageError": "Votre choix n'a pas pu être enregistré. Les outils optionnels restent désactivés. Vérifiez le stockage du navigateur et réessayez.", + "fixture": "ENVIRONNEMENT DE TEST LOCAL : outils optionnels synthétiques, non inclus dans Vanilla.", + "templateWarning": "Les politiques doivent encore être configurées ! Les pages actuelles sont encore les modèles de MapStore : l'exploitant de cette installation n'a pas encore configuré ses propres pages.", + "templateWarningLink": "Comment les configurer", + "policies": "Politiques", + "cookie": "Politique de cookies", + "privacy": "Politique de confidentialité", + "terms": "Conditions d'utilisation" }, "background": "Fond de plan", "language": "langue", diff --git a/web/client/translations/data.hr-HR.json b/web/client/translations/data.hr-HR.json index 2ed1750fa17..b852520d54a 100644 --- a/web/client/translations/data.hr-HR.json +++ b/web/client/translations/data.hr-HR.json @@ -127,11 +127,35 @@ "tooltipDeactivate": "Napusti 3D prikaz", "tooltipActivate": "Uđi u 3D prikaz" }, - "cookie": { - "info": "Ova stranica koristi kolačiće za pružanje boljeg korisničkog iskustva i funkcionalnosti. Postavke kolačića mogu se kontrolirati i prilagoditi u vašem web pregledniku.", - "moreDetailsButton": "Više detalja", - "leave": "Napusti", - "accept": "Prihvati" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Podloga", "language": "Jezik", diff --git a/web/client/translations/data.is-IS.json b/web/client/translations/data.is-IS.json index d2338c05475..a4006ec583d 100644 --- a/web/client/translations/data.is-IS.json +++ b/web/client/translations/data.is-IS.json @@ -233,11 +233,35 @@ "tooltipDeactivate": "Exit 3D Mode", "tooltipActivate": "Enter 3D Mode" }, - "cookie": { - "info": "This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.", - "moreDetailsButton": "More Details", - "leave": "Leave", - "accept": "Accept" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Background", "language": "Language", diff --git a/web/client/translations/data.it-IT.json b/web/client/translations/data.it-IT.json index cb6bd4a457e..ea8f9a1fdbb 100644 --- a/web/client/translations/data.it-IT.json +++ b/web/client/translations/data.it-IT.json @@ -380,11 +380,35 @@ "tooltipDeactivate": "Disattiva la modalità 3D", "tooltipActivate": "Attiva la modalità 3D" }, - "cookie": { - "info": "Questo sito web usa i cookie per migliorare la tua esperienza. Assumiamo che sei d'accordo sul loro utilizzo, ma puoi lasciare il sito se sei contrario.", - "moreDetailsButton": "Più dettagli", - "leave": "Lascia il sito", - "accept": "Accetto" + "privacySettings": { + "title": "Impostazioni privacy", + "settings": "Impostazioni privacy", + "necessary": "Funzionali e necessari", + "always": "Sempre attivi", + "functional": "Funzionali opzionali", + "statistics": "Statistiche", + "marketing": "Marketing", + "unused": "Non utilizzati", + "on": "Attivi", + "off": "Disattivati", + "reject": "Rifiuta opzionali", + "accept": "Accetta opzionali", + "customize": "Personalizza", + "save": "Salva le scelte", + "close": "Chiudi", + "withdraw": "Revoca tutti i consensi opzionali", + "baseline": "Questa configurazione utilizza solo strumenti tecnici necessari, per i quali non è richiesto il consenso. Chiudere questo avviso non esprime un consenso.", + "optional": "Gli strumenti opzionali restano spenti fino alla tua scelta. Puoi rifiutarli e continuare a usare MapStore.", + "required": "Autenticazione quando accedi, sicurezza e memorizzazione delle impostazioni privacy. Finalità e durata sono nella Cookie Policy.", + "status": "Puoi cambiare o revocare il consenso dalla barra inferiore. La revoca interrompe le integrazioni registrate; non ritira dati già inviati né elimina cookie di terzi.", + "storageError": "La scelta non è stata salvata. Gli opzionali restano spenti. Controlla lo storage del browser e riprova.", + "fixture": "FIXTURE DI TEST LOCALE: strumenti opzionali sintetici, esclusi da Vanilla.", + "templateWarning": "Le informative devono ancora essere configurate! Le pagine attuali sono ancora i modelli di MapStore: il gestore di questa installazione non ha ancora configurato le proprie pagine.", + "templateWarningLink": "Come configurarle", + "policies": "Informative", + "cookie": "Cookie Policy", + "privacy": "Informativa privacy", + "terms": "Termini di utilizzo" }, "background": "Sfondo", "language": "Lingua", diff --git a/web/client/translations/data.nl-NL.json b/web/client/translations/data.nl-NL.json index 995aa531e1d..f56b4ab140b 100644 --- a/web/client/translations/data.nl-NL.json +++ b/web/client/translations/data.nl-NL.json @@ -300,11 +300,35 @@ "tooltipDeactivate": "Verlaat de 3D-modus", "tooltipActivate": "Ga naar de 3D-modus" }, - "cookie": { - "info": "Deze website maakt gebruik van cookies om uw ervaring te verbeteren. We gaan ervan uit dat je hiermee akkoord gaat, maar je kunt er van afzien als je dat wilt.", - "moreDetailsButton": "Meer details", - "leave": "Verlaten", - "accept": "Aanvaarden" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Achtergrondkaart", "language": "Taal", diff --git a/web/client/translations/data.pt-BR.json b/web/client/translations/data.pt-BR.json index 332e94026c4..e8b691d698a 100644 --- a/web/client/translations/data.pt-BR.json +++ b/web/client/translations/data.pt-BR.json @@ -295,11 +295,35 @@ "tooltipDeactivate": "Sair do Modo 3D", "tooltipActivate": "Entrar no Modo 3D" }, - "cookie": { - "info": "Este site usa cookies para melhorar sua experiência. Assumiremos que você está de acordo com isso, mas você pode optar por não participar se desejar.", - "moreDetailsButton": "Mais Detalhes", - "leave": "Sair", - "accept": "Aceitar" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Plano de Fundo", "language": "Idioma", diff --git a/web/client/translations/data.pt-PT.json b/web/client/translations/data.pt-PT.json index 1b9916ebe84..daa4f445cff 100644 --- a/web/client/translations/data.pt-PT.json +++ b/web/client/translations/data.pt-PT.json @@ -311,11 +311,35 @@ "tooltipDeactivate": "Sair modo 3D", "tooltipActivate": "Activar modo 3D" }, - "cookie": { - "info": "Este website utiliza cookies para melhorar a sua experiências. Vamos assumir que concorda com isto, mas poderá sempre reverter se desejar.", - "moreDetailsButton": "Mais detalhes", - "leave": "Sair", - "accept": "Aceito" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Fundo", "language": "Idioma", diff --git a/web/client/translations/data.sk-SK.json b/web/client/translations/data.sk-SK.json index b93626b8f8e..d3041d51fe3 100644 --- a/web/client/translations/data.sk-SK.json +++ b/web/client/translations/data.sk-SK.json @@ -179,11 +179,35 @@ "tooltipDeactivate": "Opustiť 3D mód", "tooltipActivate": "Vstúpiť do 3D módu" }, - "cookie": { - "info": "This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.", - "moreDetailsButton": "Viac informácií", - "leave": "Odísť", - "accept": "Potvrdiť" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Pozadie", "language": "Jazyk", diff --git a/web/client/translations/data.sv-SE.json b/web/client/translations/data.sv-SE.json index c0f0c5488b5..506e8e55e8a 100644 --- a/web/client/translations/data.sv-SE.json +++ b/web/client/translations/data.sv-SE.json @@ -295,11 +295,35 @@ "tooltipDeactivate": "Avsluta 3D-läge", "tooltipActivate": "Öppna 3D-läge" }, - "cookie": { - "info": "Den här webbplatsen använder cookies för att förbättra din upplevelse. Vi antar att du är ok med detta, men du kan välja bort det om du vill.", - "moreDetailsButton": "Fler detaljer", - "leave": "Lämna", - "accept": "Acceptera" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "Bakgrund", "language": "Språk", diff --git a/web/client/translations/data.vi-VN.json b/web/client/translations/data.vi-VN.json index 9c24d49326f..19402d28efc 100644 --- a/web/client/translations/data.vi-VN.json +++ b/web/client/translations/data.vi-VN.json @@ -220,11 +220,35 @@ }, "confirm": "Xác nhận", "confirmTitle": "Bạn có xác nhận không?", - "cookie": { - "accept": "Chấp nhận", - "info": "Trang web này sử dụng cookie để cải thiện trải nghiệm của bạn. Chúng tôi cho rằng bạn đồng ý, nhưng bạn có thể từ chối nếu muốn.", - "leave": "Rời khỏi", - "moreDetailsButton": "Thêm chi tiết" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "cookiesPolicyNotification": { "confirm": "Tôi đồng ý", diff --git a/web/client/translations/data.zh-ZH.json b/web/client/translations/data.zh-ZH.json index d107de67095..4a051f13643 100644 --- a/web/client/translations/data.zh-ZH.json +++ b/web/client/translations/data.zh-ZH.json @@ -129,11 +129,35 @@ "tooltipDeactivate": "退出3D模式", "tooltipActivate": "进入3D模式" }, - "cookie": { - "info": "本网站使用cookies来改善您的体验。 我们假设你没有问题,但是你可以选择退出。", - "moreDetailsButton": "更多详细信息", - "leave": "离开", - "accept": "接受" + "privacySettings": { + "title": "Privacy settings", + "settings": "Privacy settings", + "necessary": "Functional and necessary", + "always": "Always active", + "functional": "Optional functional", + "statistics": "Statistics", + "marketing": "Marketing", + "unused": "Not used", + "on": "On", + "off": "Off", + "reject": "Reject optional", + "accept": "Accept optional", + "customize": "Customize", + "save": "Save choices", + "close": "Close", + "withdraw": "Withdraw all optional consent", + "baseline": "This configuration uses only necessary technical tools, which do not require consent. Closing this notice does not express consent.", + "optional": "Optional tools stay off until you choose. You can refuse them and continue using MapStore.", + "required": "Authentication when you sign in, security and remembering your privacy settings. See the Cookie Policy for purposes and duration.", + "status": "Change or withdraw consent at any time from the bottom bar. Withdrawal stops registered integrations; it cannot undo data already sent or remove third-party cookies.", + "storageError": "Your choice could not be saved. Optional tools remain off. Check browser storage and try again.", + "fixture": "LOCAL TEST FIXTURE: synthetic optional tools, not included in Vanilla.", + "templateWarning": "The policy pages still need to be configured! Current pages are still referring to the MapStore templates: the operator of this installation has not configured its own pages yet.", + "templateWarningLink": "How to configure them", + "policies": "Policies", + "cookie": "Cookie Policy", + "privacy": "Privacy Policy", + "terms": "Terms of Use" }, "background": "背景", "language": "语言", diff --git a/web/client/translations/fragments/cookie/cookieDetails-ca-ES.html b/web/client/translations/fragments/cookie/cookieDetails-ca-ES.html deleted file mode 100644 index a7a8cb206b9..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-ca-ES.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-da-DK.html b/web/client/translations/fragments/cookie/cookieDetails-da-DK.html deleted file mode 100644 index a926e1bc4fb..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-da-DK.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookiepolitik

-
-

- I henhold til lovdekret nr. 196/2003, der erstattede lov nr. 675/1996 om beskyttelse af personoplysninger, informerer vi dig om, at du ved at udfylde denne formular og sende denne e-mail giver samtykke til behandling af dine personoplysninger (følsomme data behandles under ingen omstændigheder) indhentet af GeoSolutions SAS via elektroniske og/eller automatiske værktøjer. Du kan til enhver tid udøve dine rettigheder i henhold til lovdekret nr. 196/2003 (adgang til data, opdateringer, integration, sletning). Ved at klikke på "Accepter"-knappen bekræfter du, at du har læst denne tekst og giver samtykke til behandling af dine personoplysninger. Du kan til enhver tid anmode personalet på GeoSolutions SAS' hjemmeside om at framelde dig servicen ved at følge instruktionerne i slutningen af hver besked. -

-

Cookies og hvordan de gavner dig

-

Vores hjemmeside bruger cookies, som næsten alle hjemmesider gør, for at give dig den bedste oplevelse. Cookies er små tekstfiler, der placeres på din computer eller mobiltelefon, når du browser på hjemmesider.

-

Vores cookies hjælper os med at:

-
    -
  • Få vores hjemmeside til at fungere som forventet
  • -
  • Huske dine indstillinger under og mellem besøg
  • -
  • Forbedre hastigheden og sikkerheden på sitet
  • -
  • Lade dig dele sider med sociale netværk som Facebook
  • -
-

Vi bruger ikke cookies til at:

-
    -
  • Indsamle personligt identificerbare oplysninger (uden din udtrykkelige tilladelse)
  • -
  • Indsamle følsomme oplysninger (uden din udtrykkelige tilladelse)
  • -
  • Videregive data til reklamenetværk
  • -
  • Videregive personligt identificerbare data til tredjeparter
  • -
  • Betale salgskommissioner
  • -
-

Du kan læse mere om alle de cookies, vi bruger, nedenfor.

-

Hvis indstillingerne i den software, du bruger til at se denne hjemmeside (din browser), er indstillet til at acceptere cookies, anser vi det – sammen med din fortsatte brug af vores hjemmeside – for, at du er indforstået hermed. Hvis du ønsker at fjerne eller ikke bruge cookies fra vores side, kan du lære hvordan nedenfor; det vil dog sandsynligvis betyde, at vores side ikke vil fungere som forventet.

- -

Vores egne cookies

-

Vi bruger cookies til at få vores hjemmeside til at fungere, herunder:

-
    -
  • Huske dine søgeindstillinger
  • -
  • Godkendelse til WMS, WFS, WPS via HTTP-forespørgsler
  • -
-

Der er ingen måde at forhindre disse cookies i at blive sat andet end ved ikke at bruge vores side.

-

Tredjeparts-cookies

-

Vores side inkluderer, som de fleste hjemmesider, funktionalitet leveret af tredjeparter. Et almindeligt eksempel er en indlejret YouTube-video. Vores side inkluderer følgende, som bruger cookies:

- -

Cookies fra sociale hjemmesider

-

Så du nemt kan lide eller dele vores indhold på Facebook og Twitter har vi inkluderet delingsknapper på vores side. Cookies sættes af:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • LinkedIn
  • -
  • Google +
  • -
-

Privatlivsmæssige konsekvenser vil variere fra netværk til netværk og afhænger af de privatlivsindstillinger, du har valgt på disse netværk.

-

Sådan slår du cookies fra

-

- Du kan som regel slå cookies fra ved at justere dine browserindstillinger, så den ikke accepterer cookies (lær hvordan her). Det vil dog sandsynligvis begrænse funktionaliteten af vores og en stor del af verdens hjemmesider, da cookies er en standarddel af de fleste moderne hjemmesider. -

-

- Det kan være, at dine bekymringer om cookies vedrører såkaldt "spyware". I stedet for at slå cookies fra i din browser kan du måske finde, at antispyware-software opnår det samme mål ved automatisk at slette cookies, der anses for at være invasive. Læs mere om håndtering af cookies med antispyware-software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-de-DE.html b/web/client/translations/fragments/cookie/cookieDetails-de-DE.html deleted file mode 100644 index f89d3b433d9..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-de-DE.html +++ /dev/null @@ -1,63 +0,0 @@ - - - -
-
-

Cookies Policy

-
-

-In Übereinstimmung mit dem Gesetzesdekret Nr. 196/2003, das das Gesetz Nr. 675/1996 zum Schutz personenbezogener Daten ersetzt, informieren wir Sie, dass Sie mit der weiteren Nutzung dieser Website der Verarbeitung Ihrer persönlichen Daten (sensible Daten werden in keiner Weise behandelt), die GeoSolutions SAS durch elektronische und/oder automatische Tools erworben hat, zustimmen. In jedem Fall ist es möglich, die Rechte zu nutzen, die dem Benutzer in Übereinstimmung mit Gesetzesdekret Nr. 196/2003 (Zugang zu Daten, Aktualisierung, Integration, Löschung) gewährt werden. Durch Klicken auf den Button "Akzeptieren" erklären Sie, dass Sie diesen Text gelesen haben und der Verarbeitung personenbezogener Daten zustimmen. Sie können die Redakteure von GeoSolutions SAS jederzeit bitten, sich von dem Dienst abzumelden, indem Sie den Anweisungen am Ende jeder Nachricht folgen. -

-

Was sind Cookies?

-

Ein Cookie ist eine Textdatei, die eine Website im Browser des Benutzers speichert. Cookies erlauben normalerweise, die vom Benutzer geäußerten Präferenzen zu speichern, um später nicht wieder eingefügt zu werden. Der Browser speichert die Informationen und sendet sie an den Standortserver zurück, wenn der Benutzer diese Website erneut besucht.

-

Unsere Cookies helfen uns:

-
    -
  • Die Website wie erwartet funktionieren zu lassen
  • -
  • Die Einstellungen während und zwischen den Besuchen der Seite zu merken
  • -
  • Die Geschwindigkeit der Website-Sicherheit zu verbessern
  • -
  • Es erlaubt Seiten mit sozialen Netzwerken wie Facebook zu teilen
  • -
-

Cookies werden nicht verwendet um:

-
    -
  • Alle persönlich identifizierbaren Informationen (ohne Ihre Zustimmung) zu sammeln
  • -
  • Alle sensible Daten (ohne explizite Zustimmung) zu sammeln
  • -
  • Daten an Werbenetzwerke zu übergeben
  • -
  • Personenbezogener Daten an Dritte weiterzugeben
  • -
  • Kostenpflichtige Verkaufsaufträge zu tätigen
  • -
-

Hier unten können Sie mehr über alle Cookies die wir verwende, erfahren.

-

Wenn die Einstellungen der Software, die Sie zum Durchsuchen der Website (des Browsers) verwenden, auf das Akzeptieren von Cookies eingestellt sind, akzeptieren wir diese und die fortgesetzte Nutzung unserer Website als Zustimmung zur Verwendung von Cookies. Wenn Sie Cookies von unserer Website entfernen oder nicht verwenden möchten, können Sie dies tun, indem Sie den unten stehenden Anweisungen folgen. Dies könnte jedoch dazu führen, dass unsere Website nicht wie erwartet funktioniert.

- -

Unsere Cookies

-

Wir verwenden Cookies, um bestimmte Funktionen der Website zu gewährleisten, einschließlich:

-
    -
  • Anmeldevorgänge und anschließende Authentifizierung
  • -
  • Authentifizierung für WMS-, WFS-, WPS-Dienste über HTTP-Anfragen
  • -
-

Es gibt keine Möglichkeit zu verhindern, dass diese Cookies gesetzt werden, als unsere Seite nicht zu benutzen.

-

Cookies von Dritten

-

Unsere Website enthält wie viele andere Funktionen und Dienste, die von Dritten angeboten werden. Ein gängiges Beispiel ist die Einbettung eines YouTube-Videos. Unsere Website enthält die folgenden Cookies:

- -

Social Website Cookies

-

Sie können einfach Ihre Meinung äußern oder Inhalte auf Facebook und Twitter teilen (wir haben die Freigabetasten auf unserer Seite eingefügt). Cookies wurden aktiviert für:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

Die Auswirkungen auf die Privatsphäre variieren von sozialen Netzwerken zu sozialen Netzwerken und hängen von den Datenschutzeinstellungen ab, die Sie in diesen Netzwerken gewählt haben.

-

Deaktivieren von Cookies

-

- Normalerweise können Sie Cookies deaktivieren, indem Sie Ihre Browsereinstellungen ändern, um deren Verwendung zu verhindern(siehe hier). Dies wird jedoch wahrscheinlich die Funktionalität unserer sowie vieler Websites auf der ganzen Welt einschränken (Cookies sind ein Standardbestandteil der meisten modernen Websites). -

-

- Es kann sein, dass sich Ihre Cookie-bezogenen Bedenken auf sogenannte "Spyware" beziehen. Anstatt die Cookies in Ihrem Browser zu deaktivieren, können Sie erkennen, dass die Anti-Spyware-Software das gleiche Ziel erreicht, indem Cookies, die als invasiv angesehen werden, automatisch entfernt werden. Bitte lesen wieSie Cookies mit Anti-Spyware-Software verwalten. -

-
-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-en-PT.html b/web/client/translations/fragments/cookie/cookieDetails-en-PT.html deleted file mode 100644 index a7a8cb206b9..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-en-PT.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-en-US.html b/web/client/translations/fragments/cookie/cookieDetails-en-US.html deleted file mode 100644 index a7a8cb206b9..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-en-US.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-es-ES.html b/web/client/translations/fragments/cookie/cookieDetails-es-ES.html deleted file mode 100644 index aeecfdbd50d..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-es-ES.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-fi-FI.html b/web/client/translations/fragments/cookie/cookieDetails-fi-FI.html deleted file mode 100644 index db53b29b373..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-fi-FI.html +++ /dev/null @@ -1,83 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of - personal data, we inform you that by filling out this form and then sending this email message, you consent to - the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions - SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to - Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, - you acknowledge that you have read this text and that you consent to the processing of your personal data. At - any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the - instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best - experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse - websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) - are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine - with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, - however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A - common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we - have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and - will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn - how here.). Doing so - however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies - are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in - your browser you may find that anti-spyware software achieves the same objective by automatically deleting - cookies considered to be invasive. Learn more about managing - cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-fr-FR.html b/web/client/translations/fragments/cookie/cookieDetails-fr-FR.html deleted file mode 100644 index 393eaf6509e..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-fr-FR.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-hr-HR.html b/web/client/translations/fragments/cookie/cookieDetails-hr-HR.html deleted file mode 100644 index 769ab75e0ed..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-hr-HR.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Politika kolačića

-
-

- Sukladno Uredbi br. 196/2003, koja je zamijenila Zakon br. 675/1996 o zaštiti osobnih podataka, obavještavamo Vas da ispunjavanjem ovog obrasca i slanjem ove poruke putem e-pošte pristajete na obradu vaših osobnih podataka (osjetljivi podaci neće biti obrađivani na bilo koji način) koje je GeoSolutions SAS stekao putem elektroničkih i/ili automatiziranih alata. U svakom slučaju možete ostvariti svoja prava koja su Vam dodijeljena sukladno Zakonodavnoj uredbi br. 196/2003 (pristup podacima, ažuriranja, integracija, otkazivanje). Klikom na gumb "Prihvati" potvrđujete da ste pročitali ovaj tekst i da pristajete na obradu vaših osobnih podataka. U bilo kojem trenutku možete zatražiti od osoblja GeoSolutions SAS web stranica da vas odjave sa usluge slijedeći upute na kraju svake poruke. -

-

Kolačići i njihova korist za Vas

-

Naša web stranica koristi kolačiće, kao i gotovo sve web stranice, kako bi Vam pružila najbolje moguće iskustvo. Kolačići su male tekstualne datoteke koje se pohranjuju na vašem računalu ili mobilnom telefonu prilikom pregledavanja web stranica

-

Naši kolačići pomažu kako bi:

-
    -
  • Naše web stranice radile na način na koji Vi očekujete
  • -
  • Zapamtili Vaše postavke za vrijeme i između različitih posjeta
  • -
  • Poboljšali brzinu/sigurnost web stranice
  • -
  • Omogućili dijeljenje stanica sa socijanlnim mrežama kao npr. Facebook
  • -
-

Ne koristimo kolačiće za:

-
    -
  • Prikupljanje bilo kojeg osobnog podatka (bez vašeg izričitog dopuštenja)
  • -
  • Prikupljanje bilo kojeg osjetljivog podatka (bez vašeg izričitog dopuštenja)
  • -
  • Proslijeđivanje podataka nekoj od oglašivačkih mreža
  • -
  • Prenošenje osobnih podataka trećim stranama
  • -
  • Plaćanje provizije
  • -
-

Možete saznati više o svim kolačićima koje koristimo ispod.

-

Ako su postavke vašeg softvera koji koristite za pregled ove web stranice (vaš preglednik) prilagođene za prihvaćanje kolačića, uzimamo to i vašu daljnju upotrebu naše web stranice kao da se podrazumijeva da ste suglasni sa ovakvim načinom rada. Ako želite ukloniti ili ne koristiti kolačiće s naše web stranice, možete saznati kako to učiniti u nastavku, ali to će vjerojatno značiti da naša web stranica neće raditi na način kako biste očekivali.

- -

Naši kolačići

-

Koristimo kolačiće kako bi naša web stranica radila uključujući i:

-
    -
  • Pamćenje Vaših postavki pretraživanja
  • -
  • Korisničke podatke za prijavu na WMS, WFS, WPS putem HTTP zahtjeva
  • -
-

Nema načina da se spriječi postavljanje ovih kolačića, osim da ne koristite našu web stranicu.

-

Kolačići trećih strana

-

Naša stranica, poput većine web stranica, uključuje i funkcionalnosti koju pružaju treće strane. Uobičajeni primjer je ugrađeni YouTube videozapis. Naša web stranica uključuje slijedeće koje koriste kolačiće:

- -

Kolačići socijalnih mreža

-

Na taj način jednostavno možete "lajkati" ili dijeliti naš sadržaj na Facebook i Twitter koje smo uključili u dijeljenje gumba na našoj web stranici. Kolačiće postavljaju:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

Postavke privatnosti u ovim slučajevima će se razlikovati od društvene mreže do društvene mreže i ovisiti će o postavkama privatnosti koje ste odabrali na tim mrežama.

-

Isključivanje kolačića

-

- Kolačiće obično možete isključiti prilagodbom postavki preglednika kako biste spriječili prihvaćanje kolačića (saznajte kako ovdje). Međutim, to će vjerojatno ograničiti funkcionalnost našeg i velikog broja web stranica na svijetu jer su kolačići standardni dio suvremenijih web stranica. -

-

- Može biti da se Vaša zabrinutost oko kolačića odnosi na tzv. "Spyware". Umjesto isključivanja kolačića u vašem pregledniku, možete otkriti da anti-spyware softver postiže isti cilj automatski brišući kolačiće koji se smatraju invazivnim. Saznajte više o upravljanju kolačićima pomoću antispyware softvera. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-is-IS.html b/web/client/translations/fragments/cookie/cookieDetails-is-IS.html deleted file mode 100644 index a7a8cb206b9..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-is-IS.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-it-IT.html b/web/client/translations/fragments/cookie/cookieDetails-it-IT.html deleted file mode 100644 index 327929acbc7..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-it-IT.html +++ /dev/null @@ -1,63 +0,0 @@ - - - -
-
-

Cookies Policy

-
-

- Ai sensi del Decreto Legislativo n ° 196/2003, che ha sostituito la legge n ° 675/1996 in materia di protezione dei dati personali, Vi informiamo che proseguendo la navigazione su questo sito voi acconsentite al trattamento dei vostri dati personali (i dati sensibili non saranno trattati in alcun modo) acquisiti da GeoSolutions SAS tramite strumenti elettronici e/o automatici. In ogni caso, è possibile esercitare i diritti concessi all'utente ai sensi del Decreto Legislativo n ° 196/2003 (accesso ai dati, aggiornamento, integrazione, cancellazione). Facendo clic sul pulsante “Accetto”, si dichiara di aver letto questo testo e di acconsentire al trattamento dei dati personali. In qualsiasi momento è possibile chiedere alla redazione di GeoSolutions SAS del sito di cancellarti dal servizio seguendo le istruzioni alla fine di ogni messaggio. -

-

Cosa sono i Cookies?

-

Un cookie è un file di testo che un sito web salva sul browser del computer dell’utente. Solitamente i cookie consentono di memorizzare le preferenze espresse dall’utente per non dover essere reinserite successivamente. Il browser salva l’informazione e la ritrasmette al server del sito nel momento in cui l’utente visita nuovamente quel sito web.

-

I nostri cookie ci aiutano a:

-
    -
  • Permettere al sito web di lavorare come atteso
  • -
  • Ricordare le impostazioni durante e tra le visite al sito
  • -
  • Migliorare la velocità sicurezza del sito
  • -
  • Permette di condividere le pagine con i social network come Facebook
  • -
-

Non viene fatto uso di cookies per:

-
    -
  • Raccogliere tutte le informazioni di identificazione personale (senza il vostro consenso)
  • -
  • Raccogliere tutte le informazioni sensibili (senza il tuo esplicito consenso)
  • -
  • Passare i dati alle reti pubblicitarie
  • -
  • Passare dati personali a terze parti
  • -
  • Commissioni di vendita a pagamento
  • -
-

Potete saperne di più su tutti i cookies che utilizziamo qui sotto.

-

Se le impostazioni del software che si sta utilizzando per la navigazione del sito (il browser) sono regolati per accettare i cookies prendiamo questo, e l'uso continuato del nostro sito web, a significare che si acconsente all'utilizzo di cookies. Se si desidera rimuovere o non usare i cookies dal nostro sito lo si può fare seguendo le indicazioni riportate di seguito, così facendo tuttavia il nostro sito potrebbe non funzionare come ci si aspetterebbe.

- -

I nostri Cookies

-

Utilizziamo i cookie per garantire determinate funzionalità del sito web tra cui:

-
    -
  • Operazioni di Login e successive autenticazioni
  • -
  • Autenticazione a servizi WMS, WFS, WPS attraverso richieste HTTP
  • -
-

Non è possibile prevenire che questi cookies There is no way to prevent these cookies being set other than to not use our site.

-

Cookies di Terze Parti

-

Il nostro sito, come molti, include funzionalità e servizi offerti da terze parti. Un comune esempio è l'embed di un video di YouTube. Il nostro sito include i seguenti cookie:

- -

Social Website Cookies

-

Tu puoi facilmente esprimere il tuo gradimento o condividere alcuni contenuti su Facebook e Twitter (abbiamo incluso i pulsanti di condivisione sul nostro sito). I cookies sono stati abilitati per:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

Le implicazioni di privacy su questo variano da social network a social network e dipenderanno dalle impostazioni di privacy che avete scelto su queste reti.

-

Disabilitare i Cookies

-

- Di solito è possibile disattivare i cookies modificando le impostazioni del browser per impedire l'uso degli stessi (vedi qui. In questo modo però probabilmente si limiteranno le funzionalità del nostro come di molti dei siti web di tutto il mondo (i cookie sono una componente standard della maggior parte dei siti web moderni). -

-

- Potrebbe essere che le tue preoccupazioni relativi ai cookie riguardino i cosiddetti "spyware". Piuttosto che disattivare i cookie nel tuo browser puoi sapere che il software anti-spyware raggiunge lo stesso obiettivo eliminando automaticamente i cookie considerati invasivi. Leggi come gestire i cookie con software antispyware. -

-
-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-nl-NL.html b/web/client/translations/fragments/cookie/cookieDetails-nl-NL.html deleted file mode 100644 index a7a8cb206b9..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-nl-NL.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-pt-BR.html b/web/client/translations/fragments/cookie/cookieDetails-pt-BR.html deleted file mode 100644 index e4d16ed5a79..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-pt-BR.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Política de Cookies

-
-

- Em conformidade com o Decreto-Lei nº 196/2003, que substituiu a Lei nº 675/1996 relativa à proteção de dados pessoais, informamos que, ao preencher este formulário e enviar esta mensagem de e-mail, você consente com o tratamento dos seus dados pessoais (dados sensíveis não serão tratados de forma alguma) obtidos pela GeoSolutions SAS por meio de ferramentas eletrônicas e/ou automatizadas. Em qualquer caso, você poderá exercer os seus direitos garantidos pelo Decreto-Lei nº 196/2003 (acesso, atualização, integração e cancelamento dos dados). Ao clicar no botão “Aceitar”, você reconhece que leu este texto e que consente com o tratamento dos seus dados pessoais. A qualquer momento, você poderá solicitar à equipe do site da GeoSolutions SAS o cancelamento da sua inscrição no serviço, seguindo as instruções no final de cada mensagem. -

-

Cookies e seus benefícios

-

Nosso site utiliza cookies, como quase todos os sites, para proporcionar a melhor experiência possível. Cookies são pequenos arquivos de texto que são armazenados no seu computador ou celular quando você navega em sites.

-

Nossos cookies nos ajudam a:

-
    -
  • Fazer com que nosso site funcione como você espera
  • -
  • Lembrar das suas configurações durante e entre as visitas
  • -
  • Melhorar a velocidade/segurança do site
  • -
  • Permitir compartilhar páginas em redes sociais como o Facebook
  • -
-

Não utilizamos cookies para:

-
    -
  • Coletar qualquer informação pessoal identificável (sem sua permissão expressa)
  • -
  • Coletar qualquer informação sensível (sem sua permissão expressa)
  • -
  • Transmitir dados para redes de publicidade
  • -
  • Transmitir dados de identificação pessoal a terceiros
  • -
  • Pagar comissões de vendas
  • -
-

Você pode saber mais sobre todos os cookies que utilizamos abaixo.

-

Se as configurações do seu navegador estiverem ajustadas para aceitar cookies, consideramos que você concorda com o uso de cookies ao continuar navegando em nosso site. Caso deseje remover ou desativar os cookies do nosso site, você pode aprender como fazê-lo abaixo. No entanto, isso provavelmente fará com que o site não funcione como esperado.

- -

Nossos próprios cookies

-

Utilizamos cookies para que nosso site funcione, incluindo:

-
    -
  • Relembrar suas configurações de pesquisa
  • -
  • Autenticação em WMS, WFS e WPS via requisições HTTP
  • -
-

Não há como impedir a configuração desses cookies, a não ser não usar nosso site.

-

Cookies de terceiros

-

Nosso site, como a maioria dos sites, inclui funcionalidades fornecidas por terceiros. Um exemplo comum é um vídeo do YouTube incorporado. Nosso site inclui os seguintes recursos que utilizam cookies:

- -

Cookies de redes sociais

-

Para que você possa curtir ou compartilhar facilmente nosso conteúdo em redes sociais como Facebook e Twitter, incluímos botões de compartilhamento em nosso site. Os cookies são definidos por:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

As implicações em privacidade variam de rede social para rede social e dependem das configurações de privacidade escolhidas em cada uma delas.

-

Desativando cookies

-

- Geralmente, você pode desativar os cookies ajustando as configurações do seu navegador para impedir que ele os aceite (saiba como aqui). No entanto, fazer isso provavelmente limitará a funcionalidade do nosso site e de grande parte dos sites da internet, já que os cookies são um componente padrão da maioria dos sites modernos. -

-

- É possível que suas preocupações com cookies estejam relacionadas aos chamados "spywares". Em vez de desativar os cookies no seu navegador, você pode usar um software anti-spyware, que atinge o mesmo objetivo excluindo automaticamente os cookies considerados invasivos. Saiba mais sobre como gerenciar cookies com software anti-spyware. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-sk-SK.html b/web/client/translations/fragments/cookie/cookieDetails-sk-SK.html deleted file mode 100644 index ecfa5d49f5f..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-sk-SK.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

Zásady používania cookies

-
-

- V súlade so zákonnou vyhláškou n° 196/2003, ktorá nahradila zákon n° 675/1996 týkajúci sa ochrany osobných údajov, vám oznamujeme, že vyplnením tohto formulára a následným odoslaním tohto emailu, súhlasíte so spracovaním vašich osobných údajov (citlivé údaje nebudú nijako spracované) získaných spoločnosťou GeoSolutions SAS prostredníctvom elektronických a/alebo automatizovaných nástrojov. V každom prípade môžete uplatniť svoje práva, ktoré vám boli udelené podľa legislatívneho dekrétu n° 196/2003 (prístup k údajom, aktualizácia, integrácia, zrušenie). Kliknutím na tlačidlo „Prijať“, potvrdzujete, že ste si prečítali tento text a že súhlasíte so spracovaním vašich osobných údajov. Kedykoľvek môžete požiadať zamestnancov webovej stránky GeoSolutions SAS, aby vás odhlásili zo služby podľa pokynov na konci každej správy. -

-

Cookies a ako môžu byť nápomocné

-

Naša webová stránka používa cookies, ako takmer všetky webové stránky, aby mohlo byť jej prehliadanie a používanie čo najlepšie. Cookies sú malé textové súbory, ktoré sú umiestnené vo vašom počítači alebo mobilnom telefóne pri prehliadaní webových stránok.

-

Naše cookies nám pomáhajú:

-
    -
  • K tomu, aby web fungoval tak ako má
  • -
  • Uložiť si nastavenia stránky počas jej používania ale aj mimo nej. Je teda možné ich znovu obnoviť.
  • -
  • Zvýšiť rýchlosť/bezpečnosť stránok
  • -
  • Umožniť zdieľanie stránky na sociálnych sieťach, ako napríklad Facebook
  • -
-

Nepoužívame cookies k:

-
    -
  • Zberu akýchkoľvek identifikačných údajov (bez vášho výslovného súhlasu)
  • -
  • Zberu akýchkoľvek citlivých informácií (bez vášho výslovného súhlasu)
  • -
  • Odosielaniu dát pre reklamné účely
  • -
  • Odosielaniu identifikačných údajov tretím stranám
  • -
  • Plateniu provízií z predaja
  • -
-

Nižšie sa môžete dozvedieť viac o všetkých cookies, ktoré používame.

-

Ak sú nastavenia vášho softvéru, ktorý používate na zobrazenie tejto webovej stránky (váš prehliadač), upravené tak, aby akceptovali cookies, akcetupjeme to, a vaše ďalšie používanie našej webovej stránky znamená, že s tým súhlasíte. Ak si želáte odstrániť alebo nepoužívať cookies z našich stránok, nižšie sa môžete dozvedieť, ako to urobiť, avšak pravdepodobne to bude znamenať, že náš web nebude fungovať tak, ako by ste očakávali.

- -

Naše vlastné cookies

-

Aby naša webová stránka fungovala, používame cookies na:

-
    -
  • Zapamätanie si nastavení vyhľadávania
  • -
  • Autentifikáciu WMS, WFS, WPS pomocou funkcie HTTP request
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Cookies tretích strán

-

Naša webová stránka, ako väčšina webových stránok, používa funkcie poskytované tretími stranami. Bežným príkladom je vložené video z YouTube. Náš web obsahuje nasledujúce prvky, ktoré používajú cookies:

- -

Cookies sociálnych sietí

-

Pre pohodlné zdieľanie nášho obsahu sme pridali funkciu zdieľania cez tlačidlá sociálnych sietí, ako napríklad Facebook a Twitter. Cookies nastavujú:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

Spôsoby ochrany osobných údajov sa budú líšiť v závislosti od sociálnej siete a budú závisieť od nastavení ochrany osobných údajov, ktoré ste v týchto sieťach vybrali.

-

Vypnutie cookies

-

- Cookies môžete vypnúť úpravou nastavení prehliadača tak, aby neprijímal cookies (návod k tomuto nastaveniu je tu.). To však pravdepodobne obmedzí funkčnosť našich a veľkej časti svetových webových stránok, pretože súbory cookie sú štandardnou súčasťou väčšiny moderných webových stránok. -

- Je možné, že obavy zo súborov cookies vyvolal práve "spyware". Namiesto ich úplného vypnutia sa však odporúča použiť anti-spyware softvér, ktorý zabezpečuje ochranu a odstránenie takých cookies, ktoré identifikuje ako invazívne. Viac informácií na: správa súborov cookie pomocou anti-spyware softvéru. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-sv-SE.html b/web/client/translations/fragments/cookie/cookieDetails-sv-SE.html deleted file mode 100644 index 557bb721b13..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-sv-SE.html +++ /dev/null @@ -1,56 +0,0 @@ - - - -
-

Policy för cookies

-
-

- I enlighet med lag nr 196/2003, som ersatte lag nr 675/1996 om skydd av personuppgifter, informerar vi dig om att du genom att fylla i detta formulär och sedan skicka detta e-postmeddelande godkänner behandlingen av dina personuppgifter (känslig information kommer inte att behandlas på något sätt) som förvärvats av GeoSolutions SAS via elektroniska och/eller automatiserade verktyg. Under alla omständigheter kan du utöva dina rättigheter som beviljats ​​dig enligt lag nr 196/2003 (datatillgång, uppdateringar, integration, avbokning). Genom att klicka på knappen "Godkänn" bekräftar du att du har läst den här texten och att du godkänner behandlingen av dina personuppgifter. Du kan när som helst be personalen på GeoSolutions SAS webbplats att avsluta prenumerationen på tjänsten genom att följa instruktionerna i slutet av varje meddelande. -

-

Cookies och hur de gynnar dig

-

Som nästan alla webbplatser använder denna webbplats cookies. Cookies är små textfiler som placeras på din dator eller mobiltelefon när du surfar på webbplatser.

-

Cookies hjälper oss med att:

-
    -
  • få vår webbplats att fungera som du förväntar dig
  • -
  • komma ihåg dina inställningar under och mellan besöken
  • -
  • förbättra webbplatsens hastighet/säkerhet
  • -
  • låta dig dela sidor med sociala nätverk som Facebook
-

Cookies används inte för att:

-
    -
  • samla in personlig information (utan ditt uttryckliga tillstånd)
  • -
  • samla in känslig information (utan ditt uttryckliga tillstånd)
  • -
  • skicka data till annonsnätverk
  • -
  • skicka personligt identifierbar information till tredje part
  • -
  • betala försäljningsprovisioner
-

Du kan lära dig mer om alla cookies vi använder nedan.

-

Om inställningarna på den programvara som du använder för att visa denna webbplats (din webbläsare) justeras för att acceptera cookies förstår vi detta och tolkar din fortsatta användning av vår webbplats som att du godkänner våra cookies. Om du vill ta bort eller inte använda cookies från vår webbplats kan du lära dig hur du gör detta nedan, men det kommer sannolikt att innebära att vår webbplats inte fungerar som du förväntar dig.

- -

Våra cookies

-

Vi använder cookies för att få vår webbplats att fungera plus:

-
    -
  • att komma ihåg dina sökinställningar
  • -
  • att autentisera för WMS, WFS, WPS via HTTP -förfrågningar
-

Det finns inget sätt att förhindra att dessa cookies sätts utom att inte använda vår webbplats.

-

Cookies från tredje part

-

Vår webbplats, liksom de flesta webbplatser, innehåller funktioner som tillhandahålls av tredje part. Ett vanligt exempel är en inbäddad YouTube -video. Vår webbplats innehåller följande cookies-användare:

- -

Cookies för sociala media

-

För att du enkelt ska kunna gilla eller dela vårt innehåll på Facebook och Twitter finns det . Vi har inkluderat delningsknappar på vår webbplats. Cookies ställs in av:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

Hur detta påverkar din integritet varierar mellan sociala nätverk och är beroende av de sekretessinställningar du har valt på dessa nätverk.

-

Stänga av cookies

-

-Du kan vanligtvis stänga av cookies genom att justera dina webbläsarinställningar så att de inte accepterar cookies (läs hur här .). Att göra det kommer dock sannolikt att begränsa funktionaliteten hos våra och en stor del av världens webbplatser eftersom cookies är standard på de flesta moderna webbplatser.

-

-Det kan vara så att du oroar dig för att cookies är relaterade till så kallade "spionprogram". I stället för att stänga av cookies i din webbläsare kan du upptäcka att antispionprogramvara gör samma nytta genom att automatiskt radera cookies som anses vara invasiva. Läs mer om hantering av cookies med antispionprogram .

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-vi-VN.html b/web/client/translations/fragments/cookie/cookieDetails-vi-VN.html deleted file mode 100644 index a7a8cb206b9..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-vi-VN.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/translations/fragments/cookie/cookieDetails-zh-ZH.html b/web/client/translations/fragments/cookie/cookieDetails-zh-ZH.html deleted file mode 100644 index a7a8cb206b9..00000000000 --- a/web/client/translations/fragments/cookie/cookieDetails-zh-ZH.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -
-

Cookies Policy

-
-

- In accordance with Law Decree n° 196/2003, which replaced the Law n° 675/1996 concerning the protection of personal data, we inform you that by filling out this form and then sending this email message, you consent to the processing of your personal data (sensitive data will not be processed in any way) acquired by GeoSolutions SAS via electronic and/or automated tools. In any case, you can exercise your rights granted to you pursuant to Legislative Decree n° 196/2003 (data access, updates, integration, cancellation). Clicking the “Accept” button, you acknowledge that you have read this text and that you consent to the processing of your personal data. At any time you can ask the staff of GeoSolutions SAS web site to unsubscribe you from the service by following the instructions at the end of each message. -

-

Cookies and how they Benefit You

-

Our website uses cookies, as almost all websites do, to help provide you with the best experience we can. Cookies are small text files that are placed on your computer or mobile phone when you browse websites

-

Our cookies help us:

-
    -
  • Make our website work as you’d expect
  • -
  • Remember your settings during and between visits
  • -
  • Improve the speed/security of the site
  • -
  • Allow you to share pages with social networks like Facebook
  • -
-

We do not use cookies to:

-
    -
  • Collect any personally identifiable information (without your express permission)
  • -
  • Collect any sensitive information (without your express permission)
  • -
  • Pass data to advertising networks
  • -
  • Pass personally identifiable data to third parties
  • -
  • Pay sales commissions
  • -
-

You can learn more about all the cookies we use below.

-

If the settings on your software that you are using to view this website (your browser) are adjusted to accept cookies we take this, and your continued use of our website, to mean that you are fine with this. Should you wish to remove or not use cookies from our site you can learn how to do this below, however doing so will likely mean that our site will not work as you would expect.

- -

Our own cookies

-

We use cookies to make our website work including:

-
    -
  • Remembering your search settings
  • -
  • Authentication to WMS, WFS, WPS via HTTP requests
  • -
-

There is no way to prevent these cookies being set other than to not use our site.

-

Third Party Cookies

-

Our site, like most websites, includes functionality provided by third parties. A common example is an embedded YouTube video. Our site includes the following which use cookies:

- -

Social Website Cookies

-

So you can easily like or share our content on the likes of Facebook and Twitter we have included sharing buttons on our site. Cookies are set by:

-
    -
  • Twitter
  • -
  • Facebook
  • -
  • Linkedin
  • -
  • Google +
  • -
-

The privacy implications on this will vary from social network to social network and will be dependent on the privacy settings you have chosen on these networks.

-

Turning Cookies Off

-

- You can usually switch cookies off by adjusting your browser settings to stop it from accepting cookies (learn how here.). Doing so however will likely limit the functionality of our’s and a large proportion of the world’s websites as cookies are a standard part of most modern websites. -

-

- It may be that you concerns around cookies relate to so called “spyware”. Rather than switching off cookies in your browser you may find that anti-spyware software achieves the same objective by automatically deleting cookies considered to be invasive. Learn more about managing cookies with antispyware software. -

-
- - diff --git a/web/client/unsupportedBrowser.html b/web/client/unsupportedBrowser.html index fc8aff38ef9..e23777ce856 100644 --- a/web/client/unsupportedBrowser.html +++ b/web/client/unsupportedBrowser.html @@ -10,7 +10,7 @@ margin: 0; } #container { - font-family: 'Noto Sans', sans-serif; + font-family: 'Noto Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; display: flex; flex-direction: column; align-items: center; @@ -20,8 +20,6 @@ justify-content: center; } - -
diff --git a/web/client/utils/ConsentManager.js b/web/client/utils/ConsentManager.js new file mode 100644 index 00000000000..9bcb2cacbb7 --- /dev/null +++ b/web/client/utils/ConsentManager.js @@ -0,0 +1,49 @@ +/* + * Copyright 2026, GeoSolutions Sas. + * All rights reserved. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ +import { normalizeChoice } from './PrivacyChoices'; + +// Integrations register inert factories: no optional work at module load time. +// Each start must return a synchronous teardown and honour AbortSignal. +export const createConsentManager = () => { + const integrations = new Map(); + let config; + let choice; + const allowed = category => config?.enabled && normalizeChoice(choice, config)?.categories[category] === true; + const stop = item => { + item.controller?.abort(); + try { item.cleanup?.(); } catch (error) { console.error('Optional integration teardown failed', item.id, error); } finally { item.controller = null; item.cleanup = null; } + }; + const reconcile = () => integrations.forEach(item => { + if (!allowed(item.category)) { stop(item); return; } + if (!item.controller) { + item.controller = new AbortController(); + try { + const cleanup = item.start({signal: item.controller.signal, isAllowed: () => !!allowed(item.category)}); + if (typeof cleanup !== 'function') throw new Error('Consent integration must return teardown'); + item.cleanup = cleanup; + } catch (error) { + stop(item); + console.error('Optional integration could not start', item.id, error); + } + } + }); + return { + update: (nextConfig, nextChoice) => { config = nextConfig; choice = nextChoice; reconcile(); }, + register: (id, category, start) => { + if (integrations.has(id) || typeof start !== 'function' + || !['functional', 'statistics', 'marketing'].includes(category)) throw new Error('Invalid consent integration'); + const item = {id, category, start}; + integrations.set(id, item); + reconcile(); + return () => { stop(item); integrations.delete(id); }; + }, + stop: () => { integrations.forEach(stop); choice = null; }, + isAllowed: category => !!allowed(category) + }; +}; +export const consentManager = createConsentManager(); +export const registerConsentIntegration = (...args) => consentManager.register(...args); diff --git a/web/client/utils/CookieNoticeUtils.js b/web/client/utils/CookieNoticeUtils.js new file mode 100644 index 00000000000..9c3fd386aeb --- /dev/null +++ b/web/client/utils/CookieNoticeUtils.js @@ -0,0 +1,56 @@ +/* + * Copyright 2026, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { getApi, getItemKey } from '../api/userPersistedStorage'; +import { privacyConfig, readPrivacyChoice, categoryIds, removePrivacyStorageItem } from './PrivacyChoices'; + +export const privacyNoticeKey = () => getItemKey('privacy', 'notice'); + +// Dismissing necessary-only information is distinct from granting consent. +export const isPrivacyNoticeAcknowledged = (config, now = Date.now()) => { + if (!config?.enabled) return false; + let raw; + try { raw = getApi().getItem(privacyNoticeKey()); } catch (e) { return false; } + let valid = false; + try { + const value = typeof raw === 'string' ? JSON.parse(raw) : raw; + valid = value?.version === 1 && value.policyVersion === config.policyVersion + && Number.isFinite(value.dismissedAt) && Number.isFinite(value.expiresAt) + && value.dismissedAt <= now && value.expiresAt > now + && value.expiresAt <= value.dismissedAt + (config.retentionDays || 180) * 86400000; + } catch (e) { /* Malformed records do not acknowledge the information. */ } + if (!valid) removePrivacyStorageItem(privacyNoticeKey(), raw); + return !!valid; +}; + +export const acknowledgePrivacyNotice = (config, now = Date.now()) => { + try { + getApi().setItem(privacyNoticeKey(), JSON.stringify({version: 1, + policyVersion: config.policyVersion, dismissedAt: now, + expiresAt: now + (config.retentionDays || 180) * 86400000})); + return true; + } catch (e) { return false; } +}; + +/** + * Tells whether the privacy panel can stay closed on the first visit. + * With the privacy configuration disabled there is nothing to show. + * @param {object} config privacy configuration + * @returns {boolean} true when the panel does not need to open + */ +export const isCookieNoticeAcknowledged = (config = privacyConfig()) => { + if (!config?.enabled) return true; + // A previous "Accept" only acknowledged the old notice; it never grants + // consent to a newly configured optional resource or a new policy version. + [getItemKey('cookie', 'approved'), 'cookies-policy-approved'].forEach(key => { + try { removePrivacyStorageItem(key, getApi().getItem(key)); } catch (e) { /* Storage may be unavailable. */ } + }); + const choice = readPrivacyChoice(config); + const notice = isPrivacyNoticeAcknowledged(config); + return categoryIds(config).length ? !!choice : notice; +}; diff --git a/web/client/utils/FileUtils.js b/web/client/utils/FileUtils.js index 947653c66d8..269fee6482e 100644 --- a/web/client/utils/FileUtils.js +++ b/web/client/utils/FileUtils.js @@ -8,7 +8,6 @@ import FileSaver from 'file-saver'; -import { DxfParser } from 'dxf-parser'; import toBlob from 'canvas-to-blob'; import shp from 'shpjs'; import tj from '@mapbox/togeojson'; @@ -135,8 +134,42 @@ export const readGeoJson = function(file, warnings = false) { reader.readAsText(file); }); }; +const LOG_LEVEL_KEY = 'loglevel'; +let dxfParserLoader; +/** + * Loads dxf-parser on demand. When its module is evaluated, dxf-parser saves its log level + * in the browser (localStorage `loglevel`, or a cookie when localStorage is not available). + * The parser does not need it, so the previous browser storage is restored after loading. + * @returns {Promise} resolves with the `DxfParser` class + */ +const loadDxfParser = () => { + if (!dxfParserLoader) { + let previousLevel = null; + try { + previousLevel = window.localStorage.getItem(LOG_LEVEL_KEY); + } catch (e) { /* Storage may be unavailable. */ } + const hadCookie = document.cookie.split(/;\s*/).some(cookie => cookie.indexOf(LOG_LEVEL_KEY + '=') === 0); + dxfParserLoader = import('dxf-parser').then(({ DxfParser }) => { + try { + if (previousLevel === null) { + window.localStorage.removeItem(LOG_LEVEL_KEY); + } else { + window.localStorage.setItem(LOG_LEVEL_KEY, previousLevel); + } + } catch (e) { /* Storage may be unavailable. */ } + if (!hadCookie) { + document.cookie = LOG_LEVEL_KEY + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT'; + } + return DxfParser; + }).catch(e => { + dxfParserLoader = null; + throw e; + }); + } + return dxfParserLoader; +}; export const readDxf = function(file) { - return new Promise((resolve, reject) => { + return loadDxfParser().then(DxfParser => new Promise((resolve, reject) => { let reader = new FileReader(); reader.onload = function() { try { @@ -151,7 +184,7 @@ export const readDxf = function(file) { reject(reader.error.name); }; reader.readAsText(file); - }); + })); }; export const readWMC = function(file) { return new Promise((resolve, reject) => { diff --git a/web/client/utils/PrivacyChoices.js b/web/client/utils/PrivacyChoices.js new file mode 100644 index 00000000000..3458b91a7ce --- /dev/null +++ b/web/client/utils/PrivacyChoices.js @@ -0,0 +1,111 @@ +/* + * Copyright 2026, GeoSolutions Sas. + * All rights reserved. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ +import { createSelector } from 'reselect'; +import ConfigUtils from './ConfigUtils'; +import { getApi, getItemKey } from '../api/userPersistedStorage'; + +export const privacyConfig = () => ConfigUtils.getConfigProp('privacy') || null; +export const privacyChoiceKey = () => getItemKey('privacy', 'choices'); +export const categoryIds = config => (config?.categories || []).filter(c => + ['functional', 'statistics', 'marketing'].includes(c.id)).map(c => c.id); + +export const normalizeChoice = (value, config, now = Date.now()) => { + if (!config || !value || value.version !== 2 || value.policyVersion !== config.policyVersion + || !value.categories || typeof value.categories !== 'object' || Array.isArray(value.categories) + || !Number.isFinite(value.updatedAt) || !Number.isFinite(value.expiresAt) + || value.updatedAt > now || value.expiresAt <= now + || value.expiresAt > value.updatedAt + (config.retentionDays || 180) * 86400000) return null; + return {version: 2, policyVersion: config.policyVersion, + updatedAt: value.updatedAt, expiresAt: value.expiresAt, + categories: Object.fromEntries(categoryIds(config).map(id => [id, value.categories[id] === true]))}; +}; +export const makePrivacyChoice = (config, selected = {}, now = Date.now()) => normalizeChoice({ + version: 2, policyVersion: config.policyVersion, updatedAt: now, + expiresAt: now + (config.retentionDays || 180) * 86400000, categories: selected +}, config, now); +// Compare before removal so cleanup cannot erase a newer choice from another tab. +// Only explicitly named privacy/legacy-notice keys are passed by callers. +export const removePrivacyStorageItem = (key, previousValue) => { + if (previousValue === null || previousValue === undefined) return; + try { + if (getApi().getItem(key) === previousValue) getApi().removeItem(key); + } catch (e) { /* Storage denial must not interrupt the application. */ } +}; +export const readPrivacyChoice = (config = privacyConfig()) => { + if (!config?.enabled) return null; + let raw; + try { raw = getApi().getItem(privacyChoiceKey()); } catch (e) { return null; } + let choice = null; + try { + if (categoryIds(config).length) { + choice = normalizeChoice(typeof raw === 'string' ? JSON.parse(raw) : raw, config); + } + } catch (e) { /* Malformed records cannot grant consent. */ } + if (!choice) removePrivacyStorageItem(privacyChoiceKey(), raw); + return choice; +}; +export const persistPrivacyChoice = choice => { + try { + getApi().setItem(privacyChoiceKey(), JSON.stringify(choice)); + return true; + } catch (e) { return false; } +}; +export const policyLinkKeys = ['cookie', 'privacy', 'terms']; +/** + * Returns the url of a policy page for the current locale. + * A link can be a single url or an object of urls by locale; when the locale is missing + * the first configured url is used. + * @param {object} config privacy configuration + * @param {string} key one of `cookie`, `privacy`, `terms` + * @param {string} locale current locale, e.g. `it-IT` + * @returns {string} the url, or undefined when not configured + */ +export const getPolicyLink = (config, key, locale) => { + const link = config?.links?.[key]; + if (!link || typeof link === 'string') return link || undefined; + return link[locale] || Object.values(link).find(Boolean); +}; +export const hasPrivacyLinks = config => policyLinkKeys.some(key => !!getPolicyLink(config, key)); +/** + * Example policy pages shipped with MapStore. They are linked only when no page is configured, + * and each page tells the operator how to replace it. + */ +export const templatePolicyLinks = { + cookie: 'product/assets/privacy/cookie.html', + privacy: 'product/assets/privacy/privacy.html', + terms: 'product/assets/privacy/terms.html' +}; +export const policyPagesDocsUrl = 'https://docs.mapstore.geosolutionsgroup.com/en/latest/developer-guide/privacy-settings/#policy-pages'; +export const usesTemplatePolicyLinks = config => config?.links === templatePolicyLinks; +const withTemplateLinks = config => config?.enabled && !hasPrivacyLinks(config) + ? {...config, links: templatePolicyLinks} + : config; +// Keys of the privacy configuration that can be provided at runtime. +const runtimePrivacyKeys = ['enabled', 'policyVersion', 'retentionDays', 'categories', 'links']; +/** + * Returns the privacy configuration in use. + * When `localConfig.json` does not configure `privacy.links`, the configuration can be provided + * at runtime, for example by an extension, with `setControlProperty('privacy', 'defaults', config)`. + * The runtime keys `policyVersion`, `retentionDays`, `categories` and `links` replace the ones of + * `localConfig.json`; `enabled` is used only when `localConfig.json` has no `privacy` section. + * When neither configures a page, the links point to the template pages (`templatePolicyLinks`). + * Every reader of the privacy configuration must use this selector, so that the stored choices + * are always checked against the same policy version. + * @param {object} state application state + * @returns {object} the privacy configuration, or null when not configured + */ +export const privacyConfigSelector = createSelector( + () => privacyConfig(), + state => state?.controls?.privacy?.defaults, + (config, defaults) => { + if (!defaults || hasPrivacyLinks(config)) return withTemplateLinks(config); + const runtime = Object.fromEntries(runtimePrivacyKeys + .filter(key => defaults[key] !== undefined && (key !== 'enabled' || !config)) + .map(key => [key, defaults[key]])); + return withTemplateLinks({...config, ...runtime}); + } +); diff --git a/web/client/utils/__tests__/FileUtilsDxf-test.js b/web/client/utils/__tests__/FileUtilsDxf-test.js new file mode 100644 index 00000000000..bbabb20a327 --- /dev/null +++ b/web/client/utils/__tests__/FileUtilsDxf-test.js @@ -0,0 +1,28 @@ +/* + * Copyright 2026, GeoSolutions Sas. + * All rights reserved. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ +import expect from 'expect'; +import { readDxf } from '../FileUtils'; + +const DXF = '0\nSECTION\n2\nENTITIES\n0\nPOINT\n10\n1\n20\n2\n30\n0\n0\nENDSEC\n0\nEOF\n'; +const hasLogLevelCookie = () => document.cookie.split(/;\s*/).some(cookie => cookie.indexOf('loglevel=') === 0); + +describe('FileUtils readDxf browser storage', () => { + it('loading the application does not store the dxf-parser log level', () => { + expect(window.localStorage.getItem('loglevel')).toBe(null); + expect(hasLogLevelCookie()).toBe(false); + }); + it('reads a DXF file and leaves no log level in the browser', (done) => { + readDxf(new File([DXF], 'point.dxf')).then(dxf => { + expect(dxf.entities.length).toBe(1); + expect(dxf.entities[0].type).toBe('POINT'); + expect(dxf.entities[0].position).toEqual({x: 1, y: 2, z: 0}); + expect(window.localStorage.getItem('loglevel')).toBe(null); + expect(hasLogLevelCookie()).toBe(false); + done(); + }).catch(done); + }); +}); diff --git a/web/client/utils/__tests__/PrivacyChoices-test.js b/web/client/utils/__tests__/PrivacyChoices-test.js new file mode 100644 index 00000000000..5868842e494 --- /dev/null +++ b/web/client/utils/__tests__/PrivacyChoices-test.js @@ -0,0 +1,265 @@ +/* + * Copyright 2026, GeoSolutions Sas. + * All rights reserved. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ +import expect from 'expect'; +import { normalizeChoice, makePrivacyChoice, readPrivacyChoice, persistPrivacyChoice, privacyChoiceKey, getPolicyLink, hasPrivacyLinks, privacyConfigSelector, templatePolicyLinks } from '../PrivacyChoices'; +import ConfigUtils from '../ConfigUtils'; +import { createConsentManager } from '../ConsentManager'; +import { setApi, getApi, getItemKey, addApi } from '../../api/userPersistedStorage'; +import { privacyNoticeKey, acknowledgePrivacyNotice, isPrivacyNoticeAcknowledged, isCookieNoticeAcknowledged } from '../CookieNoticeUtils'; +const config = {enabled: true, policyVersion: 'test', retentionDays: 180, categories: [{id: 'functional'}, {id: 'statistics'}]}; + +describe('Consent lifecycle', () => { + it('shows necessary-only information on first visit and remembers dismissal separately from consent', () => { + setApi('memoryStorage'); + const necessary = {...config, categories: []}; + getApi().removeItem(privacyNoticeKey()); + getApi().removeItem(privacyChoiceKey()); + expect(isCookieNoticeAcknowledged(necessary)).toBe(false); + expect(acknowledgePrivacyNotice(necessary)).toBe(true); + expect(isCookieNoticeAcknowledged(necessary)).toBe(true); + expect(readPrivacyChoice(necessary)).toBe(null); + expect(isCookieNoticeAcknowledged(config)).toBe(false); + const record = JSON.parse(getApi().getItem(privacyNoticeKey())); + expect(isPrivacyNoticeAcknowledged(necessary, record.expiresAt)).toBe(false); + expect(getApi().getItem(privacyNoticeKey())).toBe(null); + acknowledgePrivacyNotice(necessary); + expect(isPrivacyNoticeAcknowledged({...necessary, policyVersion: 'next'})).toBe(false); + expect(getApi().getItem(privacyNoticeKey())).toBe(null); + getApi().setAccessDenied(true); + expect(isPrivacyNoticeAcknowledged(necessary)).toBe(false); + expect(acknowledgePrivacyNotice(necessary)).toBe(false); + getApi().setAccessDenied(false); + getApi().removeItem(privacyNoticeKey()); + setApi('localStorage'); + }); + it('rejects old notices, changed policy, expired records and non-boolean grants', () => { + expect(normalizeChoice(true, config)).toBe(null); + expect(normalizeChoice({version: 1, categories: {functional: true}}, config)).toBe(null); + const choice = makePrivacyChoice(config, {functional: 'true', statistics: true}, 1000); + expect(choice.categories).toEqual({functional: false, statistics: true}); + expect(normalizeChoice(choice, {...config, policyVersion: 'new'}, 1000)).toBe(null); + expect(normalizeChoice(choice, config, choice.expiresAt)).toBe(null); + }); + it('does not run integrations before choice or after refusal, starts only selected categories and tears down on withdrawal', () => { + const manager = createConsentManager(); + let signal; let count = 0; let stopped = 0; + manager.register('fixture', 'functional', context => { signal = context.signal; count++; return () => { stopped++; }; }); + manager.update(config, null); + manager.update(config, makePrivacyChoice(config, {})); + expect(count).toBe(0); + manager.update(config, makePrivacyChoice(config, {statistics: true})); + expect(count).toBe(0); + manager.update(config, makePrivacyChoice(config, {functional: true})); + manager.update(config, makePrivacyChoice(config, {functional: true})); + expect(count).toBe(1); + expect(signal.aborted).toBe(false); + manager.update(config, makePrivacyChoice(config, {})); + expect(signal.aborted).toBe(true); + expect(stopped).toBe(1); + expect(manager.isAllowed('functional')).toBe(false); + manager.stop(); + }); + it('disables a running integration on policy upgrade and unregisters it safely', () => { + const manager = createConsentManager(); + const teardown = expect.createSpy(); + manager.update(config, makePrivacyChoice(config, {functional: true})); + const unregister = manager.register('fixture', 'functional', () => teardown); + manager.update({...config, policyVersion: 'new'}, makePrivacyChoice(config, {functional: true})); + expect(teardown).toHaveBeenCalled(); + unregister(); + manager.stop(); + }); + it('persists the choice and fails closed if storage cannot be read', () => { + setApi('memoryStorage'); + const api = getApi(); + const choice = makePrivacyChoice(config, {functional: true}); + expect(persistPrivacyChoice(choice)).toBe(true); + expect(readPrivacyChoice(config)).toEqual(choice); + api.setAccessDenied(true); + expect(readPrivacyChoice(config)).toBe(null); + expect(persistPrivacyChoice(choice)).toBe(false); + api.setAccessDenied(false); + api.removeItem(privacyChoiceKey()); + setApi('localStorage'); + }); +}); + + +describe('Selective privacy storage migration', () => { + const legacy = () => [getItemKey('cookie', 'approved'), 'cookies-policy-approved']; + beforeEach(() => { setApi('memoryStorage'); }); + afterEach(() => { + getApi().setAccessDenied(false); + [...legacy(), privacyChoiceKey(), privacyNoticeKey(), getItemKey('persistence', 'security')] + .forEach(key => getApi().removeItem(key)); + setApi('localStorage'); + }); + it('removes old acknowledgements without granting consent or changing authentication', () => { + const security = getItemKey('persistence', 'security'); + const original = '{"user":"synthetic","token":"synthetic-test-only"}'; + getApi().setItem(security, original); + legacy().forEach((key, index) => getApi().setItem(key, index ? 'false' : 'true')); + expect(isCookieNoticeAcknowledged(config)).toBe(false); + legacy().forEach(key => expect(getApi().getItem(key)).toBe(null)); + expect(getApi().getItem(privacyChoiceKey())).toBe(null); + expect(getApi().getItem(privacyNoticeKey())).toBe(null); + expect(getApi().getItem(security)).toBe(original); + }); + it('has nothing to show and leaves the storage untouched when privacy is disabled or missing', () => { + getApi().setItem(legacy()[0], 'true'); + expect(isCookieNoticeAcknowledged({enabled: false})).toBe(true); + expect(isCookieNoticeAcknowledged(null)).toBe(true); + expect(getApi().getItem(legacy()[0])).toBe('true'); + }); + it('preserves valid optional acceptance and refusal exactly as saved', () => { + [true, false].forEach(functional => { + const original = JSON.stringify(makePrivacyChoice(config, {functional})); + getApi().setItem(privacyChoiceKey(), original); + legacy().forEach(key => getApi().setItem(key, 'true')); + expect(isCookieNoticeAcknowledged(config)).toBe(true); + expect(getApi().getItem(privacyChoiceKey())).toBe(original); + expect(readPrivacyChoice(config).categories.functional).toBe(functional); + }); + }); + it('preserves a valid necessary-only dismissal and removes obsolete optional choices', () => { + const necessary = {...config, categories: []}; + acknowledgePrivacyNotice(necessary); + const original = getApi().getItem(privacyNoticeKey()); + persistPrivacyChoice(makePrivacyChoice(config, {functional: true})); + expect(isCookieNoticeAcknowledged(necessary)).toBe(true); + expect(getApi().getItem(privacyChoiceKey())).toBe(null); + expect(getApi().getItem(privacyNoticeKey())).toBe(original); + }); + it('removes expired, superseded, malformed and old-schema optional records on read', () => { + const old = makePrivacyChoice(config, {functional: true}, 1000); + const current = makePrivacyChoice(config, {functional: true}); + [JSON.stringify(old), JSON.stringify({...current, policyVersion: 'obsolete'}), + JSON.stringify({...current, version: 1}), JSON.stringify({...current, categories: []}), '{broken'] + .forEach(raw => { + getApi().setItem(privacyChoiceKey(), raw); + expect(readPrivacyChoice(config)).toBe(null); + expect(getApi().getItem(privacyChoiceKey())).toBe(null); + }); + }); + it('removes invalid information records without hiding a first visit', () => { + const necessary = {...config, categories: []}; + acknowledgePrivacyNotice(necessary); + const current = JSON.parse(getApi().getItem(privacyNoticeKey())); + [JSON.stringify({...current, expiresAt: 1000}), JSON.stringify({...current, policyVersion: 'obsolete'}), '{broken'] + .forEach(raw => { + getApi().setItem(privacyNoticeKey(), raw); + expect(isCookieNoticeAcknowledged(necessary)).toBe(false); + expect(getApi().getItem(privacyNoticeKey())).toBe(null); + }); + }); + it('fails closed when cleanup is denied and does not erase a concurrent newer decision', () => { + const current = JSON.stringify(makePrivacyChoice(config, {functional: true})); + let stored = '{broken'; + addApi('privacyMigrationRace', { + getItem: () => { const result = stored; stored = current; return result; }, + removeItem: () => { throw new Error('Must not remove the newer record'); } + }); + setApi('privacyMigrationRace'); + expect(readPrivacyChoice(config)).toBe(null); + expect(stored).toBe(current); + expect(readPrivacyChoice(config).categories.functional).toBe(true); + setApi('memoryStorage'); + getApi().setAccessDenied(true); + expect(isCookieNoticeAcknowledged(config)).toBe(false); + }); + it('ignores invalid records even when the browser permits reads but denies removal', () => { + const raw = JSON.stringify({...makePrivacyChoice(config, {functional: true}), policyVersion: 'obsolete'}); + addApi('privacyCleanupDenied', {getItem: () => raw, removeItem: () => { throw new Error('denied'); }}); + setApi('privacyCleanupDenied'); + expect(readPrivacyChoice(config)).toBe(null); + expect(isCookieNoticeAcknowledged(config)).toBe(false); + setApi('memoryStorage'); + }); +}); + +describe('Policy links', () => { + it('getPolicyLink returns the url of the locale, the first url as fallback, or undefined', () => { + const links = {cookie: {'en-US': 'en.html', 'it-IT': 'it.html'}, privacy: 'privacy.html', terms: {}}; + expect(getPolicyLink({links}, 'cookie', 'it-IT')).toBe('it.html'); + expect(getPolicyLink({links}, 'cookie', 'fr-FR')).toBe('en.html'); + expect(getPolicyLink({links}, 'privacy', 'fr-FR')).toBe('privacy.html'); + expect(getPolicyLink({links}, 'terms', 'fr-FR')).toBe(undefined); + expect(getPolicyLink({}, 'cookie', 'en-US')).toBe(undefined); + }); + it('hasPrivacyLinks is true only when at least one page is configured', () => { + expect(hasPrivacyLinks({links: {terms: 'terms.html'}})).toBe(true); + expect(hasPrivacyLinks({links: {cookie: {}, privacy: ''}})).toBe(false); + expect(hasPrivacyLinks({})).toBe(false); + }); +}); + +describe('privacyConfigSelector', () => { + const defaults = {policyVersion: 'extension-1', links: {cookie: 'extensions/PrivacySettings/assets/cookie.html'}}; + afterEach(() => { + ConfigUtils.removeConfigProp('privacy'); + }); + it('uses pages and version set at runtime when localConfig has no links', () => { + ConfigUtils.setConfigProp('privacy', {enabled: true, policyVersion: 'vanilla', categories: []}); + expect(privacyConfigSelector({controls: {privacy: {defaults}}})).toEqual({ + enabled: true, policyVersion: 'extension-1', categories: [], + links: {cookie: 'extensions/PrivacySettings/assets/cookie.html'} + }); + }); + it('keeps the localConfig version when the runtime defaults have none', () => { + ConfigUtils.setConfigProp('privacy', {enabled: true, policyVersion: 'vanilla'}); + expect(privacyConfigSelector({controls: {privacy: {defaults: {links: defaults.links}}}}).policyVersion).toBe('vanilla'); + }); + it('ignores runtime defaults when localConfig configures links', () => { + const localConfig = {enabled: true, policyVersion: 'operator', links: {privacy: 'https://example.com/privacy'}}; + ConfigUtils.setConfigProp('privacy', localConfig); + expect(privacyConfigSelector({controls: {privacy: {defaults}}})).toBe(localConfig); + }); + it('returns the localConfig configuration without runtime defaults, and null without any privacy configuration', () => { + const localConfig = {enabled: true, policyVersion: 'vanilla', links: {cookie: 'cookie.html'}}; + ConfigUtils.setConfigProp('privacy', localConfig); + expect(privacyConfigSelector({})).toBe(localConfig); + ConfigUtils.removeConfigProp('privacy'); + expect(privacyConfigSelector({})).toBe(null); + }); + it('links the template pages when neither localConfig nor the runtime defaults configure a page', () => { + ConfigUtils.setConfigProp('privacy', {enabled: true, policyVersion: 'vanilla', categories: []}); + expect(privacyConfigSelector({})).toEqual({ + enabled: true, policyVersion: 'vanilla', categories: [], links: templatePolicyLinks + }); + expect(privacyConfigSelector({controls: {privacy: {defaults: {policyVersion: 'extension-1'}}}})).toEqual({ + enabled: true, policyVersion: 'extension-1', categories: [], links: templatePolicyLinks + }); + expect(templatePolicyLinks).toEqual({ + cookie: 'product/assets/privacy/cookie.html', + privacy: 'product/assets/privacy/privacy.html', + terms: 'product/assets/privacy/terms.html' + }); + }); + it('does not link the template pages when privacy is disabled', () => { + const localConfig = {enabled: false, policyVersion: 'vanilla'}; + ConfigUtils.setConfigProp('privacy', localConfig); + expect(privacyConfigSelector({})).toBe(localConfig); + }); + it('replaces retention and categories of localConfig with the runtime ones', () => { + ConfigUtils.setConfigProp('privacy', {enabled: true, policyVersion: 'vanilla', retentionDays: 180, categories: [{id: 'statistics'}]}); + const runtime = {...defaults, retentionDays: 90, categories: [{id: 'functional', description: {'en-US': 'Saved searches'}}]}; + expect(privacyConfigSelector({controls: {privacy: {defaults: runtime}}})).toEqual({ + enabled: true, policyVersion: 'extension-1', retentionDays: 90, + categories: [{id: 'functional', description: {'en-US': 'Saved searches'}}], + links: {cookie: 'extensions/PrivacySettings/assets/cookie.html'} + }); + }); + it('uses the runtime enabled only when localConfig has no privacy section', () => { + const runtime = {...defaults, enabled: true}; + ConfigUtils.setConfigProp('privacy', {enabled: false, policyVersion: 'vanilla'}); + expect(privacyConfigSelector({controls: {privacy: {defaults: runtime}}}).enabled).toBe(false); + ConfigUtils.removeConfigProp('privacy'); + expect(privacyConfigSelector({controls: {privacy: {defaults: runtime}}})).toEqual({ + enabled: true, policyVersion: 'extension-1', links: {cookie: 'extensions/PrivacySettings/assets/cookie.html'} + }); + }); +});