// Copyright Epic Games, Inc. All Rights Reserved. "use strict"; import { ZenPage } from "./page.js" import { Friendly } from "../util/friendly.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"); const sort_by = this.get_param("sort", -1); this._indexer = this._load_indexer(project, oplog); this.set_title("tree - " + oplog); const section = this.add_section(project + " - " + oplog); this._create_tree(section); this._expand(this._root); this._activate_sort_header(-1, sort_by); } _create_tree(section) { const list = section.tag().id("tree_root").tag("ul"); const root = list.tag("li"); root.attr("part", "/"); const header = root.tag(); header.tag().text("/"); this._sort_headers = [ header.tag().text("size").on_click(() => this._change_sort(0)), header.tag().text("rawsize").on_click(() => this._change_sort(1)), header.tag().text("count").on_click(() => this._change_sort(2)), ]; this._root = 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; } const indexer = await this._indexer; const new_nodes = new Object(); for (var [name, size, raw_size] of indexer.enum_all()) { 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][0] += size; new_nodes[name][1] += raw_size; new_nodes[name][2] += 1; } else new_nodes[name] = [size, raw_size, 1]; } var sort_by = this.get_param("sort", -1)|0; sort_by = Math.min(Math.max(sort_by, -1), 3); 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 == 1) return is_node_l ? -1 : 1; if (sort_by >= 0) return Number(new_nodes[r][sort_by] - new_nodes[l][sort_by]); return 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); for (var i = 0; i < 2; ++i) { const size = Friendly.kib(new_nodes[name][i]); info.tag().text(size); } if (name.endsWith("/")) { const count = Friendly.sep(new_nodes[name][2]); info.tag().text(count); label.on_click((x) => this.expand_collapse(x), item); 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); } _activate_sort_header(current, next) { const impl = (index, is_on) => { if (index >= 0 && index < this._sort_headers.length) this._sort_headers[index].attr("active", is_on ? "" : null); }; impl(current, false); impl(next, true); } _change_sort(sort_by) { const current = this.get_param("sort"); if (current == sort_by) sort_by = -1; this._activate_sort_header(current, sort_by); this.set_param("sort", sort_by); for (var node = this._root.first_child(); node;) { const next = node.next_sibling(); if (node.is("ul")) node.destroy(); node = next; } this._expand(this._root); } }