tapis_job-1.4.1-alpha1/js/jobpage.js

js/jobpage.js
(function ($, Drupal, drupalSettings) {
    Drupal.behaviors.jobStatusRefresh = {
        attach: function (context, settings) {

            const $jobStatusContainer = $('#job-status-container', context);
            once('jobStatusRefresh', $jobStatusContainer, context).forEach(function (element) {

                /**
                 * Possible job statuses, according to Tapis:
                 *
                 * PENDING - Job processing beginning
                 * PROCESSING_INPUTS - Identifying input files for staging
                 * STAGING_INPUTS - Transferring job input data to execution system
                 * STAGING_JOB - Staging runtime assets to execution system
                 * SUBMITTING_JOB - Submitting job to execution system
                 * QUEUED - Job queued to execution system queue
                 * RUNNING - Job running on execution system
                 * ARCHIVING - Transferring job output to archive system
                 * BLOCKED - Job blocked
                 * PAUSED - Job processing suspended
                 * FINISHED - Job completed successfully
                 * CANCELLED - Job execution intentionally stopped
                 * FAILED - Job failed
                 */
                var refreshJobStatuses = ["TERMINATING", "PENDING", "PROCESSING_INPUTS", "STAGING_INPUTS", "STAGING_JOB", "SUBMITTING_JOB", "QUEUED", "ARCHIVING"];
                var PAGE_REFRESH_TIMEOUT_MS = 5000; // number of milliseconds before page refresh

                var jobStatus = settings.tapis_job.status;
                let progressJobStatus = '';

                // The class form-item-refresh-button is available in the DOM.
                if ($('.job-status-refresh-form .button').length > 0) {

                    // Check if the job status is "PENDING"
                    if (refreshJobStatuses.includes(jobStatus) || settings.tapis_job.jobProxyURLFlag === true) {
                        $('.job--terminate--action').show();

                        // Ensure the message container exists and sits ABOVE the Open App Session button
                        function ensureProxyStatusContainer() {
                            var $jobButtonsInner = $('.job-buttons .inner');
                            if ($jobButtonsInner.length === 0) return;

                            var $msg = $jobButtonsInner.find('#proxy-status-message');
                            if ($msg.length === 0) {
                                $msg = $('<div>', {
                                    id: 'proxy-status-message',
                                    class: 'proxy-status-message visually-hidden', // base class from CSS
                                    'aria-live': 'polite'
                                });
                                // Place it near where buttons show up; we will reposition below if needed.
                                $msg.appendTo($jobButtonsInner);
                            }

                            // If the Open App Session button exists, ensure the message is directly above it
                            var $openBtn = $jobButtonsInner.find('[data-role="open-app-session"]').first();
                            if ($openBtn.length > 0) {
                                if (!$msg.next().is($openBtn)) {
                                    $msg.insertBefore($openBtn);
                                }
                            } else {
                                // Otherwise, keep it ABOVE the terminate button (or at top as a fallback)
                                var $terminate = $jobButtonsInner.find('.job--terminate--action').first();
                                if ($terminate.length > 0) {
                                    if (!$msg.prev().is($terminate)) {
                                        $msg.insertBefore($terminate);
                                    }
                                } else {
                                    // No terminate button yet; ensure it stays at the top for visibility
                                    if ($jobButtonsInner.children().first().attr('id') !== 'proxy-status-message') {
                                        $msg.prependTo($jobButtonsInner);
                                    }
                                }
                            }
                        }

                        // Call this once after DOM ready or after job buttons render
                        ensureProxyStatusContainer();

                        function updateProxyMessage(settings) {
                            const jobStatus = (settings.tapis_job && settings.tapis_job.status) || '';
                            const proxyNotAlive = !!(settings.tapis_job && settings.tapis_job.jobProxyURLFlag);
                            const $container = $('.job-buttons .inner');
                            const hasOpenSessionBtn = $container.find('[data-role="open-app-session"]').length > 0;

                            // Ensure container exists and is positioned relative to the button
                            ensureProxyStatusContainer();
                            var $msg = $container.find('#proxy-status-message');

                            let text = '';
                            let shouldShow = false;

                            if (!hasOpenSessionBtn && jobStatus === 'RUNNING' && proxyNotAlive) {
                                // While waiting for proxy/button, show loading message above where it will appear
                                text = "Connecting to app session.";
                                shouldShow = true;
                            }

                            if (shouldShow) {
                                if ($msg.hasClass('visually-hidden') || $msg.text() !== text) {
                                    $msg.removeClass('visually-hidden')
                                        .addClass('notice')
                                        .text(text);
                                }
                            } else {
                                if (!$msg.hasClass('visually-hidden') || $msg.text() !== '') {
                                    $msg.addClass('visually-hidden')
                                        .removeClass('notice')
                                        .empty();
                                }
                            }
                        }

                        // Hide the static status
                        let jobStatusSection = $('.job-status-section');
                        jobStatusSection.addClass('hidden');

                        // Display progress section
                        let progressSection = $('.job-progress-section');
                        progressSection.removeClass('hidden');

                        let progress = progressSection.find('.oak-progress');

                        // Add a step to the progress
                        progressJobStatus = jobStatus;
                        let jobStatusFormatted = jobStatus.replace('_', ' ').toLowerCase();
                        jobStatusFormatted = jobStatusFormatted.charAt(0).toUpperCase() + jobStatusFormatted.slice(1);
                        let step = $('<li class="working"><div class="inner"><div class="step-marker"><div class="oak-progress-loader"></div></div><span>' + jobStatusFormatted + '</span></div></li>');

                        step.appendTo(progress);
                        step.delay(4).queue(function () {
                            $(this).addClass("show");
                        });

                        // Variable to store the interval ID
                        var refreshIntervalId;

                        // Function to start the interval
                        function startRefreshInterval() {
                            // Periodically click the hidden button to refresh the form.
                            refreshIntervalId = setInterval(function () {
                                $('.job-status-refresh-form .button').trigger('click');
                            }, PAGE_REFRESH_TIMEOUT_MS);
                        }

                        // Start the interval initially
                        startRefreshInterval();

                        $(document).ajaxComplete(function (event, xhr, settings) {
                            if (settings.url.indexOf('/tapis/job/') !== -1) {
                                // Assuming the response body contains the updated settings
                                var responseBody = JSON.parse(xhr.responseText);
                                responseBody.forEach(obj => {
                                    if (obj.command === 'settings' && obj.settings && obj.settings.tapis_job && obj.settings.tapis_job.status) {
                                        settings.tapis_job = obj.settings.tapis_job;

                                        // Add a step to the progress (if changed)
                                        if (progressJobStatus !== obj.settings.tapis_job.status) {
                                            progressJobStatus = obj.settings.tapis_job.status;
                                            let jobStatusFormatted = obj.settings.tapis_job.status.replace('_', ' ').toLowerCase();
                                            jobStatusFormatted = jobStatusFormatted.charAt(0).toUpperCase() + jobStatusFormatted.slice(1);

                                            let step = $('<li><div class="inner"><div class="step-marker"><div class="oak-progress-loader"></div></div><span>' + jobStatusFormatted + '</span></div></li>');

                                            step.appendTo(progress);

                                            // reset all working
                                            progress.find('.working').removeClass('working').addClass('completed');
                                            step.addClass("working");

                                            // See if there is a terminate button to render
                                            if (obj.settings.terminate_job_button && obj.settings.terminate_job_button['#markup']) {
                                                let terminateJobButton = $(obj.settings.terminate_job_button['#markup']);

                                                let jobButtonsSection = $('.job-buttons');
                                                let terminateJobButtonContainer = jobButtonsSection.find('.inner');

                                                terminateJobButton.appendTo(terminateJobButtonContainer);
                                                jobButtonsSection.removeClass('hidden');
                                            }

                                            // Check if the job status is on of those completed
                                            if (!refreshJobStatuses.includes(settings.tapis_job.status)) {
                                                step.removeClass("working");
                                                step.addClass("completed");
                                                if(settings.tapis_job.status === "BLOCKED" || settings.tapis_job.status === "FAILED") {
                                                    step.addClass("error");
                                                }
                                                else if(settings.tapis_job.status === "PAUSED" || settings.tapis_job.status === "CANCELLED") {
                                                    step.addClass("warning");
                                                }
                                                else {
                                                    step.addClass("success");
                                                }
                                            }

                                            step.delay(4).queue(function () {
                                                $(this).addClass("show");
                                            });

                                            // See if there is an open button to render
                                            if (obj.settings.job_button && obj.settings.job_button['#markup']) {
                                                let jobButton = $(obj.settings.job_button['#markup']);

                                                let jobButtonsSection = $('.job-buttons');
                                                let jobButtonsContainer = jobButtonsSection.find('.inner');

                                                jobButton.prependTo(jobButtonsContainer);
                                                jobButtonsSection.removeClass('hidden');
                                            }
                                            updateProxyMessage(obj.settings);
                                        } else {
                                            // See if there is an open button to render
                                            if (obj.settings.job_button && obj.settings.job_button['#markup']) {
                                                let jobButton = $(obj.settings.job_button['#markup']);

                                                let jobButtonsSection = $('.job-buttons');
                                                let jobButtonsContainer = jobButtonsSection.find('.inner');

                                                jobButton.prependTo(jobButtonsContainer);
                                                jobButtonsSection.removeClass('hidden');
                                            }
                                            updateProxyMessage(obj.settings);
                                        }
                                    }
                                });

                                // Check if the job status is "finished"
                                if (settings.tapis_job.jobProxyURLFlag === false) {
                                    if (!refreshJobStatuses.includes(settings.tapis_job.status)) {
                                        // Clear the interval
                                        clearInterval(refreshIntervalId);
                                        if (settings.tapis_job.status !== "RUNNING" ||
                                            $('.job--terminate--open--session--action').length > 0) {
                                            $('.job--terminate--action').hide();
                                        }
                                    }
                                } else {
                                    updateProxyMessage(settings);
                                }
                            }
                        });
                    } else {
                        if (settings.tapis_job.status !== "RUNNING" ||
                            $('.job--terminate--open--session--action').length > 0) {
                            $('.job--terminate--action').hide();
                        }
                    }
                } else {
                    console.log('The class form-item-refresh-button is not available in the DOM.');
                }
            })
        }
    };
})(jQuery, Drupal, drupalSettings);

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

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