aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/frontend/html/pages/tree.js
diff options
context:
space:
mode:
authorMartin Ridgers <[email protected]>2024-11-18 08:41:46 +0100
committerGitHub Enterprise <[email protected]>2024-11-18 08:41:46 +0100
commitcca69117b7ffac5cdd8933148ed9c94dd241528d (patch)
treeba9dfce342e86d9cbdf6cf54059e1e7d618eecee /src/zenserver/frontend/html/pages/tree.js
parentoplog prep gc fix (#216) (diff)
downloadzen-cca69117b7ffac5cdd8933148ed9c94dd241528d.tar.xz
zen-cca69117b7ffac5cdd8933148ed9c94dd241528d.zip
Dashboard: oplog tree view (#217)
* Turned tables and progress bars and friends into "widgets!" * A step to abstracting away a page's the internal DOM structure * Folded sector creation into Page and pivoted it to a widget host * Try and keep start/count as numbers regardless of input * No need for the entry table to be defined up front now * Add op count and log sixe to oplog list page * Cache left side toolbar object * Bounds count page start when building list of oplog entrie * Start/end navigation tools * Build rest of entry page while waiting for indexer to load * Consistent naming with other pages * Spacially consolidate fetching code * Hide fetch latency to speed up index generation workers * Extract dashboard structure from zen.js monolith * Fix breadcrumbs after restructuring * Add view link to actions cell of oplogs list * Generator to enumerate names of entries in indexer * Methods for simple traversal of component relations * is() to check if a component is of a certain type * Extend attr() to get and unset a component's attributes * Unsetting all styles of anchor tags was underisrable * Restore page name as id of container element * A tree view of an oplog * Move helper class out to private module scope * Small tweak to use left var that already exists * Changelog update * Updated frontend .zip archive
Diffstat (limited to 'src/zenserver/frontend/html/pages/tree.js')
-rw-r--r--src/zenserver/frontend/html/pages/tree.js118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/zenserver/frontend/html/pages/tree.js b/src/zenserver/frontend/html/pages/tree.js
new file mode 100644
index 000000000..c3cea0eb5
--- /dev/null
+++ b/src/zenserver/frontend/html/pages/tree.js
@@ -0,0 +1,118 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+"use strict";
+
+import { ZenPage } from "./page.js"
+import { ProgressBar } from "../util/widgets.js"
+import { create_indexer } from "../indexer/indexer.js"
+
+////////////////////////////////////////////////////////////////////////////////
+export class Page extends ZenPage
+{
+ main()
+ {
+ const project = this.get_param("project");
+ const oplog = this.get_param("oplog");
+
+ this._indexer = this._load_indexer(project, oplog);
+
+ this.set_title("tree - " + oplog);
+ const section = this.add_section(project + " - " + oplog);
+
+ const list = section.tag().id("tree_root").tag("ul");
+ const root = list.tag("li");
+ root.attr("part", "/");
+ root.tag().text("/");
+ this._expand(root);
+ }
+
+ async _load_indexer(project, oplog)
+ {
+ const progress_bar = this.add_widget(ProgressBar);
+ progress_bar.set_progress("indexing");
+ var indexer = create_indexer(project, oplog, (...args) => {
+ progress_bar.set_progress(...args);
+ });
+ indexer = await indexer;
+ progress_bar.destroy();
+ return indexer;
+ }
+
+ async _expand(node)
+ {
+ var prefix = "";
+ for (var item = node;; item = item.parent())
+ {
+ if (item.is("div")) break;
+ if (!item.is("li")) continue;
+ prefix = item.attr("part") + prefix;
+ }
+ console.log(prefix);
+
+ const indexer = await this._indexer;
+
+ const new_nodes = new Object();
+ for (var name of indexer.enum_names())
+ {
+ if (!name.startsWith(prefix))
+ continue;
+
+ name = name.substr(prefix.length);
+ const slash = name.indexOf("/");
+ if (slash != -1)
+ name = name.substr(0, slash + 1);
+
+ if (new_nodes[name] === undefined)
+ new_nodes[name] = 1;
+ else
+ new_nodes[name] += 1;
+ }
+
+ const by_count = this.get_param("bycount", 0)|0;
+ const sorted_keys = Object.keys(new_nodes).sort((l, r) => {
+ const is_node_l = l.endsWith("/");
+ const any_nodes = is_node_l + r.endsWith("/");
+ if (any_nodes == 0) return r < l;
+ if (any_nodes == 1) return is_node_l ? -1 : 1;
+ return by_count ? (new_nodes[r] - new_nodes[l]) : (r < l);
+ })
+
+ const list = node.tag("ul");
+ for (const name of sorted_keys)
+ {
+ const item = list.tag("li").attr("part", name);
+ const info = item.tag();
+ const label = info.tag().text(name);
+ if (name.endsWith("/"))
+ {
+ label.on_click((x) => this.expand_collapse(x), item);
+ info.tag().text(new_nodes[name]);
+ continue;
+ }
+
+ item.attr("leaf", "");
+ label.link("", {
+ "page" : "entry",
+ "project" : this.get_param("project"),
+ "oplog" : this.get_param("oplog"),
+ "opkey" : prefix + name,
+ });
+ info.tag();
+ }
+
+ node.attr("expanded", "")
+ }
+
+ _collapse(node)
+ {
+ node.first_child().next_sibling().destroy();
+ node.attr("expanded", null);
+ }
+
+ expand_collapse(node)
+ {
+ if (node.attr("expanded") === null)
+ return this._expand(node);
+ return this._collapse(node);
+ }
+}