- -
- -

Discord Bot Dashboard

- -
+ +
- -
- - -
+
-

Manage Server Settings

-

Settings for the selected server.

+

Bot Status

+

Current status of your custom Discord bot

- -
- -
-
-
-

Prefix Settings

+
+
+
+ Checking status...
-
- -
- - -
-

+
+ +
+
-
- - +
- - - - - - - - - - + + + diff --git a/api_service/dashboard_web/js/custom-bot.js b/api_service/dashboard_web/js/custom-bot.js index 90cc6b7..bb4d645 100644 --- a/api_service/dashboard_web/js/custom-bot.js +++ b/api_service/dashboard_web/js/custom-bot.js @@ -1,6 +1,6 @@ /** - * Custom Bot Management - * This module handles the custom bot functionality in the dashboard. + * Custom Bot Configuration Dashboard + * Streamlined interface for bot setup and management */ // Status constants @@ -22,11 +22,14 @@ let stopBotButton; let statusDot; let statusText; let botError; +let botConfigFeedback; /** * Initialize the custom bot functionality */ function initCustomBot() { + console.log('Initializing custom bot dashboard...'); + // Get DOM elements botTokenInput = document.getElementById('bot-token-input'); botPrefixInput = document.getElementById('bot-prefix-input'); @@ -38,6 +41,7 @@ function initCustomBot() { statusDot = document.getElementById('status-dot'); statusText = document.getElementById('status-text'); botError = document.getElementById('bot-error'); + botConfigFeedback = document.getElementById('bot-config-feedback'); // Add event listeners if (saveBotConfigButton) { @@ -65,27 +69,43 @@ function initCustomBot() { */ async function loadCustomBotSettings() { try { - const response = await API.get('/dashboard/api/settings'); - + console.log('Loading custom bot settings...'); + const response = await fetch('/dashboard/api/settings', { + method: 'GET', + credentials: 'include', + headers: { + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + console.log('Loaded bot settings:', data); + // Fill in the form fields - if (botTokenInput && response.custom_bot_token) { - botTokenInput.value = response.custom_bot_token; + if (botTokenInput && data.custom_bot_token) { + botTokenInput.value = data.custom_bot_token; } - + if (botPrefixInput) { - botPrefixInput.value = response.custom_bot_prefix || '!'; + botPrefixInput.value = data.custom_bot_prefix || '!'; } - + if (botStatusTypeSelect) { - botStatusTypeSelect.value = response.custom_bot_status_type || 'listening'; + botStatusTypeSelect.value = data.custom_bot_status_type || 'listening'; } - + if (botStatusTextInput) { - botStatusTextInput.value = response.custom_bot_status_text || '!help'; + botStatusTextInput.value = data.custom_bot_status_text || '!help'; } + + showFeedback('Bot settings loaded successfully', false); } catch (error) { console.error('Error loading custom bot settings:', error); - Toast.error('Failed to load custom bot settings'); + showFeedback('Failed to load custom bot settings: ' + error.message, true); } } @@ -94,44 +114,58 @@ async function loadCustomBotSettings() { */ async function saveCustomBotConfig() { try { + console.log('Saving custom bot configuration...'); + // Validate inputs - if (!botTokenInput.value) { - Toast.error('Bot token is required'); + if (!botTokenInput.value.trim()) { + showFeedback('Bot token is required', true); return; } - if (!botPrefixInput.value) { - Toast.error('Command prefix is required'); + if (!botPrefixInput.value.trim()) { + showFeedback('Command prefix is required', true); return; } - if (!botStatusTextInput.value) { - Toast.error('Status text is required'); + if (!botStatusTextInput.value.trim()) { + showFeedback('Status text is required', true); return; } - // Get current settings first - const currentSettings = await API.get('/dashboard/api/settings'); - - // Prepare the settings object with updated bot settings + // Prepare the settings object const settings = { - ...currentSettings, - custom_bot_token: botTokenInput.value, - custom_bot_prefix: botPrefixInput.value, + custom_bot_token: botTokenInput.value.trim(), + custom_bot_prefix: botPrefixInput.value.trim(), custom_bot_status_type: botStatusTypeSelect.value, - custom_bot_status_text: botStatusTextInput.value + custom_bot_status_text: botStatusTextInput.value.trim() }; + console.log('Sending bot configuration:', settings); + // Save the settings - await API.put('/dashboard/api/settings', settings); - - Toast.success('Custom bot configuration saved successfully'); - + const response = await fetch('/dashboard/api/settings', { + method: 'PUT', + credentials: 'include', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(settings) + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + console.log('Bot configuration saved:', result); + + showFeedback('Custom bot configuration saved successfully', false); + // Check bot status after saving - checkBotStatus(); + setTimeout(checkBotStatus, 1000); } catch (error) { console.error('Error saving custom bot configuration:', error); - Toast.error('Failed to save custom bot configuration'); + showFeedback('Failed to save custom bot configuration: ' + error.message, true); } } @@ -140,19 +174,33 @@ async function saveCustomBotConfig() { */ async function startCustomBot() { try { + console.log('Starting custom bot...'); startBotButton.disabled = true; startBotButton.textContent = 'Starting...'; - - await API.post('/dashboard/api/custom-bot/start'); - - Toast.success('Custom bot started successfully'); - + + const response = await fetch('/dashboard/api/custom-bot/start', { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + console.log('Bot start result:', result); + + showFeedback('Custom bot started successfully', false); + // Check bot status after starting - checkBotStatus(); + setTimeout(checkBotStatus, 2000); } catch (error) { console.error('Error starting custom bot:', error); - Toast.error('Failed to start custom bot: ' + (error.response?.data?.detail || error.message)); - + showFeedback('Failed to start custom bot: ' + error.message, true); + // Re-enable the button startBotButton.disabled = false; startBotButton.textContent = 'Start Bot'; @@ -164,19 +212,33 @@ async function startCustomBot() { */ async function stopCustomBot() { try { + console.log('Stopping custom bot...'); stopBotButton.disabled = true; stopBotButton.textContent = 'Stopping...'; - - await API.post('/dashboard/api/custom-bot/stop'); - - Toast.success('Custom bot stopped successfully'); - + + const response = await fetch('/dashboard/api/custom-bot/stop', { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + console.log('Bot stop result:', result); + + showFeedback('Custom bot stopped successfully', false); + // Check bot status after stopping - checkBotStatus(); + setTimeout(checkBotStatus, 2000); } catch (error) { console.error('Error stopping custom bot:', error); - Toast.error('Failed to stop custom bot: ' + (error.response?.data?.detail || error.message)); - + showFeedback('Failed to stop custom bot: ' + error.message, true); + // Re-enable the button stopBotButton.disabled = false; stopBotButton.textContent = 'Stop Bot'; @@ -188,38 +250,51 @@ async function stopCustomBot() { */ async function checkBotStatus() { try { - const response = await API.get('/dashboard/api/custom-bot/status'); - + const response = await fetch('/dashboard/api/custom-bot/status', { + method: 'GET', + credentials: 'include', + headers: { + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const status = await response.json(); + console.log('Bot status:', status); + // Update the status indicator - updateStatusIndicator(response); - + updateStatusIndicator(status); + // Update button states - updateButtonStates(response); - + updateButtonStates(status); + // Show error if any - if (response.error && botError) { - botError.textContent = response.error; + if (status.error && botError) { + botError.textContent = status.error; botError.classList.remove('hidden'); } else if (botError) { botError.classList.add('hidden'); } } catch (error) { console.error('Error checking custom bot status:', error); - + // Set status to unknown if (statusDot) { statusDot.className = 'w-4 h-4 rounded-full bg-gray-400 mr-2'; } - + if (statusText) { statusText.textContent = 'Unable to check status'; } - + // Disable buttons if (startBotButton) { startBotButton.disabled = true; } - + if (stopBotButton) { stopBotButton.disabled = true; } @@ -231,7 +306,7 @@ async function checkBotStatus() { */ function updateStatusIndicator(status) { if (!statusDot || !statusText) return; - + if (status.is_running) { statusDot.className = 'w-4 h-4 rounded-full bg-green-500 mr-2'; statusText.textContent = 'Bot is running'; @@ -252,7 +327,7 @@ function updateStatusIndicator(status) { */ function updateButtonStates(status) { if (!startBotButton || !stopBotButton) return; - + if (status.is_running) { startBotButton.disabled = true; stopBotButton.disabled = false; @@ -271,5 +346,29 @@ function updateButtonStates(status) { } } +/** + * Show feedback message to user + */ +function showFeedback(message, isError = false) { + if (botConfigFeedback) { + botConfigFeedback.textContent = message; + botConfigFeedback.className = isError ? 'mt-2 text-red-500' : 'mt-2 text-green-500'; + + // Clear feedback after 5 seconds + setTimeout(() => { + if (botConfigFeedback) { + botConfigFeedback.textContent = ''; + botConfigFeedback.className = 'mt-2'; + } + }, 5000); + } +} + +// Initialize when DOM is loaded +document.addEventListener('DOMContentLoaded', function() { + console.log('DOM loaded, initializing custom bot dashboard...'); + initCustomBot(); +}); + // Export the initialization function window.initCustomBot = initCustomBot; diff --git a/api_service/dashboard_web/js/utils.js b/api_service/dashboard_web/js/utils.js index c6fa2b8..6bbda30 100644 --- a/api_service/dashboard_web/js/utils.js +++ b/api_service/dashboard_web/js/utils.js @@ -661,9 +661,111 @@ const DOM = { } }; +// Authentication utilities +const Auth = { + async checkAuth() { + try { + const response = await fetch('/dashboard/api/user', { + method: 'GET', + credentials: 'include' + }); + + if (response.ok) { + const user = await response.json(); + console.log('User authenticated:', user); + return user; + } else { + console.log('User not authenticated'); + return null; + } + } catch (error) { + console.error('Auth check failed:', error); + return null; + } + }, + + redirectToLogin() { + window.location.href = '/dashboard/api/auth/discord'; + }, + + async logout() { + try { + await fetch('/dashboard/api/auth/logout', { + method: 'POST', + credentials: 'include' + }); + window.location.reload(); + } catch (error) { + console.error('Logout failed:', error); + window.location.reload(); + } + } +}; + +// Main dashboard initialization +async function initDashboard() { + console.log('Initializing dashboard...'); + + const authSection = document.getElementById('auth-section'); + const botConfigSection = document.getElementById('bot-config-section'); + const dashboardContainer = document.getElementById('dashboard-container'); + const loginButton = document.getElementById('login-button'); + const logoutButton = document.getElementById('logout-button'); + const usernameSpan = document.getElementById('username'); + const userAvatar = document.getElementById('user-avatar'); + + // Check authentication + const user = await Auth.checkAuth(); + + if (user) { + // User is authenticated, show dashboard + console.log('User authenticated, showing dashboard'); + DOM.hide(authSection); + DOM.hide(botConfigSection); + DOM.show(dashboardContainer); + + // Update user info + if (usernameSpan) { + usernameSpan.textContent = user.username || 'User'; + } + if (userAvatar) { + userAvatar.textContent = (user.username || 'U').charAt(0).toUpperCase(); + } + } else { + // User not authenticated, show login + console.log('User not authenticated, showing login'); + DOM.show(authSection); + DOM.hide(botConfigSection); + DOM.hide(dashboardContainer); + } + + // Add event listeners + if (loginButton) { + loginButton.addEventListener('click', () => { + console.log('Login button clicked'); + Auth.redirectToLogin(); + }); + } + + if (logoutButton) { + logoutButton.addEventListener('click', () => { + console.log('Logout button clicked'); + Auth.logout(); + }); + } +} + +// Initialize when DOM is loaded +document.addEventListener('DOMContentLoaded', function() { + console.log('DOM loaded, initializing dashboard...'); + initDashboard(); +}); + // Export utilities window.Toast = Toast; window.API = API; window.Modal = Modal; window.Form = Form; window.DOM = DOM; +window.Auth = Auth; +window.initDashboard = initDashboard;