@geogirafe/lib-geoportal 1.2.0-dev.2847697588 → 1.2.0-dev.2854703696
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/i18n/de.json +1 -0
- package/assets/i18n/en.json +1 -0
- package/assets/i18n/fr.json +1 -0
- package/assets/i18n/it.json +1 -0
- package/components/advancedfilter/component.d.ts +2 -1
- package/components/advancedfilter/component.js +3 -2
- package/components/auth/component.js +2 -2
- package/components/auth/style.css +10 -0
- package/components/auth-mobile/component.js +1 -1
- package/components/header/component.d.ts +15 -0
- package/components/header/component.js +67 -0
- package/components/header/style.css +38 -0
- package/components/main.d.ts +1 -0
- package/components/main.js +1 -0
- package/components/prototypebanner/component.js +6 -1
- package/components/themes/component.d.ts +2 -2
- package/components/themes-mobile/theme/component.js +3 -2
- package/components/userpreferences/component.js +5 -10
- package/models/basemaps/basemap.d.ts +3 -3
- package/models/customtheme.d.ts +2 -1
- package/models/georama.d.ts +10 -0
- package/models/georama.js +1 -0
- package/models/gmf.d.ts +0 -1
- package/models/layerdefinitions.d.ts +13 -0
- package/models/layerdefinitions.js +1 -0
- package/models/layers/baselayer.d.ts +3 -2
- package/models/layers/grouplayer.d.ts +2 -1
- package/models/layers/layer.d.ts +2 -1
- package/models/layers/layercog.d.ts +4 -4
- package/models/layers/layercog.js +3 -3
- package/models/layers/layerlocalfile.d.ts +2 -1
- package/models/layers/layervectortiles.d.ts +2 -1
- package/models/layers/layerwms.d.ts +4 -4
- package/models/layers/layerwms.js +3 -3
- package/models/layers/layerwmts.d.ts +4 -4
- package/models/layers/layerwmts.js +3 -3
- package/models/layers/layerxyz.d.ts +4 -4
- package/models/layers/layerxyz.js +3 -3
- package/models/layers/themelayer.d.ts +2 -1
- package/models/main.d.ts +3 -1
- package/package.json +1 -1
- package/styles/iframe.css +6 -5
- package/styles/index.css +2 -4
- package/templates/iframe.html +2 -2
- package/templates/index.html +2 -2
- package/templates/mobile.html +2 -1
- package/templates/public/about.json +1 -1
- package/tools/app/geogirafeapp-mobile.js +2 -0
- package/tools/app/geogirafeapp.js +2 -0
- package/tools/configuration/girafeconfig.d.ts +9 -0
- package/tools/configuration/girafeconfig.js +14 -0
- package/tools/share/serializers/sharedtypes.d.ts +6 -5
- package/tools/state/state.d.ts +4 -3
- package/tools/themes/themeshelper.d.ts +3 -2
- package/tools/themes/themesmanager.js +1 -1
package/assets/i18n/de.json
CHANGED
|
@@ -247,6 +247,7 @@
|
|
|
247
247
|
"geoadminch_other": "Andere",
|
|
248
248
|
"geoadminch_parcel": "Parzellen",
|
|
249
249
|
"geoadminch_zipcode": "PLZ",
|
|
250
|
+
"GeoGirafe is a flexible application to build online geoportals.": "GeoGirafe ist eine flexible Applikation um Online-Geoportale zu erstellen.",
|
|
250
251
|
"GeoJSON": "GeoJSON",
|
|
251
252
|
"Geolocation browser error": "Ihr Browser unterstützt keine Geolokalisierung",
|
|
252
253
|
"Geolocation error": "Geolocation-Fehler",
|
package/assets/i18n/en.json
CHANGED
|
@@ -249,6 +249,7 @@
|
|
|
249
249
|
"geoadminch_other": "Other",
|
|
250
250
|
"geoadminch_parcel": "Parcels",
|
|
251
251
|
"geoadminch_zipcode": "ZIP codes",
|
|
252
|
+
"GeoGirafe is a flexible application to build online geoportals.": "GeoGirafe is a flexible application to build online geoportals.",
|
|
252
253
|
"GeoJSON": "GeoJSON",
|
|
253
254
|
"Geolocation browser error": "Your browser does not support geolocation",
|
|
254
255
|
"Geolocation error": "Geolocation error",
|
package/assets/i18n/fr.json
CHANGED
|
@@ -247,6 +247,7 @@
|
|
|
247
247
|
"geoadminch_other": "Autres",
|
|
248
248
|
"geoadminch_parcel": "Parcelles",
|
|
249
249
|
"geoadminch_zipcode": "Codes postaux",
|
|
250
|
+
"GeoGirafe is a flexible application to build online geoportals.": "GeoGirafe est une application flexible permettant de créer des géoportails en ligne.",
|
|
250
251
|
"GeoJSON": "GeoJSON",
|
|
251
252
|
"Geolocation browser error": "Votre navigateur ne supporte pas la géolocalisation",
|
|
252
253
|
"Geolocation error": "Erreur de géolocalisation",
|
package/assets/i18n/it.json
CHANGED
|
@@ -247,6 +247,7 @@
|
|
|
247
247
|
"geoadminch_other": "Altri",
|
|
248
248
|
"geoadminch_parcel": "Parcelle",
|
|
249
249
|
"geoadminch_zipcode": "Codici postali",
|
|
250
|
+
"GeoGirafe is a flexible application to build online geoportals.": "GeoGirafe è un'applicazione flessibile per creare geoportali online.",
|
|
250
251
|
"GeoJSON": "GeoJSON",
|
|
251
252
|
"Geolocation browser error": "Il tuo browser non supporta la geolocalizzazione",
|
|
252
253
|
"Geolocation error": "Errore di geolocalizzazione",
|
|
@@ -4,6 +4,7 @@ import ColumnAliasHelper from '../../tools/utils/aliases.js';
|
|
|
4
4
|
import IGirafePanel from '../../tools/state/igirafepanel.js';
|
|
5
5
|
import LayerFilterElement from './layerfilterelement.js';
|
|
6
6
|
import FilterConditionElement from './filterconditionelement.js';
|
|
7
|
+
import { LayerId } from '../../models/layerdefinitions.js';
|
|
7
8
|
declare class AdvancedFilterComponent extends GirafeHTMLElement implements IGirafePanel {
|
|
8
9
|
protected templateUrl: string | null;
|
|
9
10
|
protected styleUrls: string[] | null;
|
|
@@ -16,7 +17,7 @@ declare class AdvancedFilterComponent extends GirafeHTMLElement implements IGira
|
|
|
16
17
|
layers: LayerWms[];
|
|
17
18
|
layerFilterElements: LayerFilterElement[];
|
|
18
19
|
columnAliasHelper: ColumnAliasHelper;
|
|
19
|
-
layerIsRefreshing: Map<
|
|
20
|
+
layerIsRefreshing: Map<LayerId, boolean>;
|
|
20
21
|
private csvDownloader;
|
|
21
22
|
constructor();
|
|
22
23
|
render(): void;
|
|
@@ -185,8 +185,9 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
185
185
|
filterElement.addCondition();
|
|
186
186
|
this.render();
|
|
187
187
|
}
|
|
188
|
-
const layerId =
|
|
189
|
-
|
|
188
|
+
const layerId = e.target.value;
|
|
189
|
+
// Loose equality == is on purpose. layer.id can be of type number or string, but .value always returns a string
|
|
190
|
+
const layer = this.layers.find((l) => l.id == layerId);
|
|
190
191
|
if (filterElement.hasAppliedConditions()) {
|
|
191
192
|
// If the filter has already been applied to the layer, a new filter is created and the old one is deleted
|
|
192
193
|
const newFilter = new LayerFilterElement(this.context, this.columnAliasHelper, this.layerFilterElements.length);
|
|
@@ -8,10 +8,10 @@ export default class OauthComponent extends GirafeHTMLElement {
|
|
|
8
8
|
return uHtml `<style>
|
|
9
9
|
.hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}button,input,select,textarea{font:inherit}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height) / 1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);cursor:pointer;width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad1);background-color:var(--bkg-color-grad2)}.gg-button:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed;border:none}.gg-button:disabled img{filter:opacity(.6)}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height) / 1.2);min-height:calc(var(--app-standard-height) / 1.2);max-height:calc(var(--app-standard-height) / 1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height) / 2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height) / 2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height) / 2);min-height:calc(var(--app-standard-height) / 2);max-height:calc(var(--app-standard-height) / 2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height) / 3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height) / 3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover:not(:disabled),.gg-select:hover:not(:disabled),.gg-input:hover:not(:disabled),.gg-textarea:hover:not(:disabled),.gg-icon-button:hover:not(:disabled){background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height) / 2);height:calc(var(--app-standard-height) / 2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}.tippy-box{background-color:var(--bkg-color)!important;border:var(--app-standard-border)!important}.tippy-content{color:var(--text-color)!important}.tippy-arrow{color:var(--bkg-color)!important}.tippy-box[data-theme~=error]{background-color:var(--error-color);white-space:pre-line}div.tippy-box[data-theme=image-popup]{border:var(--app-standard-border)!important;& div.tippy-content{background-color:var(--bkg-color)!important;& img{max-width:20rem;max-height:20rem}}& div.tippy-arrow{color:var(--bkg-color)!important}}
|
|
10
10
|
</style><style>
|
|
11
|
-
.container{border-right:var(--app-standard-border);flex-direction:row;align-items:center;display:flex}.name{text-align:left;flex-direction:column;display:flex}.avatar-initials{background-color:var(--app-color-grey);color:#000;border-radius:50%;justify-content:center;align-items:center;width:2rem;height:2rem;font-weight:700;display:flex}.gg-icon-button.logged-in{flex-direction:row;gap:.5rem;padding:.5rem}
|
|
11
|
+
.container{border-right:var(--app-standard-border);flex-direction:row;align-items:center;display:flex}.name{text-align:left;flex-direction:column;display:flex}.avatar-initials{background-color:var(--app-color-grey);color:#000;border-radius:50%;justify-content:center;align-items:center;width:2rem;height:2rem;font-weight:700;display:flex}.gg-icon-button.logged-in{flex-direction:row;gap:.5rem;padding:.5rem}@media (width<=991px){#login-btn>span,.logged-in>.name{display:none}#login-btn>img{padding-right:.5rem}}
|
|
12
12
|
</style>
|
|
13
13
|
<style>${this.customStyle}</style>
|
|
14
|
-
<div class="${this.context.configManager.Config.oauth || this.context.configManager.Config.gmfauth ? '' : 'hidden'}"><div class="${this.state.oauth.status === 'loggedIn' ? 'hidden' : 'container'}"><button class="gg-icon-button gg-medium-withtext" onclick="${() => this.onLoginClick()}"><img alt="menu-icon" src="icons/user.svg"> <span i18n="Login">Login</span></button></div><div class="${this.state.oauth.status !== 'loggedIn' ? 'hidden' : 'container'}"><button class="gg-icon-button logged-in" onclick="${() => this.onLogoutClick()}"><span class="avatar-initials">${this.getInitials()}</span><div class="name"><span class="${this.getFullName() ? '' : 'hidden'}">${this.getFullName()}</span> <span>${this.getDisplayName()}</span></div></button></div></div>
|
|
14
|
+
<div class="${this.context.configManager.Config.oauth || this.context.configManager.Config.gmfauth ? '' : 'hidden'}"><div class="${this.state.oauth.status === 'loggedIn' ? 'hidden' : 'container'}"><button id="login-btn" class="gg-icon-button gg-medium-withtext" aria-label="Login" onclick="${() => this.onLoginClick()}"><img alt="menu-icon" src="icons/user.svg"> <span i18n="Login">Login</span></button></div><div class="${this.state.oauth.status !== 'loggedIn' ? 'hidden' : 'container'}"><button class="gg-icon-button logged-in" onclick="${() => this.onLogoutClick()}"><span class="avatar-initials">${this.getInitials()}</span><div class="name"><span class="${this.getFullName() ? '' : 'hidden'}">${this.getFullName()}</span> <span>${this.getDisplayName()}</span></div></button></div></div>
|
|
15
15
|
${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
16
16
|
};
|
|
17
17
|
constructor(name = 'oauth') {
|
|
@@ -11,7 +11,7 @@ export default class MobileOauthComponent extends OauthComponent {
|
|
|
11
11
|
.container{filter:drop-shadow(0 4px 7px #0004382c);background-color:#fff;border-radius:8px;flex-direction:column;padding:1em;display:flex}.container:active{background-color:#c6ceda}.container>button{background:0 0;border:none;flex-direction:column;flex:1;justify-content:center;align-items:center;display:flex}.container>button>img{opacity:.7;width:25%;padding-bottom:1em}.container>button>span{color:#3f68a7;flex:1;justify-content:center;align-items:center;font-size:1.2em;font-weight:600;display:flex}
|
|
12
12
|
</style>
|
|
13
13
|
<style>${this.customStyle}</style>
|
|
14
|
-
<div class="${this.context.configManager.Config.oauth || this.context.configManager.Config.gmfauth ? '' : 'hidden'}"><div class="${this.state.oauth.status === 'loggedIn' ? 'hidden' : 'container'}"><button class="gg-icon-button gg-medium-withtext" onclick="${() => this.onLoginClick()}"><img alt="menu-icon" src="icons/user.svg"> <span i18n="Login">Login</span></button></div><div class="${this.state.oauth.status !== 'loggedIn' ? 'hidden' : 'container'}"><button class="gg-icon-button logged-in" onclick="${() => this.onLogoutClick()}"><span class="avatar-initials">${this.getInitials()}</span><div class="name"><span class="${this.getFullName() ? '' : 'hidden'}">${this.getFullName()}</span> <span>${this.getDisplayName()}</span></div></button></div></div>
|
|
14
|
+
<div class="${this.context.configManager.Config.oauth || this.context.configManager.Config.gmfauth ? '' : 'hidden'}"><div class="${this.state.oauth.status === 'loggedIn' ? 'hidden' : 'container'}"><button id="login-btn" class="gg-icon-button gg-medium-withtext" aria-label="Login" onclick="${() => this.onLoginClick()}"><img alt="menu-icon" src="icons/user.svg"> <span i18n="Login">Login</span></button></div><div class="${this.state.oauth.status !== 'loggedIn' ? 'hidden' : 'container'}"><button class="gg-icon-button logged-in" onclick="${() => this.onLogoutClick()}"><span class="avatar-initials">${this.getInitials()}</span><div class="name"><span class="${this.getFullName() ? '' : 'hidden'}">${this.getFullName()}</span> <span>${this.getDisplayName()}</span></div></button></div></div>
|
|
15
15
|
${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
16
16
|
};
|
|
17
17
|
constructor() {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import GirafeHTMLElement from '../../base/GirafeHTMLElement.js';
|
|
2
|
+
import GirafeConfig from '../../tools/configuration/girafeconfig.js';
|
|
3
|
+
declare class HeaderComponent extends GirafeHTMLElement {
|
|
4
|
+
protected templateUrl: string | null;
|
|
5
|
+
protected styleUrls: string[] | null;
|
|
6
|
+
template: () => import("uhtml").Hole;
|
|
7
|
+
constructor();
|
|
8
|
+
get config(): GirafeConfig;
|
|
9
|
+
get logoSource(): string;
|
|
10
|
+
get logoAltText(): string;
|
|
11
|
+
private setHtmlMetaData;
|
|
12
|
+
registerEvents(): void;
|
|
13
|
+
protected connectedCallback(): void;
|
|
14
|
+
}
|
|
15
|
+
export default HeaderComponent;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html as uHtml } from 'uhtml';
|
|
8
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
9
|
+
import GirafeHTMLElement from '../../base/GirafeHTMLElement.js';
|
|
10
|
+
import { UsedInTemplateOnly } from '../../decorators.js';
|
|
11
|
+
class HeaderComponent extends GirafeHTMLElement {
|
|
12
|
+
templateUrl = null;
|
|
13
|
+
styleUrls = null;
|
|
14
|
+
template = () => {
|
|
15
|
+
return uHtml `<style>
|
|
16
|
+
#header{box-sizing:border-box;align-items:center;gap:1rem;height:100%;padding:.15rem 1rem;display:flex}#logo{filter:none;width:auto;height:100%;max-height:100%;display:block}#app-title{color:var(--text-color);-webkit-line-clamp:2;-webkit-box-orient:vertical;min-width:0;font-size:1.3rem;font-weight:700;display:-webkit-box;overflow:hidden}@media (width<=991px){#app-title{display:none}}
|
|
17
|
+
</style>
|
|
18
|
+
<style>${this.customStyle}</style>
|
|
19
|
+
<div id="header">${this.config.branding.logo !== '' ? uHtml ` <img id="logo" alt="${this.logoAltText}" src="${this.logoSource}"> ` : ''} ${this.config.branding.showAppTitleInHeader ? uHtml `<div id="app-title" i18n="${this.config.branding.appTitle}">${this.config.branding.appTitle}</div>` : ''}</div>
|
|
20
|
+
${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
21
|
+
};
|
|
22
|
+
constructor() {
|
|
23
|
+
super('header');
|
|
24
|
+
}
|
|
25
|
+
get config() {
|
|
26
|
+
return this.context.configManager.Config;
|
|
27
|
+
}
|
|
28
|
+
get logoSource() {
|
|
29
|
+
if (this.state.interface.darkFrontendMode) {
|
|
30
|
+
return this.config.branding.logoDarkMode;
|
|
31
|
+
}
|
|
32
|
+
return this.config.branding.logo;
|
|
33
|
+
}
|
|
34
|
+
get logoAltText() {
|
|
35
|
+
return `${this.config.branding.appTitle.toLowerCase().replaceAll(' ', '-')}-logo`;
|
|
36
|
+
}
|
|
37
|
+
setHtmlMetaData() {
|
|
38
|
+
const title = this.context.i18nManager.getTranslation(this.config.branding.appTitle);
|
|
39
|
+
const description = this.context.i18nManager.getTranslation(this.config.branding.description);
|
|
40
|
+
document.title = title;
|
|
41
|
+
document.querySelector('meta[name="description"]')?.setAttribute('content', description);
|
|
42
|
+
}
|
|
43
|
+
registerEvents() {
|
|
44
|
+
this.subscribe('language', () => this.setHtmlMetaData());
|
|
45
|
+
if (!this.state.interface.isMobile) {
|
|
46
|
+
this.subscribe('interface.darkFrontendMode', () => this.refreshRender());
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
connectedCallback() {
|
|
50
|
+
super.connectedCallback();
|
|
51
|
+
this.setHtmlMetaData();
|
|
52
|
+
this.render();
|
|
53
|
+
super.girafeTranslate();
|
|
54
|
+
if (this.state.interface.isMobile) {
|
|
55
|
+
// Header shouldn't be visible on mobile
|
|
56
|
+
this.hide();
|
|
57
|
+
}
|
|
58
|
+
this.registerEvents();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
__decorate([
|
|
62
|
+
UsedInTemplateOnly()
|
|
63
|
+
], HeaderComponent.prototype, "logoSource", null);
|
|
64
|
+
__decorate([
|
|
65
|
+
UsedInTemplateOnly()
|
|
66
|
+
], HeaderComponent.prototype, "logoAltText", null);
|
|
67
|
+
export default HeaderComponent;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* SPDX-License-Identifier: Apache-2.0 */
|
|
2
|
+
#header {
|
|
3
|
+
height: 100%;
|
|
4
|
+
display: flex;
|
|
5
|
+
gap: 1rem;
|
|
6
|
+
padding: 0.15rem 1rem;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
align-items: center;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
#logo {
|
|
12
|
+
width: auto;
|
|
13
|
+
height: 100%;
|
|
14
|
+
max-height: 100%;
|
|
15
|
+
display: block;
|
|
16
|
+
filter: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#app-title {
|
|
20
|
+
font-size: 1.3rem;
|
|
21
|
+
font-weight: bold;
|
|
22
|
+
color: var(--text-color);
|
|
23
|
+
min-width: 0;
|
|
24
|
+
/* Will limit word wrapping to two lines */
|
|
25
|
+
display: -webkit-box;
|
|
26
|
+
-webkit-box-orient: vertical;
|
|
27
|
+
-webkit-line-clamp: 2;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
Don't show app title on small screens
|
|
33
|
+
*/
|
|
34
|
+
@media (max-width: 991px) {
|
|
35
|
+
#app-title {
|
|
36
|
+
display: none;
|
|
37
|
+
}
|
|
38
|
+
}
|
package/components/main.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export { default as ExternalLayersComponent } from './extlayers/component.js';
|
|
|
24
24
|
export { default as FeedbackButtonComponent } from './feedbackbutton/component.js';
|
|
25
25
|
export { default as GeolocationMobile } from './geolocation-mobile/component.js';
|
|
26
26
|
export { default as GetDirectionsArtifact } from './getdirections/component.js';
|
|
27
|
+
export { default as HeaderComponent } from './header/component.js';
|
|
27
28
|
export { default as HelpComponent } from './help/component.js';
|
|
28
29
|
export { default as InfoboxComponent } from './infobox/component.js';
|
|
29
30
|
export { default as InfoWindowComponent } from './infowindow/component.js';
|
package/components/main.js
CHANGED
|
@@ -23,6 +23,7 @@ export { default as ExternalLayersComponent } from './extlayers/component.js';
|
|
|
23
23
|
export { default as FeedbackButtonComponent } from './feedbackbutton/component.js';
|
|
24
24
|
export { default as GeolocationMobile } from './geolocation-mobile/component.js';
|
|
25
25
|
export { default as GetDirectionsArtifact } from './getdirections/component.js';
|
|
26
|
+
export { default as HeaderComponent } from './header/component.js';
|
|
26
27
|
export { default as HelpComponent } from './help/component.js';
|
|
27
28
|
export { default as InfoboxComponent } from './infobox/component.js';
|
|
28
29
|
export { default as InfoWindowComponent } from './infowindow/component.js';
|
|
@@ -19,7 +19,12 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
19
19
|
}
|
|
20
20
|
connectedCallback() {
|
|
21
21
|
super.connectedCallback();
|
|
22
|
-
this.
|
|
22
|
+
if (this.context.configManager.Config.branding.prototypeBanner) {
|
|
23
|
+
this.render();
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.hide();
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
export default PrototypeBannerComponent;
|
|
@@ -13,9 +13,9 @@ declare class ThemeComponent extends GirafeHTMLElement {
|
|
|
13
13
|
activeThemeType: ThemeType;
|
|
14
14
|
clickOutsideContainer: HTMLElement | null;
|
|
15
15
|
get customThemes(): CustomTheme[];
|
|
16
|
-
get allThemes(): Record<
|
|
16
|
+
get allThemes(): Record<import("../../models/layerdefinitions.js").LayerId, ThemeLayer>;
|
|
17
17
|
get favoriteThemes(): (ThemeLayer | CustomTheme)[];
|
|
18
|
-
get activeThemes(): Record<
|
|
18
|
+
get activeThemes(): Record<import("../../models/layerdefinitions.js").LayerId, ThemeLayer> | (ThemeLayer | CustomTheme)[];
|
|
19
19
|
constructor();
|
|
20
20
|
registerEvents(): void;
|
|
21
21
|
render(): void;
|
|
@@ -28,8 +28,9 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
28
28
|
this.refreshTheme();
|
|
29
29
|
}
|
|
30
30
|
refreshTheme() {
|
|
31
|
-
const themeId =
|
|
32
|
-
|
|
31
|
+
const themeId = this.getAttribute('themeid');
|
|
32
|
+
// Loose equality == is on purpose. layer.id can be of type number or string, but getAttribute() always returns a string
|
|
33
|
+
const theme = this.state.layers.layersList.find((layer) => layer.id == themeId);
|
|
33
34
|
if (theme) {
|
|
34
35
|
this.theme = this.context.layerManager.getTreeItem(theme.treeItemId);
|
|
35
36
|
}
|
|
@@ -47,10 +47,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
47
47
|
}
|
|
48
48
|
}),
|
|
49
49
|
logLevel: new UserPreference('general.logLevel', null, 'system', 'select'),
|
|
50
|
-
theme: new UserPreference('themes.defaultTheme', 'theme', 'map', 'select', (themeName) =>
|
|
51
|
-
const themeId = Object.keys(this.state.themes._allThemes).find((themeKey) => this.state.themes._allThemes[Number(themeKey)].name === themeName);
|
|
52
|
-
return this.state.themes._allThemes[Number(themeId)];
|
|
53
|
-
}),
|
|
50
|
+
theme: new UserPreference('themes.defaultTheme', 'theme', 'map', 'select', (themeName) => Object.values(this.state.themes._allThemes).find((theme) => theme.name === themeName)),
|
|
54
51
|
basemap: new UserPreference('basemaps.defaultBasemap', 'activeBasemaps', 'map', 'select', (bsName) => {
|
|
55
52
|
const newDefaultBasemap = Object.values(this.state.basemaps).find((basemap) => basemap.name === bsName);
|
|
56
53
|
if (newDefaultBasemap?.opacity == 0) {
|
|
@@ -151,9 +148,8 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
151
148
|
}
|
|
152
149
|
this.refreshThemeOptions();
|
|
153
150
|
if (this.preferences.basemap) {
|
|
154
|
-
this.preferences.basemap.options = Object.
|
|
155
|
-
|
|
156
|
-
return { label: baseMapName, value: baseMapName };
|
|
151
|
+
this.preferences.basemap.options = Object.values(this.state.basemaps).map((basemap) => {
|
|
152
|
+
return { label: basemap.name, value: basemap.name };
|
|
157
153
|
});
|
|
158
154
|
}
|
|
159
155
|
if (this.preferences.selectionComponent) {
|
|
@@ -198,9 +194,8 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
198
194
|
return;
|
|
199
195
|
}
|
|
200
196
|
let defaultThemes = [{ label: '-', value: '' }];
|
|
201
|
-
Object.
|
|
202
|
-
|
|
203
|
-
defaultThemes.push({ label: themeName, value: themeName });
|
|
197
|
+
Object.values(this.state.themes._allThemes).forEach((theme) => {
|
|
198
|
+
defaultThemes.push({ label: theme.name, value: theme.name });
|
|
204
199
|
});
|
|
205
200
|
defaultThemes = defaultThemes.sort((a, b) => a.label.toUpperCase().localeCompare(b.label.toUpperCase()));
|
|
206
201
|
const customThemes = this.context.customThemesManager.customThemes.map((ct) => {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { GMFBackgroundLayer } from '../gmf.js';
|
|
2
1
|
import BaseLayer from '../layers/baselayer.js';
|
|
2
|
+
import { BasemapDefinition, LayerId } from '../layerdefinitions.js';
|
|
3
3
|
declare class Basemap {
|
|
4
|
-
id:
|
|
4
|
+
id: LayerId;
|
|
5
5
|
name: string;
|
|
6
6
|
thumbnail: string;
|
|
7
7
|
opacity: number;
|
|
8
8
|
layersList: BaseLayer[];
|
|
9
|
-
constructor(elem:
|
|
9
|
+
constructor(elem: BasemapDefinition, opacity?: number);
|
|
10
10
|
get projection(): string | undefined;
|
|
11
11
|
get opacityDisabled(): boolean;
|
|
12
12
|
}
|
package/models/customtheme.d.ts
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { GMFTreeItem, GMFTheme } from './gmf.js';
|
|
2
|
+
/**
|
|
3
|
+
* These are the interfaces for a Georama backend that differ from GMF
|
|
4
|
+
*/
|
|
5
|
+
export interface GeoramaTreeItem extends Omit<GMFTreeItem, 'id'> {
|
|
6
|
+
id: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GeoramaTheme extends Omit<GMFTheme, 'id'> {
|
|
9
|
+
id: string;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/models/gmf.d.ts
CHANGED
|
@@ -75,7 +75,6 @@ export interface GMFTheme {
|
|
|
75
75
|
export interface GMFGroup extends GMFTreeItem {
|
|
76
76
|
children: GMFTreeItem[];
|
|
77
77
|
}
|
|
78
|
-
export type GMFBackgroundLayer = GMFTreeItem;
|
|
79
78
|
export type GMFServerOgcType = 'mapserver' | 'qgisserver' | 'georama' | 'geoserver' | 'arcgis' | 'other';
|
|
80
79
|
export interface GMFServerOgc {
|
|
81
80
|
url: string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { GMFTheme, GMFTreeItem } from './gmf.js';
|
|
2
|
+
import { GeoramaTheme, GeoramaTreeItem } from './georama.js';
|
|
3
|
+
/**
|
|
4
|
+
* Unified interfaces for layer definitions from different backends.
|
|
5
|
+
*/
|
|
6
|
+
export type LayerId = number | string;
|
|
7
|
+
export interface TreeItemDefinition extends Omit<GMFTreeItem, 'id'>, Omit<GeoramaTreeItem, 'id'> {
|
|
8
|
+
id: LayerId;
|
|
9
|
+
}
|
|
10
|
+
export interface ThemeDefinition extends Omit<GMFTheme, 'id'>, Omit<GeoramaTheme, 'id'> {
|
|
11
|
+
id: LayerId;
|
|
12
|
+
}
|
|
13
|
+
export type BasemapDefinition = TreeItemDefinition;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import GroupLayer from './grouplayer.js';
|
|
2
2
|
import ThemeLayer from './themelayer.js';
|
|
3
|
+
import { LayerId } from '../layerdefinitions.js';
|
|
3
4
|
type BaseLayerOptions = {
|
|
4
5
|
isDefaultChecked?: boolean;
|
|
5
6
|
disclaimer?: string;
|
|
6
7
|
metadataUrl?: string;
|
|
7
8
|
};
|
|
8
9
|
declare abstract class BaseLayer {
|
|
9
|
-
id:
|
|
10
|
+
id: LayerId;
|
|
10
11
|
treeItemId: string;
|
|
11
12
|
name: string;
|
|
12
13
|
order: number;
|
|
@@ -27,6 +28,6 @@ declare abstract class BaseLayer {
|
|
|
27
28
|
abstract get inactive(): boolean;
|
|
28
29
|
abstract clone(): BaseLayer;
|
|
29
30
|
parent?: ThemeLayer | GroupLayer;
|
|
30
|
-
constructor(id:
|
|
31
|
+
constructor(id: LayerId, name: string, order: number, options?: BaseLayerOptions);
|
|
31
32
|
}
|
|
32
33
|
export default BaseLayer;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import BaseLayer from './baselayer.js';
|
|
2
|
+
import { LayerId } from '../layerdefinitions.js';
|
|
2
3
|
import ILayerWithTime from './ilayerwithtime.js';
|
|
3
4
|
import ITimeOptions from '../../tools/time/itimeoptions.js';
|
|
4
5
|
export type GroupLayerOptions = {
|
|
@@ -21,7 +22,7 @@ declare class GroupLayer extends BaseLayer implements ILayerWithTime {
|
|
|
21
22
|
timeAttribute?: string;
|
|
22
23
|
timeRestriction?: string;
|
|
23
24
|
children: BaseLayer[];
|
|
24
|
-
constructor(id:
|
|
25
|
+
constructor(id: LayerId, name: string, order: number, options?: GroupLayerOptions);
|
|
25
26
|
clone(): GroupLayer;
|
|
26
27
|
get active(): boolean;
|
|
27
28
|
get inactive(): boolean;
|
package/models/layers/layer.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import BaseLayer from './baselayer.js';
|
|
2
2
|
import GroupLayer from './grouplayer.js';
|
|
3
3
|
import ThemeLayer from './themelayer.js';
|
|
4
|
+
import { LayerId } from '../layerdefinitions.js';
|
|
4
5
|
type LayerOptions = {
|
|
5
6
|
isDefaultChecked?: boolean;
|
|
6
7
|
disclaimer?: string;
|
|
@@ -15,7 +16,7 @@ declare abstract class Layer extends BaseLayer {
|
|
|
15
16
|
swiped: 'left' | 'right' | 'no';
|
|
16
17
|
isLegendExpanded: boolean;
|
|
17
18
|
parent: ThemeLayer | GroupLayer;
|
|
18
|
-
constructor(id:
|
|
19
|
+
constructor(id: LayerId, name: string, order: number, options?: LayerOptions);
|
|
19
20
|
get isTransparent(): boolean;
|
|
20
21
|
get hasValidOpacity(): boolean;
|
|
21
22
|
get active(): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LayerId, TreeItemDefinition } from '../layerdefinitions.js';
|
|
2
2
|
import Layer from './layer.js';
|
|
3
3
|
type LayerCogTilesOptions = {
|
|
4
4
|
isDefaultChecked?: boolean;
|
|
@@ -9,9 +9,9 @@ type LayerCogTilesOptions = {
|
|
|
9
9
|
};
|
|
10
10
|
declare class LayerCog extends Layer {
|
|
11
11
|
source: string;
|
|
12
|
-
constructor(id:
|
|
12
|
+
constructor(id: LayerId, name: string, order: number, source: string, options?: TreeItemDefinition | LayerCogTilesOptions);
|
|
13
13
|
clone(): LayerCog;
|
|
14
|
-
private static
|
|
15
|
-
private static
|
|
14
|
+
private static isTreeItemDefinition;
|
|
15
|
+
private static getOptionsFromDefinition;
|
|
16
16
|
}
|
|
17
17
|
export default LayerCog;
|
|
@@ -10,7 +10,7 @@ class LayerCog extends Layer {
|
|
|
10
10
|
source;
|
|
11
11
|
constructor(id, name, order, source, options) {
|
|
12
12
|
let opts = options ?? {};
|
|
13
|
-
opts = LayerCog.
|
|
13
|
+
opts = LayerCog.isTreeItemDefinition(opts) ? LayerCog.getOptionsFromDefinition(opts) : opts;
|
|
14
14
|
super(id, name, order, opts);
|
|
15
15
|
this.source = source;
|
|
16
16
|
}
|
|
@@ -26,10 +26,10 @@ class LayerCog extends Layer {
|
|
|
26
26
|
clonedObject.activeState = this.activeState;
|
|
27
27
|
return clonedObject;
|
|
28
28
|
}
|
|
29
|
-
static
|
|
29
|
+
static isTreeItemDefinition(options) {
|
|
30
30
|
return 'id' in options;
|
|
31
31
|
}
|
|
32
|
-
static
|
|
32
|
+
static getOptionsFromDefinition(options) {
|
|
33
33
|
return {
|
|
34
34
|
isDefaultChecked: options.metadata?.isChecked,
|
|
35
35
|
metadataUrl: options.metadata?.metadataUrl,
|
|
@@ -3,6 +3,7 @@ import Layer from './layer.js';
|
|
|
3
3
|
import Geometry from 'ol/geom/Geometry.js';
|
|
4
4
|
import { Extent } from 'ol/extent.js';
|
|
5
5
|
import ILayerWithLegend from './ilayerwithlegend.js';
|
|
6
|
+
import { LayerId } from '../layerdefinitions.js';
|
|
6
7
|
declare class LayerLocalFile extends Layer implements ILayerWithLegend {
|
|
7
8
|
_features: Feature<Geometry>[];
|
|
8
9
|
lastModifiedDate: string;
|
|
@@ -12,7 +13,7 @@ declare class LayerLocalFile extends Layer implements ILayerWithLegend {
|
|
|
12
13
|
extent: Extent;
|
|
13
14
|
private readonly file;
|
|
14
15
|
private readonly locale;
|
|
15
|
-
constructor(id:
|
|
16
|
+
constructor(id: LayerId, order: number, file: File, features: Feature<Geometry>[], extent: Extent, locale: string, options?: {
|
|
16
17
|
isDefaultChecked?: boolean;
|
|
17
18
|
});
|
|
18
19
|
clone(): LayerLocalFile;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Layer from './layer.js';
|
|
2
|
+
import { LayerId } from '../layerdefinitions.js';
|
|
2
3
|
type LayerVectorTilesOptions = {
|
|
3
4
|
projection?: string;
|
|
4
5
|
layerName?: string;
|
|
@@ -12,7 +13,7 @@ declare class LayerVectorTiles extends Layer {
|
|
|
12
13
|
style: string;
|
|
13
14
|
layerName?: string;
|
|
14
15
|
projection?: string;
|
|
15
|
-
constructor(id:
|
|
16
|
+
constructor(id: LayerId, name: string, order: number, style: string, options?: LayerVectorTilesOptions);
|
|
16
17
|
clone(): LayerVectorTiles;
|
|
17
18
|
}
|
|
18
19
|
export default LayerVectorTiles;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import WfsFilter from '../../tools/wfs/wfsfilter.js';
|
|
2
|
-
import {
|
|
2
|
+
import { LayerId, TreeItemDefinition } from '../layerdefinitions.js';
|
|
3
3
|
import ServerOgc from '../serverogc.js';
|
|
4
4
|
import ILayerWithFilter from './ilayerwithfilter.js';
|
|
5
5
|
import ILayerWithLegend from './ilayerwithlegend.js';
|
|
@@ -70,7 +70,7 @@ declare class LayerWms extends Layer implements ILayerWithLegend, ILayerWithFilt
|
|
|
70
70
|
timeAttribute?: string;
|
|
71
71
|
enumeratedAttributes?: string[];
|
|
72
72
|
editable?: string;
|
|
73
|
-
constructor(id:
|
|
73
|
+
constructor(id: LayerId, name: string, order: number, ogcServer: ServerOgc, options?: TreeItemDefinition | LayerWmsOptions);
|
|
74
74
|
clone(): LayerWms;
|
|
75
75
|
static isResolutionRangeRestricted(minResolution: number | undefined, maxResolution: number | undefined): boolean | 0 | undefined;
|
|
76
76
|
hasRestrictedResolution(): boolean | 0 | undefined;
|
|
@@ -82,8 +82,8 @@ declare class LayerWms extends Layer implements ILayerWithLegend, ILayerWithFilt
|
|
|
82
82
|
get serverUniqueQueryId(): string;
|
|
83
83
|
get wfsQueryable(): boolean;
|
|
84
84
|
get wmsQueryableOnly(): boolean;
|
|
85
|
-
private static
|
|
86
|
-
private static
|
|
85
|
+
private static isTreeItemDefinition;
|
|
86
|
+
private static getOptionsFromDefinition;
|
|
87
87
|
private static getDefaultWmsInfoFormat;
|
|
88
88
|
}
|
|
89
89
|
export default LayerWms;
|
|
@@ -44,7 +44,7 @@ class LayerWms extends Layer {
|
|
|
44
44
|
editable;
|
|
45
45
|
constructor(id, name, order, ogcServer, options) {
|
|
46
46
|
let opts = options ?? {};
|
|
47
|
-
opts = LayerWms.
|
|
47
|
+
opts = LayerWms.isTreeItemDefinition(opts) ? LayerWms.getOptionsFromDefinition(opts) : opts;
|
|
48
48
|
super(id, name, order, opts);
|
|
49
49
|
this.ogcServer = ogcServer;
|
|
50
50
|
this.minResolution = opts?.minResolution;
|
|
@@ -152,10 +152,10 @@ class LayerWms extends Layer {
|
|
|
152
152
|
get wmsQueryableOnly() {
|
|
153
153
|
return this.queryable && !this.ogcServer.wfsSupport;
|
|
154
154
|
}
|
|
155
|
-
static
|
|
155
|
+
static isTreeItemDefinition(options) {
|
|
156
156
|
return 'id' in options;
|
|
157
157
|
}
|
|
158
|
-
static
|
|
158
|
+
static getOptionsFromDefinition(options) {
|
|
159
159
|
const opts = {
|
|
160
160
|
isDefaultChecked: options.metadata?.isChecked,
|
|
161
161
|
metadataUrl: options.metadata?.metadataUrl,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LayerId, TreeItemDefinition } from '../layerdefinitions.js';
|
|
2
2
|
import ServerOgc from '../serverogc.js';
|
|
3
3
|
import ILayerWithLegend from './ilayerwithlegend.js';
|
|
4
4
|
import Layer from './layer.js';
|
|
@@ -48,12 +48,12 @@ declare class LayerWmts extends Layer implements ILayerWithLegend {
|
|
|
48
48
|
hiDPILegendImages?: Record<string, string>;
|
|
49
49
|
/** Linked ol layer, starting with an underscore to not be part of the proxy. **/
|
|
50
50
|
_olayer?: TileLayer<WMTS>;
|
|
51
|
-
constructor(id:
|
|
51
|
+
constructor(id: LayerId, name: string, order: number, url: string, layer: string, options?: TreeItemDefinition | LayerWmtsOptions, ogcServer?: ServerOgc);
|
|
52
52
|
clone(): LayerWmts;
|
|
53
53
|
get layerUniqueId(): string;
|
|
54
54
|
hasRestrictedResolution(): boolean | 0 | undefined;
|
|
55
55
|
isVisibleAtResolution(resolution: number): boolean;
|
|
56
|
-
private static
|
|
57
|
-
private static
|
|
56
|
+
private static isTreeItemDefinition;
|
|
57
|
+
private static getOptionsFromDefinition;
|
|
58
58
|
}
|
|
59
59
|
export default LayerWmts;
|
|
@@ -39,7 +39,7 @@ class LayerWmts extends Layer {
|
|
|
39
39
|
_olayer;
|
|
40
40
|
constructor(id, name, order, url, layer, options, ogcServer) {
|
|
41
41
|
let opts = options ?? {};
|
|
42
|
-
opts = LayerWmts.
|
|
42
|
+
opts = LayerWmts.isTreeItemDefinition(opts) ? LayerWmts.getOptionsFromDefinition(opts) : opts;
|
|
43
43
|
super(id, name, order, opts);
|
|
44
44
|
this.url = url;
|
|
45
45
|
this.layer = layer;
|
|
@@ -102,10 +102,10 @@ class LayerWmts extends Layer {
|
|
|
102
102
|
}
|
|
103
103
|
return resolution >= (this.minResolution ?? -1) && resolution <= (this.maxResolution ?? Infinity);
|
|
104
104
|
}
|
|
105
|
-
static
|
|
105
|
+
static isTreeItemDefinition(options) {
|
|
106
106
|
return 'id' in options;
|
|
107
107
|
}
|
|
108
|
-
static
|
|
108
|
+
static getOptionsFromDefinition(options) {
|
|
109
109
|
return {
|
|
110
110
|
isDefaultChecked: options.metadata?.isChecked,
|
|
111
111
|
metadataUrl: options.metadata?.metadataUrl,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LayerId, TreeItemDefinition } from '../layerdefinitions.js';
|
|
2
2
|
import Layer from './layer.js';
|
|
3
3
|
type LayerXYZTilesOptions = {
|
|
4
4
|
isDefaultChecked?: boolean;
|
|
@@ -9,9 +9,9 @@ type LayerXYZTilesOptions = {
|
|
|
9
9
|
};
|
|
10
10
|
declare class LayerXYZ extends Layer {
|
|
11
11
|
source: string;
|
|
12
|
-
constructor(id:
|
|
12
|
+
constructor(id: LayerId, name: string, order: number, source: string, options?: TreeItemDefinition | LayerXYZTilesOptions);
|
|
13
13
|
clone(): LayerXYZ;
|
|
14
|
-
private static
|
|
15
|
-
private static
|
|
14
|
+
private static isTreeItemDefinition;
|
|
15
|
+
private static getOptionsFromDefinition;
|
|
16
16
|
}
|
|
17
17
|
export default LayerXYZ;
|
|
@@ -10,7 +10,7 @@ class LayerXYZ extends Layer {
|
|
|
10
10
|
source;
|
|
11
11
|
constructor(id, name, order, source, options) {
|
|
12
12
|
let opts = options ?? {};
|
|
13
|
-
opts = LayerXYZ.
|
|
13
|
+
opts = LayerXYZ.isTreeItemDefinition(opts) ? LayerXYZ.getOptionsFromDefinition(opts) : opts;
|
|
14
14
|
super(id, name, order, opts);
|
|
15
15
|
this.source = source;
|
|
16
16
|
}
|
|
@@ -26,10 +26,10 @@ class LayerXYZ extends Layer {
|
|
|
26
26
|
clonedObject.activeState = this.activeState;
|
|
27
27
|
return clonedObject;
|
|
28
28
|
}
|
|
29
|
-
static
|
|
29
|
+
static isTreeItemDefinition(options) {
|
|
30
30
|
return 'id' in options;
|
|
31
31
|
}
|
|
32
|
-
static
|
|
32
|
+
static getOptionsFromDefinition(options) {
|
|
33
33
|
return {
|
|
34
34
|
isDefaultChecked: options.metadata?.isChecked,
|
|
35
35
|
metadataUrl: options.metadata?.metadataUrl,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import BaseLayer from './baselayer.js';
|
|
2
2
|
import { Coordinate } from 'ol/coordinate.js';
|
|
3
|
+
import { LayerId } from '../layerdefinitions.js';
|
|
3
4
|
export type ThemeLayerOptions = {
|
|
4
5
|
isDefaultChecked?: boolean;
|
|
5
6
|
disclaimer?: string;
|
|
@@ -15,7 +16,7 @@ declare class ThemeLayer extends BaseLayer {
|
|
|
15
16
|
location?: Coordinate;
|
|
16
17
|
zoom?: number;
|
|
17
18
|
children: BaseLayer[];
|
|
18
|
-
constructor(id:
|
|
19
|
+
constructor(id: LayerId, name: string, order: number, icon?: string, options?: ThemeLayerOptions);
|
|
19
20
|
clone(): ThemeLayer;
|
|
20
21
|
get active(): boolean;
|
|
21
22
|
get inactive(): boolean;
|
package/models/main.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ export { default as BasemapSwisstopoVectorTiles } from './basemaps/basemapswisst
|
|
|
5
5
|
export { default as CustomTheme } from './customtheme.js';
|
|
6
6
|
export type { FilterOperator, AttributeTypeGroup, LogicalFilterOperator } from './filter.js';
|
|
7
7
|
export { filterOperatorValues, filterOperators, isFilterOperator, isValuelessFilterOperator, isTwoSidedFilterOperator, isListFilterOperator, operatorsByAttributeTypeGroup, logicalFilterOperators, isLogicalFilterOperator } from './filter.js';
|
|
8
|
-
export type {
|
|
8
|
+
export type { GeoramaTreeItem, GeoramaTheme } from './georama.js';
|
|
9
|
+
export type { GMFMetadata, GMFChildLayer, GMFTreeItem, GMFThemeFunctionality, GMFThemeFunctionalities, GMFTheme, GMFGroup, GMFServerOgcType, GMFServerOgc, GMFServerOgcAttributes, GMFServerOgcObjectAttributes, GMFServerOgcColumnAttributes } from './gmf.js';
|
|
10
|
+
export type { LayerId, TreeItemDefinition, ThemeDefinition, BasemapDefinition } from './layerdefinitions.js';
|
|
9
11
|
export { default as BaseLayer } from './layers/baselayer.js';
|
|
10
12
|
export type { GroupLayerOptions } from './layers/grouplayer.js';
|
|
11
13
|
export { default as GroupLayer } from './layers/grouplayer.js';
|
package/package.json
CHANGED
package/styles/iframe.css
CHANGED
|
@@ -10,14 +10,15 @@ body {
|
|
|
10
10
|
overflow: hidden;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
girafe-header {
|
|
14
|
+
height: 2.25rem;
|
|
14
15
|
position: absolute;
|
|
15
|
-
top: 0.
|
|
16
|
-
left:
|
|
16
|
+
top: 0.5rem;
|
|
17
|
+
left: 0.5rem;
|
|
17
18
|
z-index: 10;
|
|
18
|
-
|
|
19
|
-
background-color: #fff;
|
|
19
|
+
background-color: var(--bkg-color);
|
|
20
20
|
opacity: 0.5;
|
|
21
|
+
border-radius: 4px;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
#content {
|
package/styles/index.css
CHANGED
package/templates/iframe.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<meta name="description" content="GeoGirafe is
|
|
7
|
+
<meta name="description" content="GeoGirafe is a flexible application to build online geoportals." />
|
|
8
8
|
|
|
9
9
|
<meta name="configs" content="main" />
|
|
10
10
|
<link rel="config-main-url" href="config.json" />
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
<span lang="en">Loading...</span>
|
|
108
108
|
</div>
|
|
109
109
|
<girafe-app>
|
|
110
|
-
<
|
|
110
|
+
<girafe-header></girafe-header>
|
|
111
111
|
|
|
112
112
|
<div id="content">
|
|
113
113
|
<div id="main">
|
package/templates/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<meta name="description" content="GeoGirafe is
|
|
7
|
+
<meta name="description" content="GeoGirafe is a flexible application to build online geoportals." />
|
|
8
8
|
|
|
9
9
|
<!--
|
|
10
10
|
If redirect-url meta tag is present, a redirect will happen when the detected device is an iPhone or Android.
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
<girafe-app>
|
|
115
115
|
<header>
|
|
116
116
|
<girafe-theme-select data-tour="theme-selection"></girafe-theme-select>
|
|
117
|
-
<
|
|
117
|
+
<girafe-header></girafe-header>
|
|
118
118
|
<div class="header-center-align">
|
|
119
119
|
<girafe-search id="search" plugin="config:search">
|
|
120
120
|
<!-- <div slot="search-tooltip">
|
package/templates/mobile.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<html lang="en">
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
|
-
<meta name="description" content="GeoGirafe is
|
|
6
|
+
<meta name="description" content="GeoGirafe is a flexible application to build online geoportals." />
|
|
7
7
|
<meta
|
|
8
8
|
name="viewport"
|
|
9
9
|
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
<span lang="en">Loading...</span>
|
|
81
81
|
</div>
|
|
82
82
|
<girafe-app>
|
|
83
|
+
<girafe-header></girafe-header>
|
|
83
84
|
<div class="bottom-button-container-mobile">
|
|
84
85
|
<girafe-align-north-button-mobile></girafe-align-north-button-mobile>
|
|
85
86
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.2.0-dev.
|
|
1
|
+
{"version":"1.2.0-dev.2854703696", "build":"2854703696", "date":"16/09/2026"}
|
|
@@ -29,6 +29,7 @@ import MobileSelectedLayerElementComponent from '../../components/themes-mobile/
|
|
|
29
29
|
import GetDirectionsArtifact from '../../components/getdirections/component.js';
|
|
30
30
|
import MenuMobileShareButton from '../../components/menu-buttons-mobile/MenuMobileShareButton.js';
|
|
31
31
|
import ShareMobileComponent from '../../components/share-mobile/component.js';
|
|
32
|
+
import HeaderComponent from '../../components/header/component.js';
|
|
32
33
|
export default class GeoGirafeAppMobile extends GeoGirafeApp {
|
|
33
34
|
initializeInterface() {
|
|
34
35
|
if (window.cordova) {
|
|
@@ -54,6 +55,7 @@ export default class GeoGirafeAppMobile extends GeoGirafeApp {
|
|
|
54
55
|
customElements.define('girafe-map', DeprecatedMapComponent);
|
|
55
56
|
customElements.define('girafe-search', MobileSearchComponent);
|
|
56
57
|
customElements.define('girafe-offline', OfflineComponent);
|
|
58
|
+
customElements.define('girafe-header', HeaderComponent);
|
|
57
59
|
customElements.define('girafe-theme-select', MobileThemeComponent);
|
|
58
60
|
customElements.define('girafe-display-selector-button-mobile', DisplaySelectorButtonMobile);
|
|
59
61
|
customElements.define('girafe-display-menu-button-mobile', DisplayMenuButtonMobile);
|
|
@@ -58,6 +58,7 @@ import FeedbackButtonComponent from '../../components/feedbackbutton/component.j
|
|
|
58
58
|
import AddBookmarkComponent from '../../components/addbookmark/component.js';
|
|
59
59
|
import DrawingToolbarComponent from '../../components/drawing-toolbar/component.js';
|
|
60
60
|
import SearchFilterComponent from '../../components/search-filter/component.js';
|
|
61
|
+
import HeaderComponent from '../../components/header/component.js';
|
|
61
62
|
export default class GeoGirafeApp {
|
|
62
63
|
readyPromise;
|
|
63
64
|
resolveReady;
|
|
@@ -108,6 +109,7 @@ export default class GeoGirafeApp {
|
|
|
108
109
|
defineCoreComponents() {
|
|
109
110
|
customElements.define('girafe-about', AboutComponent);
|
|
110
111
|
customElements.define('girafe-advanced-filter', AdvancedFilterComponent);
|
|
112
|
+
customElements.define('girafe-header', HeaderComponent);
|
|
111
113
|
customElements.define('girafe-basemap', BasemapComponent);
|
|
112
114
|
customElements.define('girafe-coordinate', CoordinateComponent);
|
|
113
115
|
customElements.define('girafe-contact', ContactComponent);
|
|
@@ -289,6 +289,14 @@ declare class GirafeConfig {
|
|
|
289
289
|
permalink?: {
|
|
290
290
|
sanitizeConfig?: SanitizeConfig;
|
|
291
291
|
};
|
|
292
|
+
branding: {
|
|
293
|
+
logo: string;
|
|
294
|
+
logoDarkMode: string;
|
|
295
|
+
appTitle: string;
|
|
296
|
+
showAppTitleInHeader: boolean;
|
|
297
|
+
description: string;
|
|
298
|
+
prototypeBanner: boolean;
|
|
299
|
+
};
|
|
292
300
|
extendedConfig?: Record<string, object>;
|
|
293
301
|
static readonly DEFAULT_LOCALE = "en-US";
|
|
294
302
|
/**
|
|
@@ -332,5 +340,6 @@ declare class GirafeConfig {
|
|
|
332
340
|
private initApiConfig;
|
|
333
341
|
private initConfigFiltering;
|
|
334
342
|
private initPermalinkConfig;
|
|
343
|
+
private initBrandingConfig;
|
|
335
344
|
}
|
|
336
345
|
export default GirafeConfig;
|
|
@@ -39,6 +39,7 @@ class GirafeConfig {
|
|
|
39
39
|
feedback;
|
|
40
40
|
filtering;
|
|
41
41
|
permalink;
|
|
42
|
+
branding;
|
|
42
43
|
// The extended configuration can be used by third-party components or extensions
|
|
43
44
|
// to add custom attributes to the GirafeConfig.
|
|
44
45
|
extendedConfig;
|
|
@@ -81,6 +82,7 @@ class GirafeConfig {
|
|
|
81
82
|
this.api = this.initApiConfig(config);
|
|
82
83
|
this.filtering = this.initConfigFiltering(config);
|
|
83
84
|
this.permalink = this.initPermalinkConfig(config);
|
|
85
|
+
this.branding = this.initBrandingConfig(config);
|
|
84
86
|
try {
|
|
85
87
|
this.search = this.initConfigSearch(config);
|
|
86
88
|
}
|
|
@@ -510,5 +512,17 @@ class GirafeConfig {
|
|
|
510
512
|
sanitizeConfig: defaultPermalinkSanitizeConfig
|
|
511
513
|
});
|
|
512
514
|
}
|
|
515
|
+
initBrandingConfig(config) {
|
|
516
|
+
// Logos, title and description fall back to GeoGirafe defaults if not specified
|
|
517
|
+
return {
|
|
518
|
+
logo: config.branding?.logo ?? 'images/logo/horizontal_black.svg',
|
|
519
|
+
logoDarkMode: config.branding?.logoDarkMode ?? config.branding?.logo ?? 'images/logo/horizontal_white.svg',
|
|
520
|
+
appTitle: config.branding?.appTitle ?? 'GeoGirafe',
|
|
521
|
+
showAppTitleInHeader: config.branding?.showAppTitleInHeader ?? false,
|
|
522
|
+
description: config.branding?.description ?? 'GeoGirafe is a flexible application to build online geoportals.',
|
|
523
|
+
// The prototype banner is shown by default
|
|
524
|
+
prototypeBanner: config.branding?.prototypeBanner ?? true
|
|
525
|
+
};
|
|
526
|
+
}
|
|
513
527
|
}
|
|
514
528
|
export default GirafeConfig;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FilterOperator, LogicalFilterOperator } from '../../../models/filter.js';
|
|
2
2
|
import { GMFServerOgcType } from '../../../models/gmf.js';
|
|
3
|
+
import { LayerId } from '../../../models/layerdefinitions.js';
|
|
3
4
|
export type SharedFilterCondition = {
|
|
4
5
|
property: string;
|
|
5
6
|
propertyType?: string;
|
|
@@ -14,7 +15,7 @@ export type SharedFilter = {
|
|
|
14
15
|
};
|
|
15
16
|
export type SharedLayer = SharedInternalTheme | SharedInternalGroup | SharedInternalLayer | SharedExternalTheme | SharedExternalLayer;
|
|
16
17
|
export type SharedInternalTheme = {
|
|
17
|
-
id:
|
|
18
|
+
id: LayerId;
|
|
18
19
|
order: number;
|
|
19
20
|
checked: number;
|
|
20
21
|
isExpanded: number;
|
|
@@ -25,7 +26,7 @@ export type SharedInternalTheme = {
|
|
|
25
26
|
* And should forcefully be added to the layer tree because the user just didn't know this layer when he has created this shared state
|
|
26
27
|
* Or if it was explicitly removed from the user, and then we won't have to display it again
|
|
27
28
|
*/
|
|
28
|
-
excludedChildrenIds:
|
|
29
|
+
excludedChildrenIds: Array<LayerId>;
|
|
29
30
|
/**
|
|
30
31
|
* When configuring the share with "preferNames=true", the name of the layer will be used to generate the sahred state
|
|
31
32
|
* instead of the ID. But in this case, we also have to share the type os the layer, because tha layer name can be
|
|
@@ -38,7 +39,7 @@ export type SharedInternalTheme = {
|
|
|
38
39
|
excludedChildrenNames: string[];
|
|
39
40
|
};
|
|
40
41
|
export type SharedInternalGroup = {
|
|
41
|
-
id:
|
|
42
|
+
id: LayerId;
|
|
42
43
|
order: number;
|
|
43
44
|
checked: number;
|
|
44
45
|
isExpanded: number;
|
|
@@ -50,7 +51,7 @@ export type SharedInternalGroup = {
|
|
|
50
51
|
excludedChildrenNames: string[];
|
|
51
52
|
};
|
|
52
53
|
export type SharedInternalLayer = {
|
|
53
|
-
id:
|
|
54
|
+
id: LayerId;
|
|
54
55
|
order: number;
|
|
55
56
|
checked: number;
|
|
56
57
|
isExpanded: number;
|
|
@@ -87,7 +88,7 @@ export type SharedExternalLayer = {
|
|
|
87
88
|
swiped?: 'left' | 'right' | 'no';
|
|
88
89
|
};
|
|
89
90
|
export type SharedBasemap = {
|
|
90
|
-
id:
|
|
91
|
+
id: LayerId;
|
|
91
92
|
name: string;
|
|
92
93
|
opacity: number;
|
|
93
94
|
};
|
package/tools/state/state.d.ts
CHANGED
|
@@ -13,9 +13,10 @@ import ObjectSelection from './objectselection.js';
|
|
|
13
13
|
import type Theme from '../../models/theme.js';
|
|
14
14
|
import GraphicalInterface from './graphicalInterface.js';
|
|
15
15
|
import { GMFThemeFunctionalities, GMFThemeFunctionality } from '../../models/gmf.js';
|
|
16
|
+
import { LayerId } from '../../models/layerdefinitions.js';
|
|
16
17
|
export type ThemesConfig = {
|
|
17
|
-
_allThemes: Record<
|
|
18
|
-
_allFunctionalities: Record<
|
|
18
|
+
_allThemes: Record<LayerId, ThemeLayer>;
|
|
19
|
+
_allFunctionalities: Record<LayerId, GMFThemeFunctionalities>;
|
|
19
20
|
isLoaded: boolean;
|
|
20
21
|
lastSelectedTheme: ThemeLayer | CustomTheme | null;
|
|
21
22
|
};
|
|
@@ -101,7 +102,7 @@ export default class State {
|
|
|
101
102
|
*/
|
|
102
103
|
themes: ThemesConfig;
|
|
103
104
|
functionalities: Record<string, GMFThemeFunctionality>;
|
|
104
|
-
basemaps: Record<
|
|
105
|
+
basemaps: Record<LayerId, Basemap>;
|
|
105
106
|
ogcServers: Record<string, ServerOgc>;
|
|
106
107
|
activeBasemaps: Basemap[];
|
|
107
108
|
projection: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import GirafeSingleton from '../../base/GirafeSingleton.js';
|
|
2
2
|
import BaseLayer from '../../models/layers/baselayer.js';
|
|
3
|
+
import { LayerId } from '../../models/layerdefinitions.js';
|
|
3
4
|
import GroupLayer from '../../models/layers/grouplayer.js';
|
|
4
5
|
import Layer from '../../models/layers/layer.js';
|
|
5
6
|
import ThemeLayer from '../../models/layers/themelayer.js';
|
|
@@ -10,8 +11,8 @@ export type LayerTreeChanges = {
|
|
|
10
11
|
export default class ThemesHelper extends GirafeSingleton {
|
|
11
12
|
initializeSingleton(): void;
|
|
12
13
|
private get state();
|
|
13
|
-
findBaseLayerById(layerId:
|
|
14
|
-
findBaseLayerRecursiveById(layers: BaseLayer[], layerId:
|
|
14
|
+
findBaseLayerById(layerId: LayerId): BaseLayer;
|
|
15
|
+
findBaseLayerRecursiveById(layers: BaseLayer[], layerId: LayerId): BaseLayer | null;
|
|
15
16
|
findThemeByName(themename: string): ThemeLayer | null;
|
|
16
17
|
findGroupByName(groupname: string): GroupLayer | null;
|
|
17
18
|
findLayerByName(layername: string): Layer | null;
|