import { DEFAULT_ACTIVITIES, DEFAULT_CONFIG } from './constants.js'; /** * Manages card configuration, including merging defaults with user config */ export class ConfigManager { constructor() { this._config = null; } /** * Validates and sets the configuration * @param {Object} config - User configuration * @throws {Error} If entities are not defined */ setConfig(config) { if (!config.entities || !Array.isArray(config.entities)) { throw new Error('You need to define entities'); } const mergedActivities = this._mergeActivities(config.activities); this._config = { entities: config.entities, map_provider: config.map_provider || DEFAULT_CONFIG.map_provider, google_api_key: config.google_api_key || DEFAULT_CONFIG.google_api_key, map_type: config.map_type || DEFAULT_CONFIG.map_type, default_zoom: config.default_zoom || DEFAULT_CONFIG.default_zoom, update_interval: config.update_interval || DEFAULT_CONFIG.update_interval, marker_border_radius: config.marker_border_radius || DEFAULT_CONFIG.marker_border_radius, badge_border_radius: config.badge_border_radius || DEFAULT_CONFIG.badge_border_radius, marker_size: config.marker_size || DEFAULT_CONFIG.marker_size, use_predicted_activity: config.use_predicted_activity || DEFAULT_CONFIG.use_predicted_activity, activity_source: config.activity_source || DEFAULT_CONFIG.activity_source, zones: config.zones || DEFAULT_CONFIG.zones, activities: mergedActivities, debug: config.debug || DEFAULT_CONFIG.debug }; return this._config; } /** * Merges user activity colors with default activity icons and names * @param {Object} userActivities - User-provided activity configurations * @returns {Object} Merged activity configurations */ _mergeActivities(userActivities) { const activities = {}; Object.keys(DEFAULT_ACTIVITIES).forEach(key => { activities[key] = { icon: DEFAULT_ACTIVITIES[key].icon, name: DEFAULT_ACTIVITIES[key].name, color: (userActivities && userActivities[key] && userActivities[key].color) ? userActivities[key].color : DEFAULT_ACTIVITIES[key].color }; }); return activities; } /** * Checks if specific config properties have changed * @param {Object} oldConfig - Previous configuration * @param {Array} properties - Properties to check * @returns {boolean} True if any property changed */ hasChanged(oldConfig, properties) { if (!oldConfig) return false; return properties.some(prop => { return JSON.stringify(oldConfig[prop]) !== JSON.stringify(this._config[prop]); }); } /** * Gets the current configuration * @returns {Object} Current configuration */ getConfig() { return this._config; } /** * Builds URL parameters for the iframe * @returns {URLSearchParams} URL parameters */ buildIframeParams() { if (!this._config) { throw new Error('Configuration not set'); } const params = new URLSearchParams({ provider: this._config.map_provider, apikey: this._config.google_api_key || '', maptype: this._config.map_type, zoom: this._config.default_zoom, mode: 'proxy', debug: this._config.debug ? '1' : '0' }); // Add entities const entitiesParam = this._config.entities .map(e => `${e.person}${e.activity ? ':' + e.activity : ''}`) .join(','); params.append('entities', entitiesParam); // Add zones (only colors) const zonesParam = Object.entries(this._config.zones) .map(([state, config]) => `${state}:${encodeURIComponent(config.color)}`) .join(','); params.append('zones', zonesParam); // Add activities const activitiesParam = Object.entries(this._config.activities) .map(([state, config]) => `${state}:${config.icon}:${encodeURIComponent(config.color)}:${encodeURIComponent(config.name)}`) .join(','); params.append('activities', activitiesParam); // Add border radius params.append('marker_radius', encodeURIComponent(this._config.marker_border_radius)); params.append('badge_radius', encodeURIComponent(this._config.badge_border_radius)); params.append('marker_size', encodeURIComponent(this._config.marker_size)); return params; } /** * Gets a stub configuration for initial setup * @returns {Object} Stub configuration */ static getStubConfig() { return { ...DEFAULT_CONFIG }; } }