From 63c30e8eb7292e6f0938ec571a27c8ba31665f55 Mon Sep 17 00:00:00 2001 From: Tom Bishop Date: Tue, 23 Jul 2024 12:07:18 -0400 Subject: [PATCH] CLDR-16844 Preliminary refactoring for Dashboard (#3874) --- .../cldr-apps/js/src/esm/cldrDashContext.mjs | 121 ++++++++++++++++++ .../esm/{cldrDash.mjs => cldrDashData.mjs} | 2 +- tools/cldr-apps/js/src/esm/cldrEvent.mjs | 4 +- tools/cldr-apps/js/src/esm/cldrGui.mjs | 94 +------------- tools/cldr-apps/js/src/esm/cldrLoad.mjs | 5 +- tools/cldr-apps/js/src/esm/cldrProgress.mjs | 4 +- tools/cldr-apps/js/src/esm/cldrTable.mjs | 9 +- .../js/src/views/DashboardWidget.vue | 29 ++--- tools/cldr-apps/js/src/views/GeneralInfo.vue | 4 +- .../cldr-apps/js/src/views/OverallErrors.vue | 2 +- ...{TestCldrDash.mjs => TestCldrDashData.mjs} | 18 +-- tools/cldr-apps/js/test/index.js | 4 +- 12 files changed, 159 insertions(+), 137 deletions(-) create mode 100644 tools/cldr-apps/js/src/esm/cldrDashContext.mjs rename tools/cldr-apps/js/src/esm/{cldrDash.mjs => cldrDashData.mjs} (99%) rename tools/cldr-apps/js/test/{TestCldrDash.mjs => TestCldrDashData.mjs} (87%) diff --git a/tools/cldr-apps/js/src/esm/cldrDashContext.mjs b/tools/cldr-apps/js/src/esm/cldrDashContext.mjs new file mode 100644 index 00000000000..a96127f41e8 --- /dev/null +++ b/tools/cldr-apps/js/src/esm/cldrDashContext.mjs @@ -0,0 +1,121 @@ +/* + * cldrDashContext: encapsulate code that determines how the Dashboard is combined with + * other Survey Tool GUI components. + */ + +import * as cldrDrag from "./cldrDrag.mjs"; +import * as cldrNotify from "./cldrNotify.mjs"; +import * as cldrVue from "./cldrVue.mjs"; + +import DashboardWidget from "../views/DashboardWidget.vue"; + +// Caution: these strings also occur literally in other files (.mjs/.vue/.css) +const OPEN_DASH_BUTTON_CLASS = "open-dash"; +const DASH_SECTION_ID = "DashboardSection"; +const NEIGHBOR_SECTION_ID = "VotingEtcSection"; + +/** + * The application instance for the DashboardWidget component when it has been mounted + */ +let wrapper = null; + +/** + * Is the Info Panel currently displayed? + */ +let visible = false; + +function isVisible() { + return visible; // boolean +} + +function wireUpOpenButtons() { + const els = document.getElementsByClassName(OPEN_DASH_BUTTON_CLASS); + for (let i = 0; i < els.length; i++) { + els[i].onclick = () => insert(); + } +} + +/** + * Create or reopen the DashboardWidget Vue component + */ +function insert() { + if (visible) { + return; // already inserted and visible + } + try { + if (wrapper) { + // already created/inserted but invisible + wrapper.reopen(); + } else { + const el = document.getElementById(DASH_SECTION_ID); + wrapper = cldrVue.mountReplace(DashboardWidget, el); + } + show(); + } catch (e) { + cldrNotify.exception(e, "loading Dashboard"); + console.error("Error mounting dashboard vue " + e.message + " / " + e.name); + } +} + +/** + * Show the Dashboard + */ +function show() { + if (visible) { + return; + } + const vote = document.getElementById(NEIGHBOR_SECTION_ID); + const dash = document.getElementById(DASH_SECTION_ID); + if (vote && dash) { + vote.style.height = "50%"; + dash.style.height = "50%"; + dash.style.display = "flex"; + const els = document.getElementsByClassName(OPEN_DASH_BUTTON_CLASS); + for (let i = 0; i < els.length; i++) { + els[i].style.display = "none"; + } + visible = true; + cldrDrag.enable(vote, dash, true /* up/down */); + } +} + +/** + * Hide the Dashboard + */ +function hide() { + if (!visible) { + return; + } + const vote = document.getElementById(NEIGHBOR_SECTION_ID); + const dash = document.getElementById(DASH_SECTION_ID); + if (vote && dash) { + vote.style.height = "100%"; + dash.style.display = "none"; + const els = document.getElementsByClassName(OPEN_DASH_BUTTON_CLASS); + for (let i = 0; i < els.length; i++) { + els[i].style.display = "inline"; + } + visible = false; + } +} + +function updateRow(json) { + if (visible) { + wrapper?.updatePath(json); + } +} + +function updateWithCoverage(newLevel) { + if (visible) { + wrapper?.handleCoverageChanged(newLevel); + } +} + +export { + hide, + insert, + isVisible, + updateRow, + updateWithCoverage, + wireUpOpenButtons, +}; diff --git a/tools/cldr-apps/js/src/esm/cldrDash.mjs b/tools/cldr-apps/js/src/esm/cldrDashData.mjs similarity index 99% rename from tools/cldr-apps/js/src/esm/cldrDash.mjs rename to tools/cldr-apps/js/src/esm/cldrDashData.mjs index f42165ffcdf..f341d70755d 100644 --- a/tools/cldr-apps/js/src/esm/cldrDash.mjs +++ b/tools/cldr-apps/js/src/esm/cldrDashData.mjs @@ -1,5 +1,5 @@ /* - * cldrDash: encapsulate dashboard data. + * cldrDashData: encapsulate dashboard data. */ import * as cldrAjax from "./cldrAjax.mjs"; import * as cldrClient from "./cldrClient.mjs"; diff --git a/tools/cldr-apps/js/src/esm/cldrEvent.mjs b/tools/cldr-apps/js/src/esm/cldrEvent.mjs index d732dd9092a..01d43a12eeb 100644 --- a/tools/cldr-apps/js/src/esm/cldrEvent.mjs +++ b/tools/cldr-apps/js/src/esm/cldrEvent.mjs @@ -4,7 +4,7 @@ * into smaller more specific modules) */ import * as cldrForum from "./cldrForum.mjs"; -import * as cldrGui from "./cldrGui.mjs"; +import * as cldrDashContext from "./cldrDashContext.mjs"; import * as cldrLoad from "./cldrLoad.mjs"; import * as cldrStatus from "./cldrStatus.mjs"; import * as cldrText from "./cldrText.mjs"; @@ -445,7 +445,7 @@ function unpackMenuSideBar(json) { // Note: setCurrentSpecial("general") is dubious here; it doesn't cause // the "general" page to be loaded; it doesn't hide whatever else was displayed. cldrStatus.setCurrentSpecial("general"); - cldrGui.insertDashboard(); + cldrDashContext.insert(); } else { $("#OtherSection").hide(); // Don't hide the other section when showing the dashboard. cldrStatus.setCurrentSpecial(url); diff --git a/tools/cldr-apps/js/src/esm/cldrGui.mjs b/tools/cldr-apps/js/src/esm/cldrGui.mjs index eaab5801a0e..06efc07440a 100644 --- a/tools/cldr-apps/js/src/esm/cldrGui.mjs +++ b/tools/cldr-apps/js/src/esm/cldrGui.mjs @@ -2,7 +2,7 @@ * cldrGui: encapsulate GUI functions for Survey Tool */ import * as cldrAjax from "./cldrAjax.mjs"; -import * as cldrDrag from "./cldrDrag.mjs"; +import * as cldrDashContext from "./cldrDashContext.mjs"; import * as cldrEvent from "./cldrEvent.mjs"; import * as cldrForum from "./cldrForum.mjs"; import * as cldrInfo from "./cldrInfo.mjs"; @@ -14,7 +14,6 @@ import * as cldrStatus from "./cldrStatus.mjs"; import * as cldrSurvey from "./cldrSurvey.mjs"; import * as cldrVue from "./cldrVue.mjs"; -import DashboardWidget from "../views/DashboardWidget.vue"; import MainHeader from "../views/MainHeader.vue"; const GUI_DEBUG = true; @@ -22,9 +21,6 @@ const GUI_DEBUG = true; const runGuiId = "st-run-gui"; let mainHeaderWrapper = null; -let dashboardWidgetWrapper = null; - -let dashboardVisible = false; /** * Set up the DOM and start executing Survey Tool as a single page app @@ -162,10 +158,7 @@ function setOnClicks() { if (el) { el.onclick = () => cldrForum.reload(); } - let els = document.getElementsByClassName("open-dash"); - for (let i = 0; i < els.length; i++) { - els[i].onclick = () => insertDashboard(); - } + cldrDashContext.wireUpOpenButtons(); } const leftSidebar = @@ -411,86 +404,10 @@ function updateWithStatus() { * add more widgets/components that depend on coverage level. */ function updateWidgetsWithCoverage(newLevel) { - if (dashboardVisible) { - dashboardWidgetWrapper?.handleCoverageChanged(newLevel); - } + cldrDashContext.updateWithCoverage(newLevel); cldrProgress.updateWidgetsWithCoverage(); } -/** - * Create or reopen the DashboardWidget Vue component - */ -function insertDashboard() { - if (dashboardVisible) { - return; // already inserted and visible - } - try { - if (dashboardWidgetWrapper) { - // already created/inserted but invisible - dashboardWidgetWrapper.reopen(); - } else { - const el = document.getElementById("DashboardSection"); - dashboardWidgetWrapper = cldrVue.mountReplace(DashboardWidget, el); - } - showDashboard(); - } catch (e) { - cldrNotify.exception(e, "loading Dashboard"); - console.error("Error mounting dashboard vue " + e.message + " / " + e.name); - } -} - -/** - * Show the dashboard - */ -function showDashboard() { - if (dashboardVisible) { - return; - } - const vote = document.getElementById("VotingEtcSection"); - const dash = document.getElementById("DashboardSection"); - if (vote && dash) { - vote.style.height = "50%"; - dash.style.height = "50%"; - dash.style.display = "flex"; - let els = document.getElementsByClassName("open-dash"); - for (let i = 0; i < els.length; i++) { - els[i].style.display = "none"; - } - dashboardVisible = true; - cldrDrag.enable(vote, dash, true /* up/down */); - } -} - -/** - * Hide the dashboard - */ -function hideDashboard() { - if (!dashboardVisible) { - return; - } - const vote = document.getElementById("VotingEtcSection"); - const dash = document.getElementById("DashboardSection"); - if (vote && dash) { - vote.style.height = "100%"; - dash.style.display = "none"; - let els = document.getElementsByClassName("open-dash"); - for (let i = 0; i < els.length; i++) { - els[i].style.display = "inline"; - } - dashboardVisible = false; - } -} - -function dashboardIsVisible() { - return dashboardVisible; // boolean -} - -function updateDashboardRow(json) { - if (dashboardVisible) { - dashboardWidgetWrapper?.updatePath(json); - } -} - function setToptitleVisibility(visible) { const topTitle = document.getElementById("toptitle"); if (topTitle) { @@ -513,14 +430,9 @@ function refreshCounterVetting() { } export { - dashboardIsVisible, - hideDashboard, - insertDashboard, refreshCounterVetting, run, setToptitleVisibility, - showDashboard, - updateDashboardRow, updateWidgetsWithCoverage, updateWithStatus, /* diff --git a/tools/cldr-apps/js/src/esm/cldrLoad.mjs b/tools/cldr-apps/js/src/esm/cldrLoad.mjs index db9742a5c4c..5aa56e4ea68 100644 --- a/tools/cldr-apps/js/src/esm/cldrLoad.mjs +++ b/tools/cldr-apps/js/src/esm/cldrLoad.mjs @@ -7,6 +7,7 @@ import * as cldrAjax from "./cldrAjax.mjs"; import * as cldrBulkClosePosts from "./cldrBulkClosePosts.mjs"; import * as cldrCoverage from "./cldrCoverage.mjs"; import * as cldrCreateLogin from "./cldrCreateLogin.mjs"; +import * as cldrDashContext from "./cldrDashContext.mjs"; import * as cldrDom from "./cldrDom.mjs"; import * as cldrErrorSubtypes from "./cldrErrorSubtypes.mjs"; import * as cldrEvent from "./cldrEvent.mjs"; @@ -109,7 +110,7 @@ function doHashChange(event) { const changedSpecial = oldSpecial != curSpecial; const changedPage = oldPage != trimNull(cldrStatus.getCurrentPage()); if (changedLocale || (changedSpecial && curSpecial)) { - cldrGui.hideDashboard(); + cldrDashContext.hide(); } if (changedLocale || changedSpecial || changedPage) { console.log("# hash changed, (loc, etc) reloadingV.."); @@ -610,7 +611,7 @@ function specialLoad(itemLoadInfo, curSpecial, theDiv) { if (special && special.load) { cldrEvent.hideOverlayAndSidebar(); if (curSpecial !== "general") { - cldrGui.hideDashboard(); + cldrDashContext.hide(); } cldrInfo.closePanel(false /* userWantsHidden */); // Most special.load() functions do not use a parameter; an exception is diff --git a/tools/cldr-apps/js/src/esm/cldrProgress.mjs b/tools/cldr-apps/js/src/esm/cldrProgress.mjs index 76a62546963..a80f3305338 100644 --- a/tools/cldr-apps/js/src/esm/cldrProgress.mjs +++ b/tools/cldr-apps/js/src/esm/cldrProgress.mjs @@ -5,7 +5,7 @@ */ import * as cldrAjax from "./cldrAjax.mjs"; import * as cldrCoverage from "./cldrCoverage.mjs"; -import * as cldrGui from "./cldrGui.mjs"; +import * as cldrDashContext from "./cldrDashContext.mjs"; import * as cldrNotify from "./cldrNotify.mjs"; import * as cldrSchedule from "./cldrSchedule.mjs"; import * as cldrStatus from "./cldrStatus.mjs"; @@ -172,7 +172,7 @@ function refreshPageMeter() { function refreshVoterMeter() { if (voterProgressStats) { - if (!cldrGui.dashboardIsVisible()) { + if (!cldrDashContext.isVisible()) { voterProgressStats = null; progressWrapper?.updateVoterMeter(new MeterData()); } else { diff --git a/tools/cldr-apps/js/src/esm/cldrTable.mjs b/tools/cldr-apps/js/src/esm/cldrTable.mjs index a118bbaa47e..fd6d59171ce 100644 --- a/tools/cldr-apps/js/src/esm/cldrTable.mjs +++ b/tools/cldr-apps/js/src/esm/cldrTable.mjs @@ -11,6 +11,7 @@ import * as cldrAddAlt from "./cldrAddAlt.mjs"; import * as cldrAjax from "./cldrAjax.mjs"; import * as cldrCoverage from "./cldrCoverage.mjs"; +import * as cldrDashContext from "./cldrDashContext.mjs"; import * as cldrDom from "./cldrDom.mjs"; import * as cldrEvent from "./cldrEvent.mjs"; import * as cldrGui from "./cldrGui.mjs"; @@ -304,7 +305,7 @@ function refreshSingleRow(tr, theRow, onSuccess, onFailure) { cldrSurvey.showLoader(cldrText.get("loadingOneRow")); const xhrArgs = { - url: getSingleRowUrl(tr, theRow), + url: getSingleRowUrl(theRow), handleAs: "json", load: closureLoadHandler, error: closureErrHandler, @@ -342,7 +343,7 @@ function singleRowLoadHandler(json, tr, theRow, onSuccess, onFailure) { "singleRowLoadHandler after onSuccess time = " + Date.now() ); } - cldrGui.updateDashboardRow(json); + cldrDashContext.updateRow(json); cldrInfo.showRowObjFunc(tr, tr.proposedcell, tr.proposedcell.showFn); if (CLDR_TABLE_DEBUG) { console.log( @@ -385,11 +386,11 @@ function singleRowErrHandler(err, tr, onFailure) { onFailure("err", err); } -function getSingleRowUrl(tr, theRow) { +function getSingleRowUrl(theRow) { const loc = cldrStatus.getCurrentLocale(); const api = "voting/" + loc + "/row/" + theRow.xpstrid; let p = null; - if (cldrGui.dashboardIsVisible()) { + if (cldrDashContext.isVisible()) { p = new URLSearchParams(); p.append("dashboard", "true"); } diff --git a/tools/cldr-apps/js/src/views/DashboardWidget.vue b/tools/cldr-apps/js/src/views/DashboardWidget.vue index c7bd185ea74..34f850cbb7a 100644 --- a/tools/cldr-apps/js/src/views/DashboardWidget.vue +++ b/tools/cldr-apps/js/src/views/DashboardWidget.vue @@ -186,8 +186,8 @@