@geogirafe/lib-geoportal
Version:
GeoGirafe is a flexible application to build online geoportals.
487 lines (486 loc) • 19.9 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
export var HighlightMode;
(function (HighlightMode) {
HighlightMode["HighlightAll"] = "highlight-all";
HighlightMode["HighlightPerLayer"] = "highlight-per-layer";
})(HighlightMode || (HighlightMode = {}));
import { defaultNewsSanitizeConfig, defaultPermalinkSanitizeConfig, defaultQuerySanitizeConfig } from './sanitizeconfig-defaults.js';
class GirafeConfig {
general;
languages;
interface;
themes;
basemaps;
treeview;
search;
print;
selection;
drawing;
share;
projections;
map;
map3d;
lidar;
news;
externalLayers;
contextmenu;
crs;
csv;
infoWindow;
offline;
query;
gmfauth;
oauth;
userdata;
contact;
onboarding;
api;
feedback;
filtering;
permalink;
// The extended configuration can be used by third-party components or extensions
// to add custom attributes to the GirafeConfig.
extendedConfig;
static DEFAULT_LOCALE = 'en-US';
/**
* Creates the configuration of the app validating the json passed or giving default values.
*
* Every property of config that is not complying with GirafeConfig type is ignored.
* @param config the configuration
*/
constructor(config) {
// Default values are documented here : https://doc.geogirafe.org/docs/configuration
// NOTE: Please adapt the documentation if necessary when doing changes here.
this.general = this.initConfigGeneral(config);
this.languages = this.initConfigLanguages(config);
this.interface = this.initConfigInterface(config);
this.themes = this.initConfigThemes(config);
this.basemaps = this.initConfigBasemaps(config);
this.treeview = this.initConfigTreeview(config);
this.selection = this.initConfigSelection(config);
this.drawing = this.initConfigDrawing(config);
this.projections = this.initConfigProjections(config);
this.map = this.initConfigMap(config);
this.news = this.initConfigNews(config);
this.lidar = this.initConfigLidar(config);
this.csv = this.initConfigCsv(config);
this.infoWindow = this.initConfigInfoWindow(config);
this.offline = this.initConfigOffline(config);
this.query = this.initConfigQuery(config);
this.oauth = this.initConfigOauth(config);
this.gmfauth = this.initGmfOauth(config);
this.userdata = this.initUserData(config);
this.externalLayers = this.initExternalLayers(config);
this.contextmenu = this.initContextMenu(config);
this.crs = this.initCRS(config);
this.contact = this.initConfigContact(config);
this.extendedConfig = this.initExtendedConfig(config);
this.onboarding = this.initOnboarding(config);
this.feedback = this.initFeedback(config);
this.api = this.initApiConfig(config);
this.filtering = this.initConfigFiltering(config);
this.permalink = this.initPermalinkConfig(config);
try {
this.search = this.initConfigSearch(config);
}
catch (e) {
// The application can be started even if the search is not correctly configured
// We just display a warning in the console
console.warn(e);
this.search = { providers: [{ type: 'geomapfish', url: '', resultSrid: this.map.srid }] };
}
try {
this.share = this.initConfigShare(config);
}
catch (e) {
// The application can be started even if the search is not correctly configured
// We just display a warning in the console
console.warn(e);
}
try {
this.print = this.initConfigPrint(config);
}
catch (e) {
// The application can be started even if the print is not correctly configured
// We just display a warning in the console
console.warn(e);
}
try {
this.map3d = this.initConfigMap3D(config);
}
catch (e) {
// The application can be started even if the 3D Part is not correctly configured
// We just display a warning in the console
console.warn(e);
}
try {
this.news = this.initConfigNews(config);
}
catch (e) {
// The application can be started even if the news is not correctly configured
// We just display a warning in the console
console.warn(e);
}
}
initConfigProjections(config) {
if (!config.projections) {
throw new Error(`Configuration for projections is required. See https://doc.geogirafe.org/docs/configuration`);
}
return config.projections;
}
initConfigMap3D(config) {
return config.map3d;
}
initConfigMap(config) {
// Map
if (!config.map?.srid) {
throw new Error(`Configuration for projections is required. See https://doc.geogirafe.org/docs/configuration`);
}
if (!config.map?.scales) {
throw new Error(`Configuration for projections is required. See https://doc.geogirafe.org/docs/configuration`);
}
if (!config.map?.startPosition) {
throw new Error(`Configuration for projections is required. See https://doc.geogirafe.org/docs/configuration`);
}
if (!config.map?.startZoom) {
throw new Error(`Configuration for projections is required. See https://doc.geogirafe.org/docs/configuration`);
}
return {
srid: config.map.srid,
startZoom: config.map.startZoom,
startPosition: config.map.startPosition,
maxExtent: config.map.maxExtent,
scales: config.map.scales,
constrainScales: config.map?.constrainScales ?? true,
constrainRotation: config.map?.constrainRotation ?? false,
showScaleLine: config.map?.showScaleLine ?? true
};
}
initConfigQuery(config) {
return {
legacy: config.query?.legacy ?? false,
sanitizeConfig: config.query?.sanitizeConfig ?? defaultQuerySanitizeConfig
};
}
initConfigDrawing(config) {
return {
defaultFillColor: config.drawing?.defaultFillColor ?? '#6666ff7f',
defaultStrokeColor: config.drawing?.defaultStrokeColor ?? '#0000ff',
defaultStrokeWidth: config.drawing?.defaultStrokeWidth ?? 2,
defaultTextSize: config.drawing?.defaultTextSize ?? 12,
defaultFont: config.drawing?.defaultFont ?? 'Arial',
defaultVertexRadius: config.drawing?.defaultVertexRadius ?? 8,
defaultVertexFillColor: config.drawing?.defaultVertexFillColor ?? '#ffffffbf',
defaultVertexStrokeWidth: config.drawing?.defaultVertexStrokeWidth ?? 2
};
}
initConfigShare(config) {
if (!config.share) {
return undefined;
}
if (!config.share?.createUrl) {
throw new Error(`Configuration for share.createUrl is required. See https://doc.geogirafe.org/docs/configuration`);
}
if (config.share?.service === 'geogirafe' && !config.share?.getUrl) {
throw new Error(`Configuration for share.getUrl is required if service type is 'geogirafe'. See https://doc.geogirafe.org/docs/configuration`);
}
return {
service: config.share?.service ?? 'gmf',
preferNames: config.share?.preferNames ?? false,
createUrl: config.share?.createUrl,
getUrl: config.share?.getUrl,
iframeBaseUrl: config.share?.iframeBaseUrl
};
}
initConfigSelection(config) {
return {
maxFeature: config.selection?.maxFeature ?? 300,
defaultFillColor: config.selection?.defaultFillColor ?? '#ff66667f',
defaultStrokeColor: config.selection?.defaultStrokeColor ?? '#ff3333',
defaultStrokeWidth: config.selection?.defaultStrokeWidth ?? 4,
highlightFillColor: config.selection?.highlightFillColor ?? '#00ff227f',
highlightStrokeColor: config.selection?.highlightStrokeColor ?? '#00ff22',
defaultHighlightMode: config.selection?.defaultHighlightMode ?? HighlightMode.HighlightAll
};
}
initConfigPrint(config) {
if (!config.print) {
return undefined;
}
if (!config.print?.url) {
throw new Error(`Configuration for print.url is required. See https://doc.geogirafe.org/docs/configuration`);
}
config.print.attributeNames ??= ['title', 'comments', 'legend'];
config.print.formats ??= ['pdf', 'png'];
return config.print;
}
initConfigSearch(config) {
if (!config.search) {
return undefined;
}
const providers = [];
for (const provider of config.search.providers ?? []) {
if (provider.type === 'geomapfish') {
if (!provider.url.includes('###SEARCHTERM###')) {
throw new Error(`Search provider url of type "geomapfish" is missing the expected pattern. See https://doc.geogirafe.org/docs/configuration`);
}
providers.push({
type: provider.type,
providerName: provider.providerName ?? provider.type,
url: provider.url,
resultSrid: provider.resultSrid ?? config.map.srid
});
}
else if (provider.type === 'geoadminch') {
providers.push({
type: provider.type,
providerName: provider.providerName ?? provider.type,
bbox: provider.bbox,
locationOrigins: provider.locationOrigins
});
}
else {
console.warn(`Provider type is missing or not valid: ${provider['type']}`);
}
}
if (providers.length === 0) {
console.warn('No search provider configured. Search will not be available.');
}
return {
providers: providers,
objectPreview: config.search.objectPreview ?? false,
layerPreview: config.search.layerPreview ?? false,
minResolution: config.search.minResolution ?? 0.5,
defaultFillColor: config.search.defaultFillColor ?? '#3388ff7f',
defaultStrokeColor: config.search.defaultStrokeColor ?? '#3388ff',
defaultStrokeWidth: config.search.defaultStrokeWidth ?? 2,
paintSearchResults: config.search.paintSearchResults ?? true
};
}
initConfigTreeview(config) {
return {
hideLegendWhenLayerIsDeactivated: config.treeview?.hideLegendWhenLayerIsDeactivated ?? true,
defaultIconSize: {
height: config.treeview?.defaultIconSize?.height ?? 20,
width: config.treeview?.defaultIconSize?.width ?? 20
}
};
}
initConfigBasemaps(config) {
return {
show: config.basemaps?.show ?? true,
defaultBasemap: config.basemaps?.defaultBasemap ?? 'Empty',
OSM: config.basemaps?.OSM ?? false,
SwissTopoVectorTiles: config.basemaps?.SwissTopoVectorTiles ?? false,
emptyBasemap: config.basemaps?.emptyBasemap ?? true,
opacityBasemaps: config.basemaps?.opacityBasemaps ?? []
};
}
initConfigLidar(config) {
return config.lidar;
}
initConfigNews(config) {
if (!config.news) {
return undefined;
}
if (config.news.sanitizeConfig) {
return config.news;
}
return {
...config.news,
sanitizeConfig: defaultNewsSanitizeConfig
};
}
initConfigCsv(config) {
const defaultConfig = {
encoding: 'utf-8',
extension: '.csv',
includeHeader: true,
quote: "'",
separator: ';' /* Switched to ';' as ',' wasn't working with MS Excel out of the Box (double-click on the file) while for example LibreOffice works with both*/
};
return {
...defaultConfig,
...config.csv
};
}
initConfigInfoWindow(config) {
const defaultConfig = {
defaultWindowWidth: '960px',
defaultWindowHeight: '460px',
defaultWindowPositionTop: '1rem',
defaultWindowPositionLeft: '370px'
};
return {
...defaultConfig,
...config.infoWindow
};
}
initConfigContact(config) {
return config.contact;
}
initConfigOffline(config) {
// This can be null, that's not a problem. No default value either.
return config.offline;
}
initConfigThemes(config) {
if (!config.themes?.url) {
throw new Error(`Configuration for themes.url is required. See https://doc.geogirafe.org/docs/configuration.`);
}
return {
url: config.themes.url,
defaultTheme: config.themes.defaultTheme ?? '',
imagesUrlPrefix: config.themes.imagesUrlPrefix ?? '',
showErrorsOnStart: config.themes.showErrorsOnStart ?? false,
selectionMode: config.themes.selectionMode ?? 'replace'
};
}
initConfigLanguages(config) {
if (!config.languages) {
throw new Error(`Configuration for languages is required. See https://doc.geogirafe.org/docs/configuration.`);
}
return config.languages;
}
initConfigInterface(config) {
const defaultConfig = {
defaultSelectionComponent: 'window',
darkFrontendMode: undefined,
darkMapMode: false
};
return {
...defaultConfig,
...config.interface
};
}
initConfigGeneral(config) {
return {
locale: config.general.locale ?? GirafeConfig.DEFAULT_LOCALE,
defaultUrlPrefix: config.general.defaultUrlPrefix ?? '',
// NOTE REG: Small hack specific to Vite: When running in debug mode, we force the logLevel to debug.
// Otherwise we will always have to manually activate it.
logLevel: import.meta?.env?.DEV ? 'debug' : (config.general.logLevel ?? 'warn')
};
}
initGmfOauth(config) {
if (!config.gmfauth) {
// No GMF-Auth configuration
return undefined;
}
if (!config.gmfauth.url) {
throw new Error(`Configuration for gmfauth.url is required. See https://doc.geogirafe.org/docs/configuration.`);
}
let gmfauthUrl = config.gmfauth.url;
if (!config.gmfauth.url.endsWith('/')) {
gmfauthUrl = `${config.gmfauth.url}/`;
}
if (!config.gmfauth.audience) {
throw new Error(`Configuration for gmfauth.audience is required. See https://doc.geogirafe.org/docs/configuration.`);
}
return {
url: gmfauthUrl,
audience: config.gmfauth.audience,
loginRequired: config.gmfauth.loginRequired ?? false,
checkSessionOnLoad: config.gmfauth.checkSessionOnLoad ?? true,
authMode: 'cookie',
alwaysSendCookies: config.gmfauth.alwaysSendCookies ?? false,
refererPolicy: config.gmfauth.refererPolicy ?? 'strict-origin-when-cross-origin',
audienceExcludedPaths: config.gmfauth.audienceExcludedPaths ?? []
};
}
initConfigOauth(config) {
if (!config.oauth) {
// No oAuth configuration
return undefined;
}
if (!config.oauth.issuer.url) {
throw new Error(`Configuration for oauth.issuer.url is required. See https://doc.geogirafe.org/docs/configuration.`);
}
if (!config.oauth.issuer.clientId) {
throw new Error(`Configuration for oauth.issuer.clientId is required. See https://doc.geogirafe.org/docs/configuration.`);
}
if (!config.oauth.issuer.audience) {
throw new Error(`Configuration for oauth.issuer.audience is required. See https://doc.geogirafe.org/docs/configuration.`);
}
if (!config.oauth.geomapfish.userInfoUrl) {
throw new Error(`Configuration for oauth.geomapfish.userInfoUrl is required. See https://doc.geogirafe.org/docs/configuration.`);
}
const issuerConfig = {
url: config.oauth.issuer.url,
algorithm: config.oauth.issuer.algorithm ?? 'oidc',
codeChallengeMethod: config.oauth.issuer.codeChallengeMethod ?? 'S256',
clientId: config.oauth.issuer.clientId,
scope: config.oauth.issuer.scope ?? 'openid',
loginRequired: config.oauth.issuer.loginRequired ?? false,
checkSessionOnLoad: config.oauth.issuer.checkSessionOnLoad ?? false,
audience: config.oauth.issuer.audience,
audienceExcludedPaths: config.oauth.issuer.audienceExcludedPaths ?? [],
alwaysSendCookies: config.oauth.issuer.alwaysSendCookies ?? false,
customSilentLoginParams: config.oauth.issuer.customSilentLoginParams ?? {},
customLoginParams: config.oauth.issuer.customLoginParams ?? {}
};
const geomapfishConfig = {
userInfoUrl: config.oauth.geomapfish.userInfoUrl,
loginUrl: config.oauth.geomapfish.loginUrl,
logoutUrl: config.oauth.geomapfish.logoutUrl,
anonymousUsername: config.oauth.geomapfish.anonymousUsername,
authMode: config.oauth.geomapfish.authMode ?? 'cookie',
refererPolicy: config.oauth.geomapfish.refererPolicy ?? 'strict-origin-when-cross-origin'
};
return {
issuer: issuerConfig,
geomapfish: geomapfishConfig
};
}
initUserData(config) {
const defaultConfig = {
source: 'localStorage'
};
return {
...defaultConfig,
...config.userdata
};
}
initContextMenu(config) {
const contextMenuConfig = {
crs: config.contextmenu?.crs ?? [
{ code: 'EPSG:4326', translation: 'EPSG:4326', format: 'decimal', precision: 7 },
{ code: 'EPSG:4326', translation: 'EPSG:4326-DMS', format: 'dms', precision: 2 }
],
sources: config.contextmenu?.sources ?? [],
links: config.contextmenu?.links ?? []
};
return contextMenuConfig;
}
initCRS(config) {
return config.crs;
}
initExternalLayers(config) {
return config.externalLayers ?? undefined;
}
initExtendedConfig(config) {
return config.extendedConfig ?? undefined;
}
initOnboarding(config) {
return config.onboarding ?? undefined;
}
initFeedback(config) {
return config.feedback ?? undefined;
}
initApiConfig(config) {
return config.api ?? undefined;
}
initConfigFiltering(config) {
if (config.filtering?.gmfLayerMetadataUrl &&
!(config.filtering.gmfLayerMetadataUrl.includes('###LAYERNAME###') &&
config.filtering.gmfLayerMetadataUrl.includes('###ATTRIBUTENAME###'))) {
throw new Error(`Configuration for filtering.gmfLayerMetadataUrl is missing the expected pattern. See https://doc.geogirafe.org/docs/configuration`);
}
return config.filtering ?? undefined;
}
initPermalinkConfig(config) {
return (config.permalink ?? {
sanitizeConfig: defaultPermalinkSanitizeConfig
});
}
}
export default GirafeConfig;