Код:
/* Client scripts module */
declare const console : any
declare const document: any
declare const window: any
import * as XLSX from 'xlsx.full.min.js';
declare interface SystemFolder {
folder_name : string,
folder_id: string,
files?: FileItem[],
sub_folders: SystemFolder[] | undefined
}
async function showContext(): Promise<void> {
console.log(Context.data.files_tree)
console.log(Context.data.files_tree.folder_name)
}
// Функция для прокликивания всех папок.
async function checkAllFolders(): Promise<void> {
const blueButtons = document.querySelectorAll('.link-like');
blueButtons.forEach((button: { click: () => any; }) => button.click() )
Context.data.is_checkFolders_button_visible = false
}
async function buildfiles_tree(): Promise<void> {
//Получаем загрузчик
let loader = document.querySelector('.folder-tree-loader')
//Показываем загрузчик
loader.style.display = "unset"
//Очищаем переменную
Context.data.files_tree = undefined
// Строим иерархию
await build_tree()
// Если список файлов получили сразу - скрываем кнопку. И наоборот.
Context.data.is_checkFolders_button_visible = !Context.data.load_files
//Скрываем загрузчик
loader.style.display = "none"
}
//Выстраиваем структуру
async function build_tree(): Promise<void> {
//id системной папки
let system_folder = '00000000-0000-0000-0000-000000000000'
// Создаём корень
let files_tree: SystemFolder = { folder_name: "directory", folder_id: system_folder , sub_folders: [] }
let empty_folder : SystemFolder[] = []
// let system_dirs = await System.directories.getDirs(system_folder)
let system_dirs = await System.directories.getDirs(system_folder)
//Получаем нормальные имена папок, без полного пути
const regex = /(?<=:)([^:]+)(?=:[^:]*$)/;
//Отфильтровываем папку "shared", так как там папки дублируются и заполняем корень
for (let folder of system_dirs.filter(f => f.data.__name != 'shared' ) ){
let dirty_name = folder.data.__name
const match = dirty_name.match(regex);
const f_name = match ? match[0] : dirty_name;
let files: FileItem[] = []
//Если выбрана опция загрузки файлов, загружаем их
if (Context.data.load_files){
files = await folder.getFiles()
}
const files_tree_parent = {folder_name: f_name, folder_id: folder.id , sub_folders: empty_folder }
//Получаем подпапки рекурсивно
const sub_folders = await getChildFolders(folder, files_tree_parent)
let root = {folder_name: f_name, folder_id: folder.id, files: files , sub_folders: sub_folders }
//Добавляем в корень
files_tree.sub_folders!.push(root)
}
//Записываем в контект для базовой отрисовки
Context.data.files_tree = files_tree
}
// Получаем папки
async function getChildFolders(folder: DirectoryItem, parent: SystemFolder): Promise<SystemFolder[] | undefined> {
try{
let child_dirs = await System.directories.getDirs(folder.data.__id)
// console.log(folder.data.__id)
if (!child_dirs || child_dirs.length < 1){
return []
}
else{
const regex = /(?<=:)([^:]+)(?=:[^:]*$)/;
let proper_Folders_arr = Context.data.system_folders?.map(fldr => fldr.code)
// for (let folder of child_dirs.filter(f => f.data.__name != 'process' && f.data.__name != 'widgets')){
for (let folder of child_dirs.filter(f => (proper_Folders_arr?.findIndex(fldr => fldr == f.data.__name) == -1) )){
let dirty_name = folder.data.__name
const match = dirty_name.match(regex);
const f_name = match ? match[0] : dirty_name;
let files: FileItem[] = []
if (Context.data.load_files){
files = await folder.getFiles()
}
let empty_folder : SystemFolder[] = []
const files_tree_parent = {
folder_name: f_name,
folder_id: folder.id ,
sub_folders: empty_folder,
files: files
}
let sub_folders = await getChildFolders(folder, files_tree_parent)
parent.sub_folders!.push({
folder_name: f_name,
folder_id: folder.id,
files: files ,
sub_folders: sub_folders
})
// const sub_folders = await getChildFolders(folder)
}
return parent.sub_folders
}
}
catch(error){
}
}
//Отрисовываем папки
function showFolders(folder_id: string): void {
let data: SystemFolder[] = Context.data.files_tree.sub_folders;
let application: SystemFolder | undefined = data.find(folder => folder.folder_id === folder_id);
// Проверяем, что приложение определено
if (!application || !application.sub_folders) return;
let folders = application.sub_folders;
// Находим контейнер для добавления папки
let folderContainer = document.getElementById(`fldr-${folder_id}`)?.querySelector('.folder-container');
let toggleButton = document.getElementById(`fldr-${folder_id}`)?.querySelector('.toggle-btn');
//Прерывание, если не найдено
if (!folderContainer) return;
// Проверяем отрисовку
if (folderContainer.innerHTML === "") {
// Наполняем контейнер папками
let output = renderFolders(folders);
folderContainer.innerHTML = output;
toggleButton.textContent = "[-]"; // Функциональный значок
} else {
// Очищаем контейнер
folderContainer.innerHTML = "";
toggleButton.textContent = "[+]";
}
setupEventListeners()
}
// Отрисовываем папки и подпапки рекурсивно
function renderFolders(folders: SystemFolder[]): string {
let output = "<ul>";
for (const folder of folders) {
//Если выбрана опция с изначальной загрузкой файлов. Внимание - так будет больше запросов на сервер.
if( Context.data.load_files ){
//Если файлы присутствуют
if (folder.files && folder.files.length > 0){
output += `<li class="folder pointer" value="${folder.folder_id}" id="folder-${folder.folder_id}">
<span class='link-like' value="${folder.folder_id}" >${folder.folder_name}</span>`;
}
else{
output += `<li class="folder" value="${folder.folder_id}" id="folder-${folder.folder_id}">
<span class='no-link' value="${folder.folder_id}">${folder.folder_name}</span>`;
}
}
// Если не загружаем файлы сразу. Делаем меньше запросов на сервер. Рекомендуемая настройка.
else if( !Context.data.load_files ){
output += `<li class="folder pointer" value="${folder.folder_id}" id="folder-${folder.folder_id}">
<span class='link-like' value="${folder.folder_id}" >${folder.folder_name}</span>`;
}
if (folder.sub_folders && folder.sub_folders.length > 0) {
output += `<span class="toggle-btn" data-folder-id="${folder.folder_id}">[+]</span>`;
}
output += `</li>`;
if (folder.sub_folders && folder.sub_folders.length > 0) {
output += `<div class="folder-container" id="subfolder-${folder.folder_id}" style="display: none;">${renderFolders(folder.sub_folders)}</div>`;
}
}
output += "</ul>";
return output;
}
//функция навешивания обработчиков событий на [+] и <span>
async function setupEventListeners(): Promise<void> {
setupToggleButtons(); //[+]
setupShowTable() //<span>
}
// Навешиваем EventListener на каждую кнопку
function setupToggleButtons(): void {
const toggleButtons = document.querySelectorAll('.toggle-btn');
//@ts-ignore
toggleButtons.forEach(button => {
button.addEventListener('click', function(event: Event<any>) {
//@ts-ignore
const folderId = (event.target as HTMLElement).getAttribute('data-folder-id');
showSubFolders(event, folderId);
});
});
function showSubFolders(event: Event, folderId: string): void {
//@ts-ignore
event.stopPropagation(); // Предотвращаем вызов родительского элемента
const subfolderContainer = document.getElementById(`subfolder-${folderId}`);
//@ts-ignore
const toggleButton = event.target as HTMLElement;
if (subfolderContainer) {
if (subfolderContainer.style.display === "none") {
subfolderContainer.style.display = "block"; // показать подпапки
toggleButton.textContent = "[-]"; // поменять значок
} else {
subfolderContainer.style.display = "none"; // скрыть подпапки
toggleButton.textContent = "[+]"; // поменять значок
}
}
}
}
// // Навешиваем EventListener на строчку папки <span>
function setupShowTable(): void {
const folder_string = document.querySelectorAll('.link-like');
//@ts-ignore
folder_string.forEach(span => {
span.addEventListener('click', function(event: Event<any>) {
//@ts-ignore
const folder_id = (event.target as HTMLElement).getAttribute('value');
//@ts-ignore
loadFiles(folder_id);
});
});
}
//Функция отрисовки таблицы
async function loadFiles(folder_id: string): Promise<void> {
const button = document.querySelector(`[btn-id="${folder_id}"]`)
let files = await System.directories.getFiles(folder_id)
const folder = document.getElementById(`folder-${folder_id}`);
const span = folder.querySelector('span')
let folder_name = span.innerText;
let dowload_icon = document.getElementById('load_file')
const table_cell = document.getElementById(`containing_files_table`);
let output = "<div style ='padding: 0px'>";
if (!files || files.length == 0){
dowload_icon.style.display = "none"
span.classList.remove("link-like");
folder.classList.remove("pointer");
}
else if (files && files.length > 0){
output +=
`<table class="table table-bordered" id='table-${folder_id}' >
<h3> ${folder_name} </h3>
<thead>
<tr class="table-light table customTable">
<th>Название файла</th>
<th>id файла</th>
<th>Вес файла</td>
</tr>
</thead>
<tbody>`
for (const file of files) {
output +=
`<tr>
<td>${file.data.__name }</td>
<td>${file.data.__id }</td>
<td>${file.data.size } Байт</td>
</tr>`
}
output += `
</tbody>
</table>`
dowload_icon.style.display = "block"
}
output += "</div>";
table_cell.innerHTML = output
}
//------------------------- Экспорт в файл с использованием min.js------------------------- //
async function exportTableToExcel(): Promise<void> {
const table = document.querySelector(`#containing_files_table > div > table`);
const table_name = document.querySelector(`#containing_files_table > div > h3`).innerText;
if (!table) {
console.error('Table not found');
return ;
}
// Create a new workbook
const workbook = XLSX.utils.book_new();
// Convert the HTML table to a worksheet
const worksheet = XLSX.utils.table_to_sheet(table);
// Append the worksheet to the workbook
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// Generate a binary string representation of the workbook
const excelBuffer = XLSX.write(workbook, {
bookType: 'xlsx',
type: 'array'
});
//
let name = table_name + ".xlsx"
const newTmpFile = await System.files.createTemporary(name, excelBuffer);
let downloadLink = await newTmpFile.getDownloadUrl()
Context.data.file = newTmpFile
// Create a link element
const link = document.createElement('a');
link.href = downloadLink
link.download = name
// Append to the body (required for Firefox)
document.body.appendChild(link);
link.click(); // Trigger the download
// Clean up and remove the link
document.body.removeChild(link);
}
//------------------------- Экспорт в файл ------------------------- //