- копирую модуль upload/ из drhider (слои 1-2) - blueprint: параметр sink (drhider-сессия по умолчанию, сверка — DB+парсинг) - upload_bp: contracts_upload_sink = _store_and_parse - routes: регистрирую create_upload_refs_blueprint(cfg, sink=...) - app.py: корень репо в sys.path (для import upload) - History: план переиспользования + ревью Соннета
59 lines
3.0 KiB
JavaScript
59 lines
3.0 KiB
JavaScript
// Обработчик <input webkitdirectory> change: выбор целой папки, рекурсивно,
|
|
// относительный путь сохраняется (верхняя папка отбрасывается).
|
|
|
|
import { listZipFiles } from '../zip/list_zip_files.js';
|
|
import { addFileWithDedup } from './add_file_with_dedup.js';
|
|
import { render } from './render.js';
|
|
|
|
// Фабрика обработчика change для input выбора папки.
|
|
// ctx = { state, cfg, els, onStatus }
|
|
export function makeFolderChangeHandler(ctx) {
|
|
const { state, cfg, els, onStatus } = ctx;
|
|
return async () => {
|
|
if (state.busy) return; // во время загрузки/обработки менять список нельзя
|
|
const incoming = Array.from(els.folderInput.files);
|
|
if (!incoming.length) return;
|
|
document.body.style.cursor = 'wait';
|
|
if (onStatus) onStatus('progress', 'Разбираю папку…');
|
|
let added = 0;
|
|
try {
|
|
for (const f of incoming) {
|
|
// webkitRelativePath: "TopFolder/Подпапка/file.pdf" — отбрасываем верхнюю папку
|
|
const parts = (f.webkitRelativePath || f.name).split('/');
|
|
const rel = parts.slice(1).join('/') || f.name;
|
|
const low = rel.toLowerCase();
|
|
const slashIdx = rel.lastIndexOf('/');
|
|
const relDir = slashIdx >= 0 ? rel.slice(0, slashIdx) : '';
|
|
if (low.endsWith('.zip')) {
|
|
try {
|
|
const nested = await listZipFiles(f, cfg.allowedExt);
|
|
if (nested.length) {
|
|
for (const nf of nested) {
|
|
const nm = relDir ? relDir + '/' + nf.name : nf.name;
|
|
if (addFileWithDedup(state, new File([nf], nm, { lastModified: nf.lastModified }), cfg)) added++;
|
|
}
|
|
} else {
|
|
// в архиве нет документов — добавить архив как есть, чтобы не терялся
|
|
if (addFileWithDedup(state, new File([f], rel, { lastModified: f.lastModified }), cfg)) added++;
|
|
}
|
|
} catch (err) {
|
|
if (addFileWithDedup(state, new File([f], rel, { lastModified: f.lastModified }), cfg)) added++; // zip как есть
|
|
}
|
|
} else if (cfg.allowedExt.some(e => low.endsWith(e))) {
|
|
if (addFileWithDedup(state, new File([f], rel, { lastModified: f.lastModified }), cfg)) added++;
|
|
}
|
|
// иначе — не документ, пропускаем
|
|
}
|
|
} finally {
|
|
document.body.style.cursor = '';
|
|
}
|
|
els.folderInput.value = ''; // чтобы повторный выбор той же папки сработал
|
|
render(state, els, cfg);
|
|
if (added && onStatus) {
|
|
const n = added;
|
|
const w = (n % 10 === 1 && n % 100 !== 11) ? 'файл' : (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 'файла' : 'файлов';
|
|
onStatus('done', '✅ Добавлено из папки: ' + n + ' ' + w);
|
|
}
|
|
};
|
|
}
|