ai_upgrade_assistant-0.2.0-alpha2/js/upgrade_assistant.js
js/upgrade_assistant.js
(function ($, Drupal, drupalSettings) {
'use strict';
let lastTerminalOutput = [];
Drupal.behaviors.aiUpgradeAssistant = {
attach: function (context, settings) {
// Initialize terminal output
const terminal = $('#terminal-output', context);
if (terminal.length) {
this.initializeTerminal(terminal);
}
// Initialize check status button
const checkStatusUrl = drupalSettings.aiUpgradeAssistant.checkStatusUrl;
const refreshInterval = drupalSettings.aiUpgradeAssistant.refreshInterval || 2000;
const progressBar = $('.progress-bar', context);
const $results = $('#upgrade-results-container');
const $button = $('#check-status-button', context).once('upgrade-assistant').on('click', function(e) {
e.preventDefault();
// Disable button and show loading
$button.prop('disabled', true).val(Drupal.t('Checking...'));
// Make AJAX call
$.ajax({
url: checkStatusUrl,
method: 'GET',
success: function(response) {
if (response.status === 'success') {
var html = '<div class="upgrade-assistant-status">';
// Add status items
if (response.data.status_items.length > 0) {
html += '<h3>' + Drupal.t('System Status') + '</h3><ul>';
response.data.status_items.forEach(function(item) {
html += '<li class="status-' + item.type + '">' + item.message + '</li>';
});
html += '</ul>';
} else {
html += '<p>' + Drupal.t('Your site is up to date!') + '</p>';
}
// Add actions
if (response.data.actions.length > 0) {
html += '<h3>' + Drupal.t('Recommended Actions') + '</h3>';
response.data.actions.forEach(function(action) {
html += '<div class="upgrade-action">' +
'<h4>' + action.title + '</h4>' +
'<pre>' + action.command + '</pre>' +
'<button class="button" onclick="return confirm(\'' +
Drupal.t('Are you sure you want to run this command?') +
'\')">' + Drupal.t('Run Command') + '</button>' +
'</div>';
});
}
html += '</div>';
$results.html(html);
} else {
$results.html('<div class="messages messages--error">' +
Drupal.t('Error checking status') + '</div>');
}
},
error: function(xhr) {
$results.html('<div class="messages messages--error">' +
Drupal.t('Error checking status: @error', {
'@error': xhr.responseJSON?.message || Drupal.t('Unknown error')
}) + '</div>');
},
complete: function() {
// Re-enable button
$button.prop('disabled', false).val(Drupal.t('Check Site Status'));
}
});
});
function updateTerminalOutput(messages) {
if (!Array.isArray(messages) || messages.length === 0) {
return;
}
// Only add new messages that we haven't seen before
const newMessages = messages.filter(msg => {
return !lastTerminalOutput.some(last =>
last.timestamp === msg.timestamp && last.message === msg.message
);
});
if (newMessages.length === 0) {
return;
}
// Update our last seen messages
lastTerminalOutput = messages;
// Add new messages to terminal
newMessages.forEach(msg => {
const timestamp = new Date(msg.timestamp * 1000).toLocaleTimeString();
const cssClass = msg.type === 'error' ? 'text-danger' :
msg.type === 'success' ? 'text-success' : 'text-info';
terminal.append(
$('<div>', {
class: cssClass,
text: `[${timestamp}] ${msg.message}`
})
);
});
// Scroll to bottom
terminal.scrollTop(terminal[0].scrollHeight);
}
function checkStatus() {
$.getJSON(checkStatusUrl)
.done(function (response) {
// Update progress bar
if (response.progress !== undefined) {
progressBar.css('width', response.progress + '%')
.attr('aria-valuenow', response.progress)
.text(response.progress + '%');
}
// Update terminal output
if (response.terminal_output) {
updateTerminalOutput(response.terminal_output);
}
// Continue polling if batch is active
if (response.is_active) {
setTimeout(checkStatus, refreshInterval);
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
console.error('Status check failed:', textStatus, errorThrown);
// Retry on failure
setTimeout(checkStatus, refreshInterval);
});
}
// Start checking status
checkStatus();
},
initializeTerminal: function(terminal) {
if (!terminal.length) return;
// Start polling for terminal updates
this.pollTerminal(terminal);
},
pollTerminal: function(terminal) {
const self = this;
const url = drupalSettings.path.baseUrl + 'admin/reports/upgrade-assistant/terminal';
function poll() {
$.ajax({
url: url,
method: 'GET',
success: function(response) {
if (response.output && response.output.length) {
// Clear terminal if it's getting too long
if (terminal.children().length > 200) {
terminal.empty();
}
// Add new messages
response.output.forEach(function(item) {
const timestamp = new Date(item.timestamp * 1000).toLocaleTimeString();
const line = $('<div class="terminal-line"></div>')
.text(`[${timestamp}] ${item.message}`);
terminal.append(line);
});
// Auto-scroll to bottom
terminal.scrollTop(terminal[0].scrollHeight);
}
},
complete: function() {
// Continue polling if the terminal is still in the DOM
if (terminal.length && terminal.closest('body').length) {
setTimeout(poll, 1000);
}
}
});
}
// Start polling
poll();
}
};
})(jQuery, Drupal, drupalSettings);
