import * as plugins from '../plugins.js'; import * as shared from '../elements/shared/index.js'; import { DeesElement, customElement, html, state, css, cssManager, property, } from '@design.estate/dees-element'; import * as appstate from '../appstate.js'; @customElement('cloudly-view-settings') export class CloudlyViewSettings extends DeesElement { @state() private settings: plugins.interfaces.data.ICloudlySettingsMasked = {}; @state() private isLoading = false; @state() private testResults: {[key: string]: {success: boolean; message: string}} = {}; constructor() { super(); this.loadSettings(); } public static styles = [ cssManager.defaultStyles, shared.viewHostCss, css` .settings-container { padding: 24px 0; display: flex; flex-direction: column; gap: 16px; } .provider-icon { margin-right: 8px; font-size: 20px; } .test-status { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; } .test-status dees-button { margin-left: auto; } .loading-container { display: flex; justify-content: center; padding: 48px; } .actions-container { display: flex; justify-content: center; margin-top: 24px; } dees-panel { margin-bottom: 16px; } .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; } .form-grid.single { grid-template-columns: 1fr; } @media (max-width: 768px) { .form-grid { grid-template-columns: 1fr; } } `, ]; private async loadSettings() { this.isLoading = true; try { // Use shared API client const response = await appstate.apiClient.settings.getSettings(); this.settings = response.settings; } catch (error) { console.error('Failed to load settings:', error); plugins.deesCatalog.DeesToast.createAndShow({ message: `Failed to load settings: ${error.message}`, type: 'error', }); } finally { this.isLoading = false; } } private async saveSettings(formData: any) { console.log('saveSettings called with formData:', formData); this.isLoading = true; try { const updates: Partial = {}; // Process form data for (const [key, value] of Object.entries(formData)) { console.log(`Processing ${key}:`, value); if (value !== undefined && value !== '****' && !value?.toString().endsWith('****')) { // Only update if value changed (not masked) updates[key as keyof plugins.interfaces.data.ICloudlySettings] = value as string; } } console.log('Updates to send:', updates); const response = await appstate.apiClient.settings.updateSettings(updates); if (response.success) { plugins.deesCatalog.DeesToast.createAndShow({ message: 'Settings saved successfully', type: 'success', }); await this.loadSettings(); // Reload to get masked values } else { throw new Error(response.message); } } catch (error) { console.error('Failed to save settings:', error); plugins.deesCatalog.DeesToast.createAndShow({ message: `Failed to save settings: ${error.message}`, type: 'error', }); } finally { this.isLoading = false; } } private async testConnection(provider: string) { this.isLoading = true; try { const response = await appstate.apiClient.settings.testProviderConnection(provider); this.testResults = { ...this.testResults, [provider]: { success: response.connectionValid, message: response.message } }; // Show toast notification plugins.deesCatalog.DeesToast.createAndShow({ message: response.message, type: response.connectionValid ? 'success' : 'error', }); } catch (error) { this.testResults = { ...this.testResults, [provider]: { success: false, message: `Test failed: ${error.message}` } }; plugins.deesCatalog.DeesToast.createAndShow({ message: `Connection test failed: ${error.message}`, type: 'error', }); } finally { this.isLoading = false; } } private renderProviderStatus(provider: string) { const result = this.testResults[provider]; if (!result) return ''; return html` `; } public render() { if (this.isLoading && Object.keys(this.settings).length === 0) { return html`
`; } return html` Settings
{ console.log('formData event received:', e); console.log('Event detail:', e.detail); console.log('Event detail.data:', e.detail.data); this.saveSettings(e.detail.data); }}>
${this.renderProviderStatus('hetzner')} { e.preventDefault(); e.stopPropagation(); this.testConnection('hetzner'); }} >
${this.renderProviderStatus('cloudflare')} { e.preventDefault(); e.stopPropagation(); this.testConnection('cloudflare'); }} >
${this.renderProviderStatus('aws')} { e.preventDefault(); e.stopPropagation(); this.testConnection('aws'); }} >
${this.renderProviderStatus('digitalocean')} { e.preventDefault(); e.stopPropagation(); this.testConnection('digitalocean'); }} >
${this.renderProviderStatus('azure')} { e.preventDefault(); e.stopPropagation(); this.testConnection('azure'); }} >
${this.renderProviderStatus('google')} { e.preventDefault(); e.stopPropagation(); this.testConnection('google'); }} >
`; } }