diff --git a/assets/sai.css b/assets/sai.css
index bfd5711..914cb88 100644
--- a/assets/sai.css
+++ b/assets/sai.css
@@ -1217,3 +1217,13 @@ body.overlay-active {
width: 10px;
text-align: center;
}
+
+.sai-pagination {
+ text-align: center;
+ margin: 20px 0;
+}
+
+.sai-pagination-info {
+ color: #fff;
+ margin: 0 15px;
+}
diff --git a/assets/sai.js b/assets/sai.js
index df4e768..182fffd 100644
--- a/assets/sai.js
+++ b/assets/sai.js
@@ -406,6 +406,14 @@ var seg_counter = 0;
var pcon_topology = {};
var pcon_energy_cache = {};
var last_builder_list = [];
+var current_overview_offset = 0;
+
+window.change_page = function(new_offset) {
+ current_overview_offset = new_offset;
+ sai.send("{\"schema\":" +
+ "\"com.warmcat.sai.taskinfo\", \"js_api_version\": " + SAI_JS_API_VERSION +
+ ", \"offset\": " + current_overview_offset + "}");
+};
function createPconDiv(pcon) {
const pconDiv = document.createElement("div");
@@ -1849,7 +1857,8 @@ function ws_open_sai()
*/
sai.send("{\"schema\":" +
- "\"com.warmcat.sai.taskinfo\", \"js_api_version\": " + SAI_JS_API_VERSION + "}");
+ "\"com.warmcat.sai.taskinfo\", \"js_api_version\": " + SAI_JS_API_VERSION +
+ ", \"offset\": " + current_overview_offset + "}");
};
sai.onmessage = function got_packet(msg) {
@@ -2034,10 +2043,25 @@ function ws_open_sai()
* display events wholesale
*/
if (jso.overview.length) {
+ var pagination_html = "";
+ if (!gitohashi_integ && jso.total_events > 6) {
+ pagination_html += "<div class=\"sai-pagination\">";
+ if (jso.offset > 0) {
+ pagination_html += "<button class=\"btn sai-pagination-btn\" data-offset=\"" + Math.max(0, jso.offset - 6) + "\">< Newer</button> ";
+ }
+ pagination_html += "<span class=\"sai-pagination-info\">Showing " + (jso.offset + 1) + " - " + Math.min(jso.offset + 6, jso.total_events) + " of " + jso.total_events + "</span>";
+ if (jso.offset + 6 < jso.total_events) {
+ pagination_html += "<button class=\"btn sai-pagination-btn\" data-offset=\"" + (jso.offset + 6) + "\">Older ></button>";
+ }
+ pagination_html += "</div>";
+ }
+
+ s = pagination_html + s;
+
for (n = jso.overview.length - 1; n >= 0; n--)
s += sai_event_render(jso.overview[n], now_ut, 1);
- s = s + "</table>";
+ s = s + "</table>" + pagination_html;
if (document.getElementById("sai_sticky"))
document.getElementById("sai_sticky").innerHTML = s;
@@ -2581,6 +2605,12 @@ window.addEventListener("load", function() {
var id = hdr.id.substring(8);
toggleSegment(id);
}
+ var pbtn = e.target.closest('.sai-pagination-btn');
+ if (pbtn) {
+ if (window.change_page) {
+ window.change_page(parseInt(pbtn.getAttribute('data-offset')));
+ }
+ }
});
const savedFlex = localStorage.getItem('sai-left-pane-flex');
diff --git a/src/common/include/private.h b/src/common/include/private.h
index 8e96344..92aee13 100644
--- a/src/common/include/private.h
+++ b/src/common/include/private.h
@@ -22,7 +22,6 @@
*/
#include <libwebsockets.h>
-#include <sqlite3.h>
#if defined(WIN32)
#define HAVE_STRUCT_TIMESPEC
@@ -69,7 +68,7 @@ enum {
typedef struct sais_sqlite_cache {
lws_dll2_t list;
char uuid[65];
- sqlite3 *pdb;
+ struct sqlite3 *pdb;
lws_usec_t idle_since;
int refcount;
} sais_sqlite_cache_t;
@@ -565,6 +564,7 @@ typedef struct sai_browse_rx_taskinfo {
uint64_t last_log_ts;
unsigned int log_start;
unsigned int js_api_version;
+ unsigned int offset;
uint8_t logs;
} sai_browse_rx_taskinfo_t;
@@ -797,9 +797,9 @@ sai_ss_tx_from_buflist_helper(struct lws_ss_handle *ss, struct lws_buflist **buf
int
sai_event_db_ensure_open(struct lws_context *cx, lws_dll2_owner_t *sqlite3_cache,
const char *sqlite3_path_lhs, const char *event_uuid,
- char create_if_needed, sqlite3 **ppdb);
+ char create_if_needed, struct sqlite3 **ppdb);
void
-sai_event_db_close(lws_dll2_owner_t *sqlite3_cache, sqlite3 **ppdb);
+sai_event_db_close(lws_dll2_owner_t *sqlite3_cache, struct sqlite3 **ppdb);
int
sai_event_db_close_all_now(lws_dll2_owner_t *sqlite3_cache);
@@ -808,5 +808,5 @@ int
sai_event_db_delete_database(const char *sqlite3_path_lhs, const char *event_uuid);
int
-sai_sqlite3_statement(sqlite3 *pdb, const char *cmd, const char *desc);
+sai_sqlite3_statement(struct sqlite3 *pdb, const char *cmd, const char *desc);
diff --git a/src/web/w-private.h b/src/web/w-private.h
index bd27cd7..b2ba540 100644
--- a/src/web/w-private.h
+++ b/src/web/w-private.h
@@ -98,6 +98,7 @@ struct pss {
int specificity;
int segment_flags;
unsigned int js_api_version;
+ unsigned int overview_offset;
/* notification hmac information */
char notification_sig[128];
diff --git a/src/web/w-ws-browser.c b/src/web/w-ws-browser.c
index 8082b74..b0ae98d 100644
--- a/src/web/w-ws-browser.c
+++ b/src/web/w-ws-browser.c
@@ -59,6 +59,7 @@ static lws_struct_map_t lsm_browser_taskinfo[] = {
LSM_CARRAY (sai_browse_rx_taskinfo_t, task_hash, "task_hash"),
LSM_UNSIGNED (sai_browse_rx_taskinfo_t, logs, "logs"),
LSM_UNSIGNED (sai_browse_rx_taskinfo_t, js_api_version, "js_api_version"),
+ LSM_UNSIGNED (sai_browse_rx_taskinfo_t, offset, "offset"),
LSM_UNSIGNED (sai_browse_rx_taskinfo_t, last_log_ts, "last_log_ts"),
};
@@ -601,6 +602,7 @@ saiw_ws_json_rx_browser(struct vhd *vhd, struct pss *pss, uint8_t *buf,
if (ti->js_api_version)
pss->js_api_version = ti->js_api_version;
+ pss->overview_offset = ti->offset;
saiw_browser_broadcast_queue_builders(pss->vhd, pss);
saiw_browser_queue_overview(pss->vhd, pss);
@@ -881,7 +883,7 @@ saiw_browser_queue_overview(struct vhd *vhd, struct pss *pss)
filt[0] = '\0';
esc[0] = '\0';
- n = -8;
+ n = -6;
if (pss->specific_project[0]) {
lws_sql_purify(esc, pss->specific_project, sizeof(esc) - 1);
@@ -889,10 +891,24 @@ saiw_browser_queue_overview(struct vhd *vhd, struct pss *pss)
n = -1;
}
+ unsigned int total_events = 0;
+ {
+ char q[256];
+ sqlite3_stmt *stmt;
+ lws_snprintf(q, sizeof(q), "SELECT COUNT(*) FROM events%s%s",
+ filt[0] ? " WHERE " : "",
+ filt[0] ? filt + 5 : "");
+ if (sqlite3_prepare_v2(vhd->pdb, q, -1, &stmt, NULL) == SQLITE_OK) {
+ if (sqlite3_step(stmt) == SQLITE_ROW)
+ total_events = (unsigned int)sqlite3_column_int(stmt, 0);
+ sqlite3_finalize(stmt);
+ }
+ }
+
pss->wants_event_updates = 1;
if (lws_struct_sq3_deserialize(vhd->pdb, filt[0] ? filt : NULL,
"created ", lsm_schema_sq3_map_event,
- &owner, &ac, 0, n)) {
+ &owner, &ac, (int)pss->overview_offset, n)) {
lwsl_notice("%s: OVERVIEW 2 failed\n", __func__);
return 0;
@@ -907,8 +923,11 @@ saiw_browser_queue_overview(struct vhd *vhd, struct pss *pss)
"{\"schema\":\"sai.warmcat.com.overview\","
" \"api_version\":%u,"
" \"alang\":\"%s\","
+ " \"total_events\":%u,"
+ " \"offset\":%u,"
"\"overview\":[", SAIW_API_VERSION,
- lws_json_purify(esc, pss->alang, sizeof(esc) - 1, NULL)
+ lws_json_purify(esc, pss->alang, sizeof(esc) - 1, NULL),
+ total_events, pss->overview_offset
);
saiw_ws_browser_queue_REQUIRES_LWS_PRE(pss, start,