From 2a49155b056f854867defc4255e53b159b02e60e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 24 Aug 2026 17:10:21 +0300 Subject: [PATCH] =?UTF-8?q?v0.0.69:=20=D0=B0=D1=80=D1=85=D0=B8=D0=B2=D1=8B?= =?UTF-8?q?=20=D0=B8=D0=B7=20=D0=BF=D0=B0=D0=BF=D0=BA=D0=B8=20=D0=BD=D0=B5?= =?UTF-8?q?=20=D1=82=D0=B5=D1=80=D1=8F=D1=8E=D1=82=D1=81=D1=8F=20=E2=80=94?= =?UTF-8?q?=20zip=20=D0=B1=D0=B5=D0=B7=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=BE=D0=B2=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D1=8F=D0=B5=D1=82=D1=81=D1=8F=20=D0=BA=D0=B0=D0=BA=20?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8C;=20=D1=80=D0=B0=D1=81=D0=BA=D1=80?= =?UTF-8?q?=D1=8B=D1=82=D0=B8=D0=B5=20zip=20=D1=81=20=D0=B4=D0=BE=D0=BA?= =?UTF-8?q?=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D0=BC=D0=B8;=20=D1=81?= =?UTF-8?q?=D0=BA=D0=BB=D0=BE=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D1=87?= =?UTF-8?q?=D1=91=D1=82=D1=87=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History/README.md | 1 + .../2026-08-24-folder-zip-not-lost.md | 33 +++++++++++++++++++ site/app.py | 2 +- site/templates/index.html | 22 ++++++++++--- 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 History/ux-frontend/2026-08-24-folder-zip-not-lost.md diff --git a/History/README.md b/History/README.md index 418b597..f8a3697 100644 --- a/History/README.md +++ b/History/README.md @@ -105,6 +105,7 @@ - **2026-08-24-interrupt-eta-implemented.md** — v0.0.63: реализовано прерывание с сохранением + ETA + UI-таблица. - **2026-08-24-time-tickers-estimates.md** — v0.0.64–0.0.65: тикер текущего файла на всех этапах, мгновенные оценки времени по файлам и суммарно. - **2026-08-24-folder-select-implemented.md** — v0.0.68: кнопка «Выбрать папку» (webkitdirectory, рекурсивно, относительный путь). +- **2026-08-24-folder-zip-not-lost.md** — v0.0.69: архивы из папки без документов не теряются (добавляются как есть); раскрытие zip с документами; склонение счётчика. - **2026-08-24-ui-locks-session-freeze.md** — v0.0.66: блокировки UI (выбор/удаление) на время работы, заморозка сессии + кнопка «Новая сессия». ## upload/ — загрузка файлов diff --git a/History/ux-frontend/2026-08-24-folder-zip-not-lost.md b/History/ux-frontend/2026-08-24-folder-zip-not-lost.md new file mode 100644 index 0000000..3cfe7f9 --- /dev/null +++ b/History/ux-frontend/2026-08-24-folder-zip-not-lost.md @@ -0,0 +1,33 @@ +# v0.0.69 — Архивы из папки: не терять, раскрывать документы (2026-08-24) + +_ux-frontend. После ретеста v0.0.68 пользователем на проде._ + +## Ситуация +Пользователь выбрал папку, в которой лежали `iviconfig8257.zip` (17.1 KB) и +`Nail_Nevrolog_20250602.PDF`. Добавился только PDF («Добавлено из папки: 1 файлов»), +zip не раскрылся. Требование: «если в папке архив — его надо раскрывать!». + +## Диагностика (Playwright на проде, v0.0.68) +- Сервер отдавал v0.0.68 с кнопкой — деплой прошёл; первая загрузка страницы + показывала старый кэш v0.0.67 (нужен reload). +- Собранный в браузере валидный zip с документами в подпапке — обработчик папки + РАСКРЫВАЕТ корректно: файлы добавляются с префиксом пути (`Подпапка/Договор…`), + статус «Добавлено из папки: 4 файлов». +- Вывод: `iviconfig8257.zip` не раскрылся, потому что ВНУТРИ нет документов + (конфиги/прочее) — `listZipFiles` вернул пусто. Оба обработчика (fileInput и + folderInput) молча ТЕРЯЛИ такой архив. + +## Фикс (site/templates/index.html) +1. `fi`-обработчик: `nested.length` → добавлять файлы; иначе — архив как есть. +2. `folder`-обработчик: то же для zip из папки (если документов нет — архив как есть). +3. Склонение счётчика: «1 файл / 2 файла / 5 файлов». + +Поведение после фикса: +- В папке zip с документами → раскрывается (файлы с путём в таблицу). +- В папке zip без документов / нераспакованный → добавляется как zip, не теряется. + +## Проверка +- `node --check` — OK, `py_compile` — OK. +- Локальный запуск на 127.0.0.1:5010 (v0.0.69), сценарий папки + [zip-конфиг + PDF] → «✅ Добавлено из папки: 2 файла», в таблице оба файла. +- Версия 0.0.68 → 0.0.69. diff --git a/site/app.py b/site/app.py index 4b20c5c..ba46014 100644 --- a/site/app.py +++ b/site/app.py @@ -21,7 +21,7 @@ if _sys_path_root not in sys.path: sys.path.insert(0, _sys_path_root) # Версия приложения (меняется при изменениях) -VERSION = "0.0.68" +VERSION = "0.0.69" def setup_logging(): diff --git a/site/templates/index.html b/site/templates/index.html index 97222b2..8652626 100644 --- a/site/templates/index.html +++ b/site/templates/index.html @@ -555,7 +555,8 @@ fi.addEventListener('change', async () => { if (f.name.toLowerCase().endsWith('.zip')) { try { const nested = await listZipFiles(f); - nested.forEach(x => addFileWithDedup(x)); + if (nested.length) nested.forEach(x => addFileWithDedup(x)); + else addFileWithDedup(f); // в архиве нет документов — добавить архив как есть } catch (err) { addFileWithDedup(f); // не удалось распаковать — добавить zip как есть } @@ -596,9 +597,15 @@ folderInput.addEventListener('change', async () => { if (low.endsWith('.zip')) { try { const nested = await listZipFiles(f); - for (const nf of nested) { - const nm = relDir ? relDir + '/' + nf.name : nf.name; - addFileWithDedup(new File([nf], nm, { lastModified: nf.lastModified })); + if (nested.length) { + for (const nf of nested) { + const nm = relDir ? relDir + '/' + nf.name : nf.name; + addFileWithDedup(new File([nf], nm, { lastModified: nf.lastModified })); + added++; + } + } else { + // в архиве нет документов — добавить архив как есть, чтобы не терялся + addFileWithDedup(new File([f], rel, { lastModified: f.lastModified })); added++; } } catch (err) { @@ -616,7 +623,12 @@ folderInput.addEventListener('change', async () => { } folderInput.value = ''; // чтобы повторный выбор той же папки сработал rr(); - if (added) { st.className = 'status done'; st.textContent = '✅ Добавлено из папки: ' + added + ' файлов'; } + if (added) { + st.className = 'status done'; + const n = added; + const w = (n % 10 === 1 && n % 100 !== 11) ? 'файл' : (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 'файла' : 'файлов'; + st.textContent = '✅ Добавлено из папки: ' + n + ' ' + w; + } }); function ss(idx, h) { const e = document.getElementById('st-' + idx); if (e) e.innerHTML = h; }