From 9098f425f9c83b246d73bdc91c3e80aa891ebf0b Mon Sep 17 00:00:00 2001 From: Evgenii Alekseev Date: Tue, 1 Jul 2025 12:16:15 +0300 Subject: [PATCH] feat: add cookies support and improve autorefresh UX This commit also includes changing of load logic to update row by row instead of full table toggle. It also changes behaviour on openned dropdowns blocking refresh --- .../ahriman/templates/build-status.jinja2 | 6 +- .../build-status/package-info-modal.jinja2 | 7 +- .../templates/build-status/table.jinja2 | 130 ++++++++++-------- .../share/ahriman/templates/repo-index.jinja2 | 65 ++++----- .../templates/utils/bootstrap-scripts.jinja2 | 89 ++++++++++-- .../ahriman/templates/utils/style.jinja2 | 12 +- 6 files changed, 191 insertions(+), 118 deletions(-) diff --git a/package/share/ahriman/templates/build-status.jinja2 b/package/share/ahriman/templates/build-status.jinja2 index 8b8c4134..9601d67b 100644 --- a/package/share/ahriman/templates/build-status.jinja2 +++ b/package/share/ahriman/templates/build-status.jinja2 @@ -99,6 +99,8 @@ + data-toolbar="#toolbar" + data-unique-id="id"> diff --git a/package/share/ahriman/templates/build-status/package-info-modal.jinja2 b/package/share/ahriman/templates/build-status/package-info-modal.jinja2 index 1ba2556c..4a968736 100644 --- a/package/share/ahriman/templates/build-status/package-info-modal.jinja2 +++ b/package/share/ahriman/templates/build-status/package-info-modal.jinja2 @@ -80,8 +80,7 @@ data-classes="table table-hover" data-sortable="true" data-sort-name="timestamp" - data-sort-order="desc" - data-toggle="table"> + data-sort-order="desc"> @@ -509,6 +508,8 @@ } ready(_ => { + packageInfoEventsTable.bootstrapTable({}); + packageInfoEventsUpdateChart = new Chart(packageInfoEventsUpdateChartCanvas, { type: "line", data: {}, @@ -539,5 +540,7 @@ clearInterval(packageInfoAutoReloadTask); packageInfoAutoReloadTask = null; // not really required (?) but lets clear everything }); + + restoreAutoReloadSettings(packageInfoAutoReloadButton, packageInfoAutoReloadInput); }); diff --git a/package/share/ahriman/templates/build-status/table.jinja2 b/package/share/ahriman/templates/build-status/table.jinja2 index 7aeb9c7d..93739607 100644 --- a/package/share/ahriman/templates/build-status/table.jinja2 +++ b/package/share/ahriman/templates/build-status/table.jinja2 @@ -113,24 +113,24 @@ convert: response => response.json(), }, data => { - const payload = data.map(description => { - const package_base = description.package.base; - const web_url = description.package.remote.web_url; - return { - id: package_base, - base: web_url ? safeLink(web_url, package_base, package_base).outerHTML : safe(package_base), - version: safe(description.package.version), - packager: description.package.packager ? safe(description.package.packager) : "", - packages: listToTable(Object.keys(description.package.packages)), - groups: listToTable(extractListProperties(description.package, "groups")), - licenses: listToTable(extractListProperties(description.package, "licenses")), - timestamp: new Date(1000 * description.status.timestamp).toISOStringShort(), - status: description.status.status, - }; - }); + const payload = data + .map(description => { + const package_base = description.package.base; + const web_url = description.package.remote.web_url; + return { + id: package_base, + base: web_url ? safeLink(web_url, package_base, package_base).outerHTML : safe(package_base), + version: safe(description.package.version), + packager: description.package.packager ? safe(description.package.packager) : "", + packages: listToTable(Object.keys(description.package.packages)), + groups: listToTable(extractListProperties(description.package, "groups")), + licenses: listToTable(extractListProperties(description.package, "licenses")), + timestamp: new Date(1000 * description.status.timestamp).toISOStringShort(), + status: description.status.status, + }; + }); - table.bootstrapTable("load", payload); - table.bootstrapTable("uncheckAll"); + updateTable(table, payload); table.bootstrapTable("hideLoading"); }, error => { @@ -241,15 +241,20 @@ function toggleTableAutoReload(interval) { clearInterval(tableAutoReloadTask); tableAutoReloadTask = toggleAutoReload(tableAutoReloadButton, interval, tableAutoReloadInput, _ => { - if ((getSelection().length === 0) && - (table.bootstrapTable("getOptions").pageNumber === 1) && - (!dashboardModal.classList.contains("show"))) { + if (!dashboardModal.classList.contains("show") && + !hasActiveDropdown()) { reload(true); } }); } ready(_ => { + const onCheckFunction = function () { + if (packageRemoveButton) { + packageRemoveButton.disabled = !getSelection().length; + } + }; + document.querySelectorAll("#repositories a").forEach(element => { element.onclick = _ => { repository = { @@ -264,49 +269,52 @@ }; }); - table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", _ => { - if (packageRemoveButton) { - packageRemoveButton.disabled = !table.bootstrapTable("getSelections").length; - } - }); - table.on("click-row.bs.table", (self, data, row, cell) => { - if (0 === cell || "base" === cell) { - const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript - table.bootstrapTable(method, {field: "id", values: [data.id]}); - } else showPackageInfo(data.id); - }); - table.on("created-controls.bs.table", _ => { - new easepick.create({ - element: document.querySelector(".bootstrap-table-filter-control-timestamp"), - css: [ - "https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css", - ], - grid: 2, - calendars: 2, - autoApply: false, - locale: { - cancel: "Clear", - }, - RangePlugin: { - tooltip: false, - }, - plugins: [ - "RangePlugin", - ], - setup: picker => { - picker.on("select", _ => { table.bootstrapTable("triggerSearch"); }); - // replace "Cancel" behaviour to "Clear" - picker.onClickCancelButton = element => { - if (picker.isCancelButton(element)) { - picker.clear(); - picker.hide(); - table.bootstrapTable("triggerSearch"); - } - }; - }, - }); + table.bootstrapTable({ + onCheck: onCheckFunction, + onCheckAll: onCheckFunction, + onClickRow: (data, row, cell) => { + if (0 === cell || "base" === cell) { + const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript + table.bootstrapTable(method, {field: "id", values: [data.id]}); + } else showPackageInfo(data.id); + }, + onCreatedControls: _ => { + new easepick.create({ + element: document.querySelector(".bootstrap-table-filter-control-timestamp"), + css: [ + "https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css", + ], + grid: 2, + calendars: 2, + autoApply: false, + locale: { + cancel: "Clear", + }, + RangePlugin: { + tooltip: false, + }, + plugins: [ + "RangePlugin", + ], + setup: picker => { + picker.on("select", _ => { table.bootstrapTable("triggerSearch"); }); + // replace "Cancel" behaviour to "Clear" + picker.onClickCancelButton = element => { + if (picker.isCancelButton(element)) { + picker.clear(); + picker.hide(); + table.bootstrapTable("triggerSearch"); + } + }; + }, + }); + }, + onUncheck: onCheckFunction, + onUncheckAll: onCheckFunction, }); + restoreAutoReloadSettings(tableAutoReloadButton, tableAutoReloadInput); + selectRepository(); {% if autorefresh_intervals %} toggleTableAutoReload(); diff --git a/package/share/ahriman/templates/repo-index.jinja2 b/package/share/ahriman/templates/repo-index.jinja2 index ab1e7c9a..326f20ea 100644 --- a/package/share/ahriman/templates/repo-index.jinja2 +++ b/package/share/ahriman/templates/repo-index.jinja2 @@ -53,8 +53,7 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa data-show-search-clear-button="true" data-sortable="true" data-sort-name="base" - data-sort-order="asc" - data-toggle="table"> + data-sort-order="asc"> @@ -128,36 +127,38 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa } ready(_ => { - table.on("created-controls.bs.table", _ => { - new easepick.create({ - element: document.querySelector(".bootstrap-table-filter-control-timestamp"), - css: [ - "https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css", - ], - grid: 2, - calendars: 2, - autoApply: false, - locale: { - cancel: "Clear", - }, - RangePlugin: { - tooltip: false, - }, - plugins: [ - "RangePlugin", - ], - setup: picker => { - picker.on("select", _ => { table.bootstrapTable("triggerSearch"); }); - // replace "Cancel" behaviour to "Clear" - picker.onClickCancelButton = element => { - if (picker.isCancelButton(element)) { - picker.clear(); - picker.hide(); - table.bootstrapTable("triggerSearch"); - } - }; - }, - }); + table.bootstrapTable({ + onCreatedControls: _ => { + new easepick.create({ + element: document.querySelector(".bootstrap-table-filter-control-timestamp"), + css: [ + "https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css", + ], + grid: 2, + calendars: 2, + autoApply: false, + locale: { + cancel: "Clear", + }, + RangePlugin: { + tooltip: false, + }, + plugins: [ + "RangePlugin", + ], + setup: picker => { + picker.on("select", _ => { table.bootstrapTable("triggerSearch"); }); + // replace "Cancel" behaviour to "Clear" + picker.onClickCancelButton = element => { + if (picker.isCancelButton(element)) { + picker.clear(); + picker.hide(); + table.bootstrapTable("triggerSearch"); + } + }; + }, + }); + }, }); }); diff --git a/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 b/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 index 52a3639c..de544f95 100644 --- a/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 +++ b/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 @@ -1,23 +1,26 @@ - + - - + + - - - + + + + - + - + + +
date
package