feat: make file picker embeddable
This commit is contained in:
+7
-1
@@ -10,7 +10,7 @@ with (ROOT / "config.json").open(encoding="utf-8") as config_file:
|
||||
CONFIG = json.load(config_file)
|
||||
|
||||
|
||||
VERSION = "0.1.10"
|
||||
VERSION = "0.1.11"
|
||||
|
||||
# Flask нужен здесь только как статический сервер HTML, CSS и ES-модулей.
|
||||
app = Flask(__name__, template_folder="templates", static_folder="static")
|
||||
@@ -34,5 +34,11 @@ def upload_frontend(filename):
|
||||
return send_from_directory(ROOT / "upload" / "frontend", filename)
|
||||
|
||||
|
||||
@app.get("/file-picker/<path:filename>")
|
||||
def file_picker_dist(filename):
|
||||
"""Отдаёт собранный универсальный picker-бандл из каталога dist."""
|
||||
return send_from_directory(ROOT / "dist", filename)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=False, host="0.0.0.0", port=5000)
|
||||
@@ -17,44 +17,15 @@
|
||||
</header>
|
||||
<!-- Скрытые input дают браузеру FileList; кнопки ниже программно вызывают click(). -->
|
||||
<section class="toolbar" aria-label="Выбор файлов">
|
||||
<input id="file-input" type="file" accept=".pdf,.doc,.docx,.txt,.md,.zip" multiple hidden>
|
||||
<input id="folder-input" type="file" accept=".pdf,.doc,.docx,.txt,.md,.zip" webkitdirectory directory multiple hidden>
|
||||
<button id="files-btn" type="button">Выбрать файлы</button>
|
||||
<button id="folder-btn" type="button" class="secondary">Выбрать папку</button>
|
||||
<button id="clear-btn" type="button" class="quiet">Очистить</button>
|
||||
<div id="file-picker"></div>
|
||||
</section>
|
||||
<!-- Сюда могут выводиться сообщения интегратора; таблица использует отдельный render(). -->
|
||||
<p id="status" class="status" role="status"></p>
|
||||
<!-- tableBodyEl является обязательным DOM-контрактом initUploadTable. -->
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>Путь</th><th>Размер</th><th>Статус</th><th></th></tr></thead>
|
||||
<tbody id="table-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- countEl обновляется render() и включает leaf-файлы даже в свернутых группах. -->
|
||||
<p id="count" class="count"></p>
|
||||
</main>
|
||||
<!-- fflate должен быть загружен до ES-модулей, потому что ZIP-парсер использует global fflate. -->
|
||||
<script src="{{ url_for('static', filename='vendor/fflate.min.js') }}"></script>
|
||||
<script type="module">
|
||||
// Конфигурация приходит из Flask; DOM-ссылки передаются в переиспользуемый picker.
|
||||
import { initUploadTable } from "/upload-frontend/table/init_upload_table.js";
|
||||
|
||||
const cfg = {{ config|tojson }};
|
||||
const table = initUploadTable({
|
||||
...cfg,
|
||||
fileInputEl: document.querySelector('#file-input'),
|
||||
folderInputEl: document.querySelector('#folder-input'),
|
||||
tableBodyEl: document.querySelector('#table-body'),
|
||||
countEl: document.querySelector('#count'),
|
||||
<script src="{{ url_for('file_picker_dist', filename='file-picker.iife.js', v=version) }}"></script>
|
||||
<script>
|
||||
FilePicker.initFilePicker({
|
||||
mount: '#file-picker',
|
||||
allowedExt: {{ config.allowedExt|tojson }},
|
||||
});
|
||||
// status зарезервирован для интегратора; picker сейчас обновляет только таблицу и count.
|
||||
const status = document.querySelector('#status');
|
||||
// Кнопки не содержат собственной логики выбора: весь state остаётся внутри table API.
|
||||
document.querySelector('#files-btn').onclick = () => table.pickFiles();
|
||||
document.querySelector('#folder-btn').onclick = () => table.pickFolder();
|
||||
document.querySelector('#clear-btn').onclick = () => table.clear();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user