From 096fa5c94b91d7b30e0e993b268d5869d5379883 Mon Sep 17 00:00:00 2001 From: michaelzicc <4149625+michaelzicc@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:01:30 -0600 Subject: [PATCH] Add Filters (#278) * Add Diagram Filters on Sidebar * Move filters into its own Accordion * Fix indention --- Emrald_Site/scripts/UI/Sidebar.js | 259 ++++++++++++++++++++++++++---- 1 file changed, 228 insertions(+), 31 deletions(-) diff --git a/Emrald_Site/scripts/UI/Sidebar.js b/Emrald_Site/scripts/UI/Sidebar.js index 5af9c760..4841bba2 100644 --- a/Emrald_Site/scripts/UI/Sidebar.js +++ b/Emrald_Site/scripts/UI/Sidebar.js @@ -406,6 +406,108 @@ if (typeof Navigation === 'undefined') buttonLocal.id = "Button_Dynamic_local" buttonLocal.innerHTML = 'Local'; buttonLocal.className = "SidebarButton"; + + var setUpFilters = function () { + let divFilters = document.createElement('div'); + divFilters.id = "Sidebar_Dynamic_Filters"; + let filterH3 = document.createElement('h3'); + let filterH3Span = document.createElement('span'); + filterH3Span.textContent = "Filters"; + filterH3.appendChild(filterH3Span); + divFilters.appendChild(filterH3); + + let filtersDiv = document.createElement('div'); + filtersDiv.style.padding = "0.5em"; + filtersDiv.id = "Sidebar_Filters_Content" + filtersDiv.className = "CategorySection"; + let diagramTypeFilterDropdownElement = document.createElement("select"); + let diagramFilterDropdownElement = document.createElement("select"); + diagramFilterDropdownElement.style.display = "none"; + + let diagramTypes = ["", ... new Set(simApp.allDataModel.DiagramList.map((diagram) => diagram.Diagram.diagramLabel))]; + for (let category of diagramTypes) { + const optionElement = document.createElement("option"); + optionElement.text = category; + diagramTypeFilterDropdownElement.add(optionElement); + } + + diagramTypeFilterDropdownElement.addEventListener("change", function () { + // First, clear exising options from the diagramFilter Dropdown + while (diagramFilterDropdownElement.options.length > 0) { + diagramFilterDropdownElement.remove(0); + } + + let filterType = diagramTypeFilterDropdownElement.value; + + diagramFilterDropdownElement.value = ""; + filterChanged(); + + if (filterType === "") { + diagramFilterDropdownElement.style.display = "none"; + let divAll = document.getElementById("Sidebar_Dynamic_All"); + setupCategories(divAll, container); + return; + } + diagramFilterDropdownElement.style.display = "block"; + + let matchingDiagrams = simApp.allDataModel.DiagramList.filter(diagram => diagram.Diagram.diagramLabel === filterType); + let /** @type {string[]} */ diagramFilterDropdownOptions = ["", ...matchingDiagrams.map(diagram => diagram.Diagram.name)]; + + for (let option of diagramFilterDropdownOptions) { + const optionElement = document.createElement("option"); + optionElement.text = option; + diagramFilterDropdownElement.add(optionElement); + } + }); + + + var filterChanged = function () { + let filterDiagram = diagramFilterDropdownElement.value; + + let divAll = document.getElementById("Sidebar_Dynamic_All"); + setupCategories(divAll, container); + if (filterDiagram === "") { + filterH3Span.textContent = "Filters"; + return; + } + filterH3Span.textContent = "Filters (Active)"; + } + + + var setupCategories = function (/** @type {HTMLElement | null} */ divAll, container) { + if (divAll == null) return; + sbObj.sidebar.dynamCategories.forEach(function (/** @type {{ title: string; id: string; }} */ cat) { + + cat.id = cat.title + "Panel_id"; + let cdiv = document.getElementById(cat.id); + if (!cdiv) { + var h3 = document.createElement('h3'); + h3.textContent = "All " + cat.title; + + var cMenu = getContextMenu(cat, h3); + $(h3).contextmenu(cMenu); + divAll.appendChild(h3); + cdiv = document.createElement('div'); + cdiv.id = cat.id; //Assign the id from the sidebar.json "DiagramsPanel_id", "StatesPanel_id", "LogicTreesPanel_id", "ActionsPanel_id", "EventsPanel_id", "VariablesPanel_id", "ExtSimPanel_id" + + cdiv.className = "CategorySection"; + divAll.appendChild(cdiv); + } else { cdiv.innerHTML = ""; } + sidebar.loadFilteredContent(cdiv, cat, diagramTypeFilterDropdownElement.value, diagramFilterDropdownElement.value); + + }.bind(this)); + } + let divAll = document.getElementById("Sidebar_Dynamic_All"); + setupCategories(divAll, container); + + diagramFilterDropdownElement.addEventListener("change", filterChanged); + + filtersDiv.appendChild(diagramTypeFilterDropdownElement); + filtersDiv.appendChild(diagramFilterDropdownElement); + divFilters.appendChild(filtersDiv); + container.appendChild(divFilters); + sidebar.ApplyJqueryUi(divFilters.id); + } var setUpLocal = function () { //Reset the color of global button to default and set color of local to be dark buttonLocal.style.backgroundColor = '#d7ebf9'; @@ -460,38 +562,29 @@ if (typeof Navigation === 'undefined') buttonAll.style.backgroundColor = '#d7ebf9'; var divAll = document.createElement('div'); divAll.id = "Sidebar_Dynamic_All"; - sbObj.sidebar.dynamCategories.forEach(function (cat) { - var h3 = document.createElement('h3'); - switch (cat.title) { - case "States": - h3.textContent = "All " + cat.title; - cat.id = "StatesPanel_id"; - break; - case "Actions": - h3.textContent = "All " + cat.title; - cat.id = "ActionsPanel_id"; - break; - case "Events": - h3.textContent = "All " + cat.title; - cat.id = "EventsPanel_id"; - break; - case "Variables": + var setupCategories = function(/** @type {HTMLDivElement} */ divAll, container) { + sbObj.sidebar.dynamCategories.forEach(function (/** @type {{ title: string; id: string; }} */ cat) { + + cat.id = cat.title + "Panel_id"; + let cdiv = document.getElementById(cat.id); + if (!cdiv) { + var h3 = document.createElement('h3'); h3.textContent = "All " + cat.title; - cat.id = "VariablesPanel_id"; - break; - } - var cMenu = getContextMenu(cat, h3); - $(h3).contextmenu(cMenu); - divAll.appendChild(h3); - var cdiv = document.createElement('div'); - cdiv.id = cat.id; //Assign the id from the sidebar.json "DiagramsPanel_id", "StatesPanel_id", "LogicTreesPanel_id", "ActionsPanel_id", "EventsPanel_id", "VariablesPanel_id", "ExtSimPanel_id" + var cMenu = getContextMenu(cat, h3); + $(h3).contextmenu(cMenu); + divAll.appendChild(h3); + cdiv = document.createElement('div'); + cdiv.id = cat.id; //Assign the id from the sidebar.json "DiagramsPanel_id", "StatesPanel_id", "LogicTreesPanel_id", "ActionsPanel_id", "EventsPanel_id", "VariablesPanel_id", "ExtSimPanel_id" - cdiv.className = "CategorySection"; - divAll.appendChild(cdiv); - sidebar.loadContent(cdiv, cat); + cdiv.className = "CategorySection"; + divAll.appendChild(cdiv); + } else { cdiv.innerHTML = ""; } + sidebar.loadFilteredContent(cdiv, cat, "", ""); - }.bind(this)); + }.bind(this)); + } + setupCategories(divAll, container); container.appendChild(divAll); sidebar.ApplyJqueryUi(divAll.id); }; @@ -555,8 +648,9 @@ if (typeof Navigation === 'undefined') label.className = "modelLabel"; label.textContent = "Modeling Items"; - var spacer2 = document.createElement('hr'); - spacer.className = "sidebarSpace"; + var spacer2 = document.createElement('hr'); + spacer.className = "sidebarSpace"; + spacer2.className = "sidebarSpace"; buttonLocal.onclick = function () { sidebar.showDynamicSidebar("local"); } buttonAll.onclick = function () { sidebar.showDynamicSidebar("all"); } @@ -565,13 +659,14 @@ if (typeof Navigation === 'undefined') container.appendChild(div); this.ApplyJqueryUi(div.id); container.appendChild(spacer); + setUpFilters(); + container.appendChild(spacer2); //container.appendChild(label); var buttonGroup = document.createElement('btn-group'); buttonGroup.appendChild(buttonAll); buttonGroup.appendChild(buttonGlobal); buttonGroup.appendChild(buttonLocal); container.appendChild(buttonGroup); - //container.appendChild(spacer2); setUpLocal(); setUpAll(); setUpGlobal(); @@ -598,6 +693,8 @@ if (typeof Navigation === 'undefined') var globalButton = document.getElementById("Button_Dynamic_global"); var allButton = document.getElementById("Button_Dynamic_All"); + let filtersAccordion = document.getElementById("Sidebar_Dynamic_Filters"); + if (type == "global") { localElement.parentNode.insertBefore(localElement, allElement); globalElement.parentNode.insertBefore(globalElement, localElement); @@ -608,6 +705,7 @@ if (typeof Navigation === 'undefined') globalButton.style.backgroundColor = '#d7ebf9'; localButton.style.backgroundColor = ''; allButton.style.backgroundColor = ''; + filtersAccordion.style.display = 'none'; } else if (type == "all") { localElement.parentNode.insertBefore(localElement, globalElement); @@ -618,6 +716,7 @@ if (typeof Navigation === 'undefined') allButton.style.backgroundColor = '#d7ebf9'; localButton.style.backgroundColor = ''; globalButton.style.backgroundColor = ''; + filtersAccordion.style.display = ''; } else { ///localElement.clone().insertBefore(globalElement); @@ -629,6 +728,7 @@ if (typeof Navigation === 'undefined') globalButton.style.backgroundColor = ''; localButton.style.backgroundColor = '#d7ebf9'; allButton.style.backgroundColor = ''; + filtersAccordion.style.display = 'none'; } } @@ -4277,6 +4377,96 @@ if (typeof Navigation === 'undefined') } } + //------------------------------------------ + //Assign the id from the sidebar.json "DiagramsPanel_id", "StatesPanel_id", "LogicTreesPanel_id", "ActionsPanel_id", "EventsPanel_id", "VariablesPanel_id", "ExtSimPanel_id" + + Sidebar.prototype.getFilteredLookup = function (container, section, id, /** @type {string}} */ diagramType, /** @type {string}} */ diagramName) { + switch (section) { + case "Diagrams": + if (this.DiagramList) { + this.addDiagramSectionItem(container, this.DiagramList); + } + break; + case "Actions": + if (this.ActionList) { + if (id == "Global_ActionsPanel_id") { + this.ActionList.forEach(function (item) { + var mainItem = item.Action.mainItem; + if (mainItem) { + item.ui_el = this.addSectionItem(container, section, item.Action.name, item.Action); + } + }.bind(this)); + } + else { // It should always come here since filters are only in the "All" tab. + let states = this.statesReferencing(null, diagramName, 'Diagram').forEach((state) => { + let actions = this.actionsReferencing(null, state.name, 'State').forEach(function (item) { + item.ui_el = this.addSectionItem(container, section, item.name, item); + }.bind(this)); + }); + } + sortDOMList(container); + } + break; + case "Events": + if (this.EventList) { + if (id == "Global_EventsPanel_id") { + this.EventList.forEach(function (item) { + if (item.Event.mainItem) { + item.ui_el = this.addSectionItem(container, section, item.Event.name, item.Event); + } + }.bind(this)); + } + else { // It should always come here since filters are only in the "All" tab. + this.statesReferencing(null, diagramName, 'Diagram').forEach((state) => { + this.eventsReferencing(null, state.name, 'State').forEach(function (item) { + item.ui_el = this.addSectionItem(container, section, item.name, item); + }.bind(this)); + }); + } + + sortDOMList(container); + } + break; + case "Logic Tree": + if (this.LogicNodeList) { + this.LogicNodeList.forEach(function (item) { + if (item.LogicNode.isRoot) { + item.ui_el = this.addSectionItem(container, section, item.LogicNode.name, item.LogicNode); + sortDOMList(container); + } + }.bind(this)); + } + break; + case "External Sims": + if (this.ExtSimList) { + this.ExtSimList.forEach(function (item) { + item.ui_el = this.addSectionItem(container, section, item.ExtSim.name, item.ExtSim); + sortDOMList(container); + }.bind(this)); + } + break; + case "Variables": + if (this.VariableList) { + this.VariableList.forEach(function (item) { + var varScope = item.Variable.varScope; + item.ui_el = this.addSectionItem(container, section, item.Variable.name, item.Variable); + sortDOMList(container); + }.bind(this)); + } + break; + case "States": + if (this.StateList) { + + this.statesReferencing(null, diagramName, 'Diagram').forEach(function (item) { + item.ui_el = this.addSectionItem(container, section, item.name, item); + sortDOMList(container); + }.bind(this)); + + } + break; + } + } + //------------------------------------------ Sidebar.prototype.onLoadLocal = function (dataObject) { @@ -4419,6 +4609,13 @@ if (typeof Navigation === 'undefined') var lookup = this.getLookup(container, catInfo.title, catInfo.id); } + Sidebar.prototype.loadFilteredContent = function (container, catInfo, /** @type {string}} */ diagramType, /** @type {string}} */ diagramName) { + if (diagramName === "") { this.loadContent(container, catInfo); } + else { + var lookup = this.getFilteredLookup(container, catInfo.title, catInfo.id, diagramType, diagramName); + } + } + Sidebar.prototype.getActionVariables = function () { var model = simApp.allDataModel; return model.VariableList;