From 471b1c133185395f452f37e017ab52839fd1237d 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 | 7 +- .../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 | 87 ++++++++++-- .../ahriman/templates/utils/style.jinja2 | 12 +- 6 files changed, 190 insertions(+), 118 deletions(-) diff --git a/package/share/ahriman/templates/build-status.jinja2 b/package/share/ahriman/templates/build-status.jinja2 index 8b8c4134..a1a62940 100644 --- a/package/share/ahriman/templates/build-status.jinja2 +++ b/package/share/ahriman/templates/build-status.jinja2 @@ -99,6 +99,9 @@ + 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..ebc35469 100644 --- a/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 +++ b/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 @@ -1,23 +1,24 @@ - + - - + + - - - + + + + - + - +
date
package