ai_upgrade_assistant-0.2.0-alpha2/js/status_page.js

js/status_page.js
(function ($, Drupal, once) {
  'use strict';

  Drupal.behaviors.aiUpgradeStatus = {
    attach: function (context, settings) {
      console.log('Initializing AI Upgrade Status...');
      
      once('aiUpgradeStatus', '.ai-upgrade-status', context).forEach(function (element) {
        console.log('Found status element, setting up polling...');
        
        const terminalWindow = document.getElementById('terminal-window');
        const countdownElement = element.querySelector('.countdown');
        
        if (!terminalWindow) {
          console.error('Terminal window element not found!');
          return;
        }
        
        let isPolling = false;
        let lastTimestamp = 0;
        let countdownInterval;
        let nextUpdateTime = 0;

        function updateCountdown() {
          if (nextUpdateTime > 0) {
            const now = Math.floor(Date.now() / 1000);
            const remaining = Math.max(0, nextUpdateTime - now);
            if (countdownElement) {
              countdownElement.textContent = remaining;
            }
          }
        }

        function scheduleNextUpdate(delaySeconds) {
          if (countdownInterval) {
            clearInterval(countdownInterval);
          }
          
          nextUpdateTime = Math.floor(Date.now() / 1000) + delaySeconds;
          
          // Start countdown immediately
          updateCountdown();
          
          // Update countdown every second
          countdownInterval = setInterval(updateCountdown, 1000);
          
          // Schedule the actual update
          return setTimeout(updateStatus, delaySeconds * 1000);
        }

        function updateStatus() {
          if (isPolling) {
            console.log('Already polling, skipping update');
            return;
          }

          console.log('Starting status update...');
          isPolling = true;
          let newMessages = [];
          
          $.ajax({
            url: Drupal.url('admin/reports/upgrade-assistant/check-status'),
            success: function (response) {
              console.log('Received status update:', response);
              
              // Update progress bar
              const progressBar = element.querySelector('.progress-bar');
              const progressText = element.querySelector('.progress-text');
              if (progressBar && progressText) {
                progressBar.style.width = response.progress + '%';
                progressText.textContent = response.progress + '% Complete';
                console.log('Updated progress:', response.progress);
              }

              // Update terminal output
              if (response.terminal_output && response.terminal_output.length > 0) {
                console.log('Got new terminal output:', response.terminal_output.length, 'messages');
                
                // Filter out messages we've already seen
                newMessages = response.terminal_output.filter(line => line.timestamp > lastTimestamp);
                console.log('New messages:', newMessages.length);
                
                if (newMessages.length > 0) {
                  // Update last timestamp
                  lastTimestamp = Math.max(...newMessages.map(line => line.timestamp));
                  
                  // Add new messages to terminal
                  const terminalContent = newMessages.map(function (line) {
                    const timestamp = new Date(line.timestamp * 1000).toTimeString().split(' ')[0];
                    return `<div class="terminal-line type-${line.type}">` +
                      `<span class="timestamp">[${timestamp}]</span> ${line.message}</div>`;
                  }).join('');

                  // Clear placeholder if it exists
                  const placeholder = terminalWindow.querySelector('.terminal-placeholder');
                  if (placeholder) {
                    placeholder.remove();
                  }

                  // Append new content
                  terminalWindow.insertAdjacentHTML('beforeend', terminalContent);
                  terminalWindow.scrollTop = terminalWindow.scrollHeight;
                  console.log('Added new terminal content');
                }
              }

              // Update module categories if they've changed
              if (response.modules) {
                Object.keys(response.modules).forEach(function (category) {
                  const details = element.querySelector(`.module-group.${category}`);
                  if (details) {
                    const count = response.modules[category].length;
                    const summary = details.querySelector('summary');
                    if (summary) {
                      const label = summary.textContent.split('(')[0].trim();
                      summary.textContent = `${label} (${count})`;
                    }
                  }
                });
              }

              isPolling = false;

              // Schedule next update based on activity
              if (response.is_active || newMessages.length > 0) {
                console.log('Activity detected, updating in 1 second');
                scheduleNextUpdate(1);
              } else {
                console.log('No activity, updating in 5 seconds');
                scheduleNextUpdate(5);
              }
            },
            error: function (xhr, status, error) {
              console.error('Error updating status:', error);
              isPolling = false;
              // Retry after error with longer delay
              scheduleNextUpdate(5);
            }
          });
        }

        // Start polling immediately
        updateStatus();

        // Add click handlers for action buttons
        once('actionButtons', '[data-action]', element).forEach(function (button) {
          button.addEventListener('click', function (e) {
            e.preventDefault();
            const action = this.dataset.action;
            const module = this.dataset.module;

            let url;
            switch (action) {
              case 'composer-update':
                url = Drupal.url(`admin/reports/upgrade-assistant/module/${module}/composer-update`);
                break;
              case 'apply-patch':
                url = Drupal.url(`admin/reports/upgrade-assistant/module/${module}/apply-patch`);
                break;
              case 'auto-fix':
                url = `/admin/reports/upgrade-assistant/auto-fix/${module}`;
                fetch(url, {
                  method: 'GET',
                  headers: {
                    'Accept': 'application/json',
                  },
                })
                .then(response => response.json())
                .then(data => {
                  if (data.status === 'success') {
                    Drupal.behaviors.messages.showMessage(data.message, 'status');
                    // Refresh status after a short delay
                    setTimeout(() => {
                      updateStatus();
                    }, 2000);
                  } else {
                    Drupal.behaviors.messages.showMessage(data.message, 'error');
                  }
                })
                .catch(error => {
                  console.error('Error:', error);
                  Drupal.behaviors.messages.showMessage(
                    Drupal.t('An error occurred while processing the request.'),
                    'error'
                  );
                });
                return;
              case 'analyze':
                url = Drupal.url(`admin/reports/upgrade-assistant/analyze/${module}`);
                fetch(url, {
                  method: 'POST',
                  headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                  },
                })
                .then(response => response.json())
                .then(data => {
                  if (data.status === 'success') {
                    window.location.href = Drupal.url(`admin/reports/upgrade-assistant/analysis/${module}`);
                  } else {
                    Drupal.behaviors.messages.showMessage(data.message || 'Analysis failed', 'error');
                  }
                })
                .catch(error => {
                  console.error('Error:', error);
                  Drupal.behaviors.messages.showMessage(
                    Drupal.t('An error occurred during analysis.'),
                    'error'
                  );
                });
                return;
              default:
                console.error('Unknown action:', action);
                return;
            }

            $.ajax({
              url: url,
              method: 'POST',
              success: function (response) {
                if (response.message) {
                  // Show status message
                  Drupal.behaviors.messages.showMessage(response.message);
                }
                // Trigger a status update immediately
                updateStatus();
              },
              error: function (xhr, status, error) {
                console.error(`Error executing ${action} for ${module}:`, error);
                Drupal.behaviors.messages.showMessage(error, 'error');
              }
            });
          });
        });

        function updateRateLimitStatus() {
          fetch('/admin/config/development/ai-upgrade-assistant/rate-limit-status')
            .then(response => response.json())
            .then(data => {
              const statusHtml = `
                <div class="rate-limit-status">
                  <h3>API Rate Limit Status</h3>
                  <div class="rate-limit-info">
                    <p>Status: ${data.enabled ? 'Enabled' : 'Disabled'}</p>
                    <p>Requests: ${data.current_requests}/${data.max_requests}</p>
                    <p>Window Remaining: ${Math.floor(data.window_remaining)}s</p>
                    <div class="progress-bar">
                      <div class="progress" style="width: ${(data.current_requests / data.max_requests) * 100}%"></div>
                    </div>
                  </div>
                </div>
              `;
              
              const container = document.querySelector('.rate-limit-container');
              if (container) {
                container.innerHTML = statusHtml;
              }
            })
            .catch(error => console.error('Error updating rate limit status:', error));
        }

        // Update rate limit status every 5 seconds
        setInterval(updateRateLimitStatus, 5000);
      });
    }
  };

  // Helper for showing status messages
  Drupal.behaviors.messages = {
    showMessage: function (message, type = 'status') {
      const messagesRegion = document.querySelector('[data-drupal-messages]');
      if (messagesRegion) {
        const messageWrapper = document.createElement('div');
        messageWrapper.setAttribute('role', 'contentinfo');
        messageWrapper.setAttribute('aria-label', Drupal.t('Status message'));
        messageWrapper.className = `messages messages--${type}`;
        messageWrapper.innerHTML = message;
        messagesRegion.appendChild(messageWrapper);

        // Remove the message after 5 seconds
        setTimeout(() => {
          messageWrapper.remove();
        }, 5000);
      }
    }
  };

})(jQuery, Drupal, once);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc