UNPKG

hslayers-ng

Version:
315 lines (310 loc) 13 kB
import * as i0 from '@angular/core'; import { Injectable, inject } from '@angular/core'; import { Subject } from 'rxjs'; class HsConfigValidationService { constructor() { /** * Default validation rules for detecting incompatible configuration combinations */ this.defaultValidationRules = [ { condition: (config) => config.defaultComposition && config.panelsEnabled?.compositions === false, message: 'defaultComposition requires compositions panel to be enabled', }, { condition: (config) => config.panelsEnabled?.sensors === true && !config.senslog?.url, message: 'sensors panel requires senslog.url to be configured', }, ]; } /** * Validates configuration for incompatible combinations and returns warning messages * @param config - The configuration object to validate * @param userRules - Optional user-defined validation rules from config * @param useDefaultRules - Whether to include default validation rules (default: true) * @returns Array of warning messages for detected conflicts */ validate(config, userRules, useDefaultRules = true) { const warnings = []; try { // Start with default rules if enabled const allRules = useDefaultRules ? [...this.defaultValidationRules] : []; // Add user rules if provided if (userRules && Array.isArray(userRules)) { userRules.forEach((userRule) => { // Validate user rule if (!userRule.condition || !userRule.message) { console.warn('HsConfigValidation Warning: Invalid validation rule provided. Rule must have condition and message properties.', userRule); return; } allRules.push(userRule); }); } // Run validation with all rules allRules.forEach((rule, index) => { try { if (rule.condition(config)) { warnings.push(`Configuration conflict detected: ${rule.message}`); } } catch (e) { warnings.push(`Error in validation rule #${index + 1}: ${e.message}`); } }); } catch (e) { warnings.push(`Critical error during configuration validation: ${e.message}`); } return warnings; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsConfigValidationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsConfigValidationService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsConfigValidationService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: () => [] }); class HsConfigObject { constructor() { /** * Controls where toast notifications are anchored to * 'screen' - anchors toasts to the viewport * 'map' - anchors toasts to the map container * @default 'map' - anchors toasts to the map container */ this.toastAnchor = 'map'; this.mapSwipeOptions = {}; this.pathExclusivity = false; this.panelsEnabled = { legend: true, compositions: true, measure: true, draw: true, layerManager: true, print: true, saveMap: true, language: true, share: true, query: true, sensors: false, search: true, tripPlanner: false, addData: true, mapSwipe: false, wfsFilter: false, }; this.componentsEnabled = { guiOverlay: true, info: true, sidebar: true, toolbar: true, searchToolbar: true, drawToolbar: true, measureToolbar: true, geolocationButton: true, defaultViewButton: true, mapControls: true, basemapGallery: false, // Says whether it should be activated by default. Is overridden by url param mapSwipe: false, queryPopup: true, }; this.layerEditorWidgetsEnabled = true; this.queryPopupWidgets = ['layer-name', 'feature-info', 'clear-layer']; this.panelWidths = { default: 425, ows: 700, compositions: 550, addData: 700, wfsFilter: 550, mapSwipe: 550, }; this.sidebarPosition = 'right'; this.sidebarToggleable = true; this.mobileBreakpoint = 767; } } class HsConfig extends HsConfigObject { constructor() { super(...arguments); this.validationService = inject(HsConfigValidationService); this.configChanges = new Subject(); this.defaultSymbolizerIcons = [ { name: 'favourite', url: 'img/icons/favourite28.svg' }, { name: 'gps', url: 'img/icons/gps43.svg' }, { name: 'information', url: 'img/icons/information78.svg' }, { name: 'wifi', url: 'img/icons/wifi8.svg' }, ]; } logConfigWarning(message) { console.warn('HsConfig Warning:', message); } /** * Validates configuration for incompatible combinations and logs warnings * @param config - The configuration object to validate * @param userRules - Optional user-defined validation rules * @param useDefaultRules - Whether to use default validation rules */ validateConfigCompatibility(config, userRules, useDefaultRules = true) { const warnings = this.validationService.validate(config, userRules, useDefaultRules); warnings.forEach((warning) => this.logConfigWarning(warning)); } /** * Safely executes a configuration update operation and handles any errors * @param operation - Function to execute * @param errorMessage - Message to log if operation fails * @returns The result of the operation or a fallback value if provided */ safeUpdate(operation, errorMessage, fallback) { try { return operation(); } catch (e) { this.logConfigWarning(`${errorMessage}: ${e.message}`); return fallback; } } checkDeprecatedCesiumConfig(newConfig) { const deprecatedProps = [ 'cesiumDebugShowFramesPerSecond', 'cesiumShadows', 'cesiumBase', 'createWorldTerrainOptions', 'terrain_provider', 'cesiumTimeline', 'cesiumAnimation', 'creditContainer', 'cesiumInfoBox', 'imageryProvider', 'terrainExaggeration', 'cesiumBingKey', 'newTerrainProviderOptions', 'terrain_providers', 'cesiumAccessToken', 'cesiumTime', ]; for (const prop of deprecatedProps) { if (newConfig[prop] != undefined) { console.error(`HsConfig.${prop} has been moved to HsCesiumConfig service or hslayersCesiumConfig.${prop} when using hslayers-cesium-app`); } } } update(newConfig) { try { if (!newConfig) { this.logConfigWarning('Empty configuration provided'); return; } this.checkDeprecatedCesiumConfig(newConfig); // Extract validation settings before processing const userValidationRules = newConfig.configValidationRules; const useDefaultRules = newConfig.useDefaultValidationRules ?? true; if (newConfig.configValidationRules) { delete newConfig.configValidationRules; } if (newConfig.useDefaultValidationRules !== undefined) { delete newConfig.useDefaultValidationRules; } if (newConfig.sidebarPosition === 'bottom') { /**Set high enough value to make sure class setting mobile-view is not toggled*/ newConfig.mobileBreakpoint = 9999; } // Update symbolizer icons with current assets path this.safeUpdate(() => { this.symbolizerIcons = this.defaultSymbolizerIcons.map((val) => ({ ...val, url: (this.assetsPath ?? '') + val.url, })); }, 'Error updating symbolizer icons'); // Update components enabled this.componentsEnabled = this.safeUpdate(() => this.updateComponentsEnabled(newConfig), 'Error updating components enabled', { ...this.componentsEnabled }) ?? this.componentsEnabled; delete newConfig.componentsEnabled; // Update panel widths this.safeUpdate(() => Object.assign(this.panelWidths, newConfig.panelWidths ?? {}), 'Error updating panel widths'); delete newConfig.panelWidths; // Update panels enabled this.safeUpdate(() => Object.assign(this.panelsEnabled, newConfig.panelsEnabled ?? {}), 'Error updating panels enabled'); delete newConfig.panelsEnabled; // Update symbolizer icons this.symbolizerIcons = this.safeUpdate(() => [ ...this.updateSymbolizers(newConfig), ...(newConfig.symbolizerIcons ?? []), ], 'Error updating symbolizers', this.symbolizerIcons) ?? this.symbolizerIcons; delete newConfig.symbolizerIcons; // Merge remaining config this.safeUpdate(() => Object.assign(this, newConfig), 'Error merging configuration'); // Handle assets path if (this.assetsPath == undefined) { this.assetsPath = ''; } this.assetsPath += this.assetsPath.endsWith('/') ? '' : '/'; this.validateConfigCompatibility(this, userValidationRules, useDefaultRules); this.configChanges.next(); } catch (e) { this.logConfigWarning('Critical error updating configuration: ' + e.message); } } /** * Merges componentsEnabled from newConfig with existing componentsEnabled * Preserves the order of keys from newConfig.componentsEnabled */ updateComponentsEnabled(newConfig) { if (!newConfig?.componentsEnabled) { return { ...this.componentsEnabled }; } try { const orderedKeys = new Set([ ...Object.keys(newConfig.componentsEnabled), ...Object.keys(this.componentsEnabled), ]); const mergedComponentsEnabled = {}; orderedKeys.forEach((key) => { mergedComponentsEnabled[key] = newConfig.componentsEnabled[key] ?? this.componentsEnabled[key]; }); return mergedComponentsEnabled; } catch (e) { this.logConfigWarning('Error in updateComponentsEnabled, using defaults: ' + e.message); return { ...this.componentsEnabled }; } } updateSymbolizers(config) { try { let assetsPath = config.assetsPath ?? ''; assetsPath += assetsPath.endsWith('/') ? '' : '/'; return this.defaultSymbolizerIcons.map((val) => ({ ...val, url: assetsPath + val.url, })); } catch (e) { this.logConfigWarning('Error in updateSymbolizers: ' + e.message); return [...this.defaultSymbolizerIcons]; } } setAppId(id) { this.id = id; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsConfig, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsConfig, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsConfig, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); /** * Generated bundle index. Do not edit. */ export { HsConfig, HsConfigObject, HsConfigValidationService }; //# sourceMappingURL=hslayers-ng-config.mjs.map