tapis_job-1.4.1-alpha1/js/joboutputfiletree.js
js/joboutputfiletree.js
/**
* @file
* joboutputfiletree.js javascript file.
*/
(function ($, Drupal, drupalSettings) {
'use strict';
Drupal.behaviors.jstree_menu = {
attach: function (context, settings) {
$("#osp_filetree").on('ready.jstree', function () {
// Deselect all nodes and fold all nodes when the jsTree is ready
$('#osp_filetree').jstree('deselect_all');
$('#osp_filetree').jstree('close_all');
document.getElementById('spinner').style.display = 'none';
});
$(once('downloadFiletreeClick', '#osp_filetree', context)).each(function () {
$(this).on('select_node.jstree', function (e, data) {
// Prevent the default action of the button click
e.preventDefault();
// If the user cancels, deselect the node
$('#osp_filetree').jstree('deselect_node', data.node.id);
if (data.node.a_attr.class === 'dir-link') {
// Perform the action associated with the directory link
var action = data.node.a_attr.dataaction;
if (action === 'download-dir') {
var filename = data.node.a_attr.filename;
var title = 'Download a directory';
var content = 'Are you sure you want to download this directory, "' +
filename + '"?<br>' + 'It may take longer for you to download it.';
showOffCanvasDialogForFile(title, content, filename, function () {
window.location.href = data.node.a_attr.href;
});
}
} else if (data.node.a_attr.class === 'file-link') {
var filename = data.node.a_attr.filename;
var title = 'Download a file';
var content = 'Are you sure you want to download this file, "' +
filename + '"?';
showOffCanvasDialogForFile(title, content, filename, function (selection) {
let fileUrl = data.node.a_attr.href;
if (selection === "download") {
window.location.href = fileUrl;
} else if (selection === 'view') {
// Open the popup window with a spinner
var popupWindow = openPopupWithSpinner();
fileUrl += "&download=0";
// console.log("file url = ", fileUrl);
const fileType = getFileType(filename);
// console.log("filetype = ", fileType);
fetch(fileUrl)
.then(response => {
if (!response.ok) {
// console.error('HTTP Status Code:', response.status);
return response.text().then(text => {
throw new Error(text);
});
}
return fileType === 'image' ? response.blob() : response.json();
})
.then(data => {
let content;
if (fileType === 'image') {
// Convert Blob to Object URL
content = URL.createObjectURL(data);
} else {
// Assuming JSON structure has a "content" field
content = data.content;
// console.log(content);
}
if (fileType === 'image') {
const match = filename.match(/\.([^.]+)$/);
let extension = match ? match[1] : '';
if (extension === 'pdf') {
popupWindow.document.body.innerHTML = `<embed src = "${content}" type = "application/${extension}" style = "width: 100%; height: 100vh;">`;
} else {
popupWindow.document.body.innerHTML = `<div id = "imageContainer" style = "display: flex; justify-content: center; align-items: center; height: 100vh;"><img id = "dynamicImage" src = "${content}" alt = "Image" style = "max-width: 100%; max-height: 100%;"></div>`;
loadImage(popupWindow);
}
} else {
// Updating the content of the div
popupWindow.document.body.innerHTML = `${content}`;
loadPrismAssets(data.assets.css, data.assets.js, popupWindow);
}
// Change the title of the popup window
popupWindow.document.title = filename;
})
.catch(error => {
console.error('Fetch operation failed:', error.message);
});
}
});
}
});
});
$(once('downloadButtonClick', '#downloadButton', context)).each(function () {
$(this).on('click', function (event) {
// Prevent the default action of the button click
event.preventDefault();
var title = "Download the entire directory";
var dialogContent = 'Are you sure you want to download the entire directory?<br>' +
'It may take longer for you to download it.';
showOffCanvasDialogForFile(title, dialogContent, 'entire_directory', function () {
var fileUrl = $('[data-drupal-selector="edit-file-url"]').val();
window.location.href = fileUrl;
});
});
});
function loadImage(popupWindow) {
// Create a script element to handle DOMContentLoaded
const script = popupWindow.document.createElement('script');
script.type = 'text/javascript';
script.text = `
document.addEventListener('DOMContentLoaded', function () {
const img = document.getElementById('dynamicImage');
img.onload = function () {
const imgWidth = img.naturalWidth;
const imgHeight = img.naturalHeight;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
// Adjust image size based on the window size while maintaining the aspect ratio
if (imgWidth > windowWidth || imgHeight > windowHeight) {
const widthRatio = windowWidth / imgWidth;
const heightRatio = windowHeight / imgHeight;
const resizeRatio = Math.min(widthRatio, heightRatio);
img.style.width = (imgWidth * resizeRatio) + 'px';
img.style.height = (imgHeight * resizeRatio) + 'px';
} else {
img.style.width = imgWidth + 'px';
img.style.height = imgHeight + 'px';
}
};
});
`;
// Append the script to the popup's document
popupWindow.document.body.appendChild(script);
}
function loadPrismAssets(cssUrls, jsUrls, popupWindow) {
cssUrls.forEach(cssUrl => {
const link = popupWindow.document.createElement('link');
link.rel = 'stylesheet';
link.href = cssUrl;
popupWindow.document.head.appendChild(link);
});
let loadScripts = function (index) {
if (index < jsUrls.length) {
const script = popupWindow.document.createElement('script');
script.src = jsUrls[index];
script.onload = function () {
loadScripts(index + 1);
};
popupWindow.document.body.appendChild(script);
} else {
// Ensure Prism runs after all scripts are loaded
popupWindow.Prism.highlightAll();
}
};
loadScripts(0);
}
// Function to create a popup window and display a loading spinner
function openPopupWithSpinner() {
var popupWindow = window.open('', '_blank', 'width=900,height=700,scrollbars=yes');
popupWindow.document.write(`
<!DOCTYPE html>
<html lang="en">
<head>
<title> Loading... </title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* Simple CSS for centering the spinner */
.spinner-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
width: 36px;
height: 36px;
border-radius: 50% ;
border-left-color: #09f;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="spinner-container">
<div class="spinner"></div>
</div>
</body>
</html>
`);
popupWindow.document.close(); // Necessary for IE >= 10
return popupWindow;
}
function getFileType(filename) {
const match = filename.match(/\.([^.]+)$/);
let extension = match ? match[1] : '';
// List of supported image types
const imageTypes = drupalSettings.tapis_job.supported_image_extensions || [];
if (imageTypes.includes(extension)) {
return 'image';
}
const supportedExtensions = drupalSettings.tapis_job.supported_extensions || [];
if (supportedExtensions.includes(extension)) {
return 'text';
}
return 'blob';
}
// Function to create and display off-canvas dialog
function showOffCanvasDialogForFile(title, content, filename, confirmCallback) {
const fileType = getFileType(filename);
// Create dialog content based on file type
let viewButton = '';
if (fileType !== 'blob') {
viewButton = '<button id="confirm-view" class="osp-custom-button">View</button> ';
}
if (viewButton !== '') {
title = "Manage File Download";
content = "Would you like to view or download the file '" + filename + "'?"
}
var dialogContent = '<p>' + content + '</p>' +
viewButton +
'<button id="confirm-download" class="osp-custom-button">Download</button> ' +
'<button id="cancel-download" class="osp-custom-button">Cancel</button>';
// Create off-canvas dialog
var offCanvas = $('<div class="off-canvas">' +
'<div class="off-canvas-content">' +
'<div class="off-canvas-header"><b>' + title + '</b></div>' +
'<div class="off-canvas-body">' + dialogContent + '</div>' +
'</div>' +
'</div>');
$('body').append(offCanvas);
// Append custom CSS to the dialog window
var css = `
.osp-custom-button {
background-color: #007bff;
color: #fff;
border: none;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline - block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 5px;
}
.osp-custom-button:hover {
background-color: #0056b3;
}
`;
// Create a style element and add the CSS to it
var styleElement = document.createElement('style');
styleElement.type = 'text/css';
styleElement.appendChild(document.createTextNode(css));
// Append the style element to the head of the document
document.head.appendChild(styleElement);
offCanvas.addClass('is-open');
$(once('confirmDownload', '#confirm-download', context)).each(function () {
$(this).on('click', function (event) {
confirmCallback("download");
offCanvas.removeClass('is-open');
offCanvas.remove();
});
});
if (viewButton !== '') {
$(once('confirmView', '#confirm-view', context)).each(function () {
$(this).on('click', function (event) {
confirmCallback("view");
offCanvas.removeClass('is-open');
offCanvas.remove();
});
});
}
$(once('concelDownload', '#cancel-download', context)).each(function () {
$(this).on('click', function (event) {
offCanvas.removeClass('is-open'); // Hide off-canvas dialog
offCanvas.remove(); // Remove off-canvas dialog from DOM });
});
});
}
$("#osp_filetree").jstree({
core: {
data: function (node, callback) {
// Load directory contents lazily
var path =
node.id === "#"
? drupalSettings.tapis_job.exec_system_exec_dir
: node.id;
$.ajax({
url: Drupal.url("tapis/job/" + drupalSettings.tapis_job.tapis_job_id +"/output/file_list"),
data: { path: path },
dataType: "json",
success: function (data) {
callback(data);
},
error: function () {
alert("Failed to load directory contents.");
},
});
},
},
types: {
file: { icon: "jstree-file" },
folder: { icon: "jstree-folder" },
},
plugins: ["types"],
});
}
};
})(jQuery, Drupal, drupalSettings);
