UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

487 lines (486 loc) 19.9 kB
// 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;