/** * ds-figma-status.js * Figma integration status and sync controls */ import toolBridge from '../../services/tool-bridge.js'; import { ComponentHelpers } from '../../utils/component-helpers.js'; class DSFigmaStatus extends HTMLElement { constructor() { super(); this.figmaToken = null; this.figmaFileKey = null; this.connectionStatus = 'unknown'; this.lastSync = null; this.isConfiguring = false; this.isSyncing = false; } async connectedCallback() { this.render(); this.setupEventListeners(); await this.checkConfiguration(); } /** * Check if Figma is configured and test connection */ async checkConfiguration() { const statusContent = this.querySelector('#figma-status-content'); if (!statusContent) return; try { // Check for stored file key in localStorage (not token - that's server-side) this.figmaFileKey = localStorage.getItem('figma_file_key'); if (!this.figmaFileKey) { this.connectionStatus = 'not_configured'; this.renderStatus(); return; } // Test connection by calling sync with dry-run check // Note: Backend checks for FIGMA_TOKEN env variable statusContent.innerHTML = ComponentHelpers.renderLoading('Checking Figma connection...'); try { // Try to get Figma file info (will fail if token not configured) const result = await toolBridge.syncFigma(this.figmaFileKey); if (result && result.tokens) { this.connectionStatus = 'connected'; this.lastSync = new Date(); } else { this.connectionStatus = 'error'; } } catch (error) { // Token not configured on backend if (error.message.includes('FIGMA_TOKEN')) { this.connectionStatus = 'token_missing'; } else { this.connectionStatus = 'error'; } console.error('Figma connection check failed:', error); } this.renderStatus(); } catch (error) { console.error('Failed to check Figma configuration:', error); statusContent.innerHTML = ComponentHelpers.renderError('Failed to check configuration', error); } } setupEventListeners() { // Configure button const configureBtn = this.querySelector('#figma-configure-btn'); if (configureBtn) { configureBtn.addEventListener('click', () => this.showConfiguration()); } // Sync button const syncBtn = this.querySelector('#figma-sync-btn'); if (syncBtn) { syncBtn.addEventListener('click', () => this.syncFromFigma()); } } showConfiguration() { this.isConfiguring = true; this.renderStatus(); // Setup save handler const saveBtn = this.querySelector('#figma-save-config-btn'); const cancelBtn = this.querySelector('#figma-cancel-config-btn'); if (saveBtn) { saveBtn.addEventListener('click', () => this.saveConfiguration()); } if (cancelBtn) { cancelBtn.addEventListener('click', () => { this.isConfiguring = false; this.renderStatus(); }); } } async saveConfiguration() { const fileKeyInput = this.querySelector('#figma-file-key-input'); const tokenInput = this.querySelector('#figma-token-input'); if (!fileKeyInput || !tokenInput) return; const fileKey = fileKeyInput.value.trim(); const token = tokenInput.value.trim(); if (!fileKey) { ComponentHelpers.showToast?.('Please enter a Figma file key', 'error'); return; } if (!token) { ComponentHelpers.showToast?.('Please enter a Figma access token', 'error'); return; } try { // Store file key in localStorage (client-side) localStorage.setItem('figma_file_key', fileKey); this.figmaFileKey = fileKey; // Display warning about backend token configuration ComponentHelpers.showToast?.('File key saved. Please configure FIGMA_TOKEN environment variable on the backend.', 'info'); this.isConfiguring = false; this.connectionStatus = 'token_missing'; this.renderStatus(); } catch (error) { console.error('Failed to save Figma configuration:', error); ComponentHelpers.showToast?.(`Failed to save configuration: ${error.message}`, 'error'); } } async syncFromFigma() { if (this.isSyncing || !this.figmaFileKey) return; this.isSyncing = true; const syncBtn = this.querySelector('#figma-sync-btn'); if (syncBtn) { syncBtn.disabled = true; syncBtn.textContent = '🔄 Syncing...'; } try { const result = await toolBridge.syncFigma(this.figmaFileKey); if (result && result.tokens) { this.lastSync = new Date(); this.connectionStatus = 'connected'; ComponentHelpers.showToast?.( `Synced ${Object.keys(result.tokens).length} tokens from Figma`, 'success' ); this.renderStatus(); } else { throw new Error('No tokens returned from Figma'); } } catch (error) { console.error('Failed to sync from Figma:', error); ComponentHelpers.showToast?.(`Sync failed: ${error.message}`, 'error'); this.connectionStatus = 'error'; this.renderStatus(); } finally { this.isSyncing = false; if (syncBtn) { syncBtn.disabled = false; syncBtn.textContent = '🔄 Sync Now'; } } } getStatusBadge() { const badges = { connected: ComponentHelpers.createBadge('Connected', 'success'), not_configured: ComponentHelpers.createBadge('Not Configured', 'info'), token_missing: ComponentHelpers.createBadge('Token Required', 'warning'), error: ComponentHelpers.createBadge('Error', 'error'), unknown: ComponentHelpers.createBadge('Unknown', 'info') }; return badges[this.connectionStatus] || badges.unknown; } renderStatus() { const statusContent = this.querySelector('#figma-status-content'); if (!statusContent) return; // Configuration form if (this.isConfiguring) { statusContent.innerHTML = `

Configure Figma Integration

Find this in your Figma file URL: figma.com/file/FILE_KEY/...
Generate at: figma.com/developers/api
⚠️ Security Note: The Figma token must be configured as the FIGMA_TOKEN environment variable on the backend server. This UI only stores the file key locally.
`; return; } // Not configured state if (this.connectionStatus === 'not_configured') { statusContent.innerHTML = `
🎨

Figma Not Configured

Connect your Figma file to sync design tokens automatically.

`; const configureBtn = statusContent.querySelector('#figma-configure-btn'); if (configureBtn) { configureBtn.addEventListener('click', () => this.showConfiguration()); } return; } // Token missing state if (this.connectionStatus === 'token_missing') { statusContent.innerHTML = `

Figma Configuration

${this.getStatusBadge()}
⚠️ Backend Configuration Required
Please set the FIGMA_TOKEN environment variable on the backend server and restart.
File Key: ${ComponentHelpers.escapeHtml(this.figmaFileKey || 'N/A')}
`; const configureBtn = statusContent.querySelector('#figma-configure-btn'); if (configureBtn) { configureBtn.addEventListener('click', () => this.showConfiguration()); } return; } // Connected state if (this.connectionStatus === 'connected') { statusContent.innerHTML = `

Figma Sync

${this.getStatusBadge()}
File Key: ${ComponentHelpers.escapeHtml(this.figmaFileKey || 'N/A')}
${this.lastSync ? `
Last Sync: ${ComponentHelpers.formatRelativeTime(this.lastSync)}
` : ''}
`; const syncBtn = statusContent.querySelector('#figma-sync-btn'); const configureBtn = statusContent.querySelector('#figma-configure-btn'); if (syncBtn) { syncBtn.addEventListener('click', () => this.syncFromFigma()); } if (configureBtn) { configureBtn.addEventListener('click', () => this.showConfiguration()); } return; } // Error state if (this.connectionStatus === 'error') { statusContent.innerHTML = `

Figma Sync

${this.getStatusBadge()}
❌ Failed to connect to Figma. Please check your configuration.
`; const configureBtn = statusContent.querySelector('#figma-configure-btn'); const syncBtn = statusContent.querySelector('#figma-sync-btn'); if (configureBtn) { configureBtn.addEventListener('click', () => this.showConfiguration()); } if (syncBtn) { syncBtn.addEventListener('click', () => this.checkConfiguration()); } } } render() { this.innerHTML = `
${ComponentHelpers.renderLoading('Checking Figma configuration...')}
`; } } customElements.define('ds-figma-status', DSFigmaStatus); export default DSFigmaStatus;