diff --git a/deploy/files.js b/deploy/files.js index 9b32903..a025050 100644 --- a/deploy/files.js +++ b/deploy/files.js @@ -53,10 +53,51 @@ function statusToHTML(st) { function renderFiles(state) { if (state.files.length === 0) { fileTable.innerHTML = 'Нет файлов — выберите .docx / .pdf'; - } else { - fileTable.innerHTML = state.files.map(function(f, i) { - var rows = '' + - '' + + lucide.createIcons(); + return; + } + + // Сгруппировать файлы по zip_source + var groups = []; // [{zip: "name.zip"|null, files: [f, ...]}] + var seen = {}; + for (var i = 0; i < state.files.length; i++) { + var f = state.files[i]; + var zip = f.zip_source || null; + var key = zip || '__naked__'; + if (!seen[key]) { + seen[key] = { zip: zip, files: [] }; + groups.push(seen[key]); + } + // Сохраняем оригинальный индекс для id строк + f._idx = i; + seen[key].files.push(f); + } + + // Рендер: заголовок ZIP → файлы с отступом + var rows = []; + for (var gi = 0; gi < groups.length; gi++) { + var g = groups[gi]; + + if (g.zip) { + // Заголовок-секция ZIP + rows.push( + '' + + '' + + '📦 ' + escHtml(g.zip) + ' — ' + g.files.length + ' файл.' + + (g.files.length === 1 ? '' : 'ов') + + '' + ); + } + + // Файлы внутри группы (с отступом если из ZIP) + for (var fi = 0; fi < g.files.length; fi++) { + var f = g.files[fi]; + var i = f._idx; + var indent = g.zip ? 'padding-left:24px;' : ''; + + rows.push( + '' + + '' + (f.doc_id ? '' : '') + escHtml(f.name) + '' + '' + formatDate(f.lastModified) + '' + @@ -65,10 +106,12 @@ function renderFiles(state) { '' + '' + '' + - 'Загрузка...'; - return rows; - }).join(''); + 'Загрузка...' + ); + } } + + fileTable.innerHTML = rows.join(''); lucide.createIcons(); }