From: DeltaMikeCharlie <127641886+DeltaMikeCharlie@users.noreply.github.com> Date: Fri, 19 Apr 2024 00:17:53 +0000 (+1000) Subject: Update WebUI to allow debug/trace subsystem selection from a list. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b100585070ef794225397d7b99375a5bef246d46;p=thirdparty%2Ftvheadend.git Update WebUI to allow debug/trace subsystem selection from a list. --- diff --git a/src/webui/static/app/ext.css b/src/webui/static/app/ext.css index eb6d3adae..e477bce04 100644 --- a/src/webui/static/app/ext.css +++ b/src/webui/static/app/ext.css @@ -476,6 +476,14 @@ background-image: url(../icons/networks.png) !important; } +.delete { + background-image: url(../icons/delete.png) !important; +} + +.list { + background-image: url(../icons/list.png) !important; +} + .muxes { background-image: url(../icons/muxes.png) !important; } diff --git a/src/webui/static/app/tvhlog.js b/src/webui/static/app/tvhlog.js index 8294a9b89..af4c724b2 100644 --- a/src/webui/static/app/tvhlog.js +++ b/src/webui/static/app/tvhlog.js @@ -12,10 +12,355 @@ tvheadend.tvhlog = function(panel, index) { tracesubs.setDisabled(!trace.getValue() || trace.disabled); } + //START SUBSYSTEM SELECTION WINDOW CODE + + //Define some variables local to this module. + let debugSubsystemsSaved = ""; + let traceSubsystemsSaved = ""; + + let debugBoxUI = {}; + let traceBoxUI = {}; + + let subsystemStore = {}; + + //Create a button to show in the TVH config/debug toolbar. + //When pressed, this will display the subsystem selection window. + let subsystemsButton = { + name: 'subsys', + builder: function() { + return new Ext.Toolbar.Button({ + tooltip: _('Select trace/debug options from a list of subsystems.'), + iconCls: 'list', + text: _('Select Subsystems'), + disabled: false + }); + }, + callback: function(conf, e, store, select) { + + //Get a list of the subsystems currently entered + //Do it this way instead of looking at the current status from + //the API because the user may be in the middle of a manual change + //and it would be polite to preserve those manual changes. + let debugBox = document.getElementsByName("debugsubs"); + let traceBox = document.getElementsByName("tracesubs"); + + //These are the existing text UI text boxes. + debugBoxUI = debugBox[0]; + traceBoxUI = traceBox[0]; + + //Save the initial UI text box values for a potential + //reset at a later time. + debugSubsystemsSaved = debugBoxUI.value; + traceSubsystemsSaved = traceBoxUI.value; + + //Break down the existing text box values into arrays. + let debugArray = debugBoxUI.value.split(","); + let traceArray = traceBoxUI.value.split(","); + + //Grab the list of subsystems from the server. + //Note that this is an asynchronous call and the + //rest of the module needs to be contained within + //the 'success' method in order to work. + let subsystemList = Ext.Ajax.request({ + url: 'api/tvhlog/subsystem/grid', + success: function(d) { + + //Parse the results of the call and extract the 'entries'. + let subsystemResponse = JSON.parse(d.responseText); + subsystemList = subsystemResponse.entries; + + //Add 'all' to the beginning of the list. + //Subsystem 'all' is not a valid subsystem per-se, + //however, TVH uses it internally to enable all subsystems. + let tempSub = { + id: -1, + subsystem: 'all', + description: _('All subsystems'), + debug: false, + trace: false + }; + subsystemList.unshift(tempSub); + + //Load the starting conditions from the text boxes + //because the user may have already made some manual changes. + let i = 0; + + while (i < subsystemList.length) { + subsystemList[i].debug = debugArray.includes(subsystemList[i].subsystem); + subsystemList[i].trace = traceArray.includes(subsystemList[i].subsystem); + i++; + } + + //Create the reset buttons for the bottom of the window. + let buttons = []; + buttons.push(new Ext.Toolbar.Button({ + handler: function() { + windowButtons(10) + }, + iconCls: 'delete', + text: _('Clear Debug'), + tooltip: _('Clear all debug subsystems.'), + })); + buttons.push(new Ext.Toolbar.Button({ + handler: function() { + windowButtons(11) + }, + iconCls: 'delete', + text: _('Clear Trace'), + tooltip: _('Clear all trace subsystems.'), + })); + buttons.push(new Ext.Toolbar.Button({ + handler: function() { + windowButtons(0) + }, + iconCls: 'undo', + text: _('Restore Debug'), + tooltip: _('Restore the debug subsystems to their initial state.'), + })); + buttons.push(new Ext.Toolbar.Button({ + handler: function() { + windowButtons(1) + }, + iconCls: 'undo', + text: _('Restore Trace'), + tooltip: _('Restore the trace subsystems to their initial state.'), + })); + + //This array will contain all of the elements to be + //rendered onto the subsystem selection window. + let windowItems = []; + + //Create the data store that feeds the grid. + //It takes the JSON response from TVH as its source. + subsystemStore = new Ext.data.JsonStore({ + root: 'entries', + data: subsystemResponse, + autoLoad: true, + id: 'id', + fields: ['debug', 'trace', 'subsystem', 'description'], + remoteSort: false, + }); + + //Take a boolean field and display checkboxes instead + //using existing ExtJS styles to match the TVH look-and-feel. + function subsystemBooleanRenderer(val) { + if (val) { + return '
 
'; + } else { + return '
 
'; + } + } + + //Define the column mode to be used. Note the custom + //rendering for the boolean fields. + let subsystemColumnModel = new Ext.grid.ColumnModel({ + columns: [{ + header: _("Debug"), + width: 50, + id: 'debug', + renderer: subsystemBooleanRenderer + }, + { + header: _("Trace"), + width: 50, + id: 'trace', + renderer: subsystemBooleanRenderer + }, + { + header: _("Subsystem"), + width: 80, + id: 'subsystem' + }, + { + header: _("Description"), + width: 280, + id: 'description' + } + ], + defaults: { + sortable: false, + menuDisabled: true, + width: 100 + } + }); + + + //Read through all of the subsystems and build a UI string. + function getSubsystemString(checkList) { + let debugList = []; + let traceList = []; + + i = 0; + while (i < checkList.length) { + + if (checkList[i].debug) { + debugList.push(checkList[i].subsystem); + } + + if (checkList[i].trace) { + traceList.push(checkList[i].subsystem); + } + + i++; + } + + return { + debug: debugList.toString(), + trace: traceList.toString() + }; + + } //END getSubsystemString + + + //Take the supplied strings and update the UI text boxes. + function updateSubsystemUI(stringValues) { + debugBoxUI.value = stringValues.debug; + traceBoxUI.value = stringValues.trace; + } + + //Taking the row and column coordinates of the grid cell, + //update the boolean values for each debug/trace and then + //update the UI. + function updateSubsystemActions(row, column) { + + let myRecord; + + //Toggle the debug subsystem + if (column == 0) { + subsystemList[row].debug = !subsystemList[row].debug; + myRecord = subsystemStore.getAt(row); + myRecord.set('debug', subsystemList[row].debug); + } + + //Toggle the trace subsystem + if (column == 1) { + subsystemList[row].trace = !subsystemList[row].trace; + myRecord = subsystemStore.getAt(row); + myRecord.set('trace', subsystemList[row].trace); + } + + //Toggle both subsystems + if (column == 2) { + + //If either is off, turn them both on + if (!subsystemList[row].debug || !subsystemList[row].trace) { + subsystemList[row].debug = true; + subsystemList[row].trace = true; + } else { + subsystemList[row].debug = false; + subsystemList[row].trace = false; + } + + myRecord = subsystemStore.getAt(row); + myRecord.set('debug', subsystemList[row].debug); + myRecord.set('trace', subsystemList[row].trace); + } + + //Update the existing UI text fields with the new values. + updateSubsystemUI(getSubsystemString(subsystemList)); + } //END updateSubsystemActions + + //Reset the subsystem selection to its original value. + function resetSubsystems(propertyName, textBoxUI, newValues) { + + let newArray = newValues.split(","); + + //Reset the text box to the previous values + textBoxUI.value = newValues; + + //Loop through all of the subsystems and update their state + //in the array and the store based on the saved state. + let i = 0; + while (i < subsystemList.length) { + + subsystemList[i][propertyName] = newArray.includes(subsystemList[i].subsystem); + let myRecord = subsystemStore.getAt(i); + myRecord.set(propertyName, subsystemList[i][propertyName]); + i++; + } //END while loop + } //END reset subsystems + + + //Handle the buttons at the bottom of the window. + function windowButtons(button) { + + if (button == 0) { + resetSubsystems("debug", debugBoxUI, debugSubsystemsSaved); + } + + if (button == 1) { + resetSubsystems("trace", traceBoxUI, traceSubsystemsSaved); + } + + if (button == 10) { + resetSubsystems("debug", debugBoxUI, ""); + } + + if (button == 11) { + resetSubsystems("trace", traceBoxUI, ""); + } + + + } //End window button handlers. + + + //Creeate the grid to be shown on the subsystem selection window. + let grid = new Ext.grid.GridPanel({ + flex: 1, + autoWidth: true, + autoScroll: true, + stripeRows: true, + store: subsystemStore, + cm: subsystemColumnModel, + border: false, + viewConfig: { + markDirty: false //Hide the red tag that highlights changed records. + }, + listeners: { + cellclick: function(gridView, htmlElement, columnIndex, dataRecord) { + updateSubsystemActions(htmlElement, columnIndex); + } + } //END listeners + }); + + //Add the grid to the list of items to be rendered on the window. + windowItems.push(grid); + + //Create a window to display the list of subsystems. + let windowHeight = Ext.getBody().getViewSize().height - 150; + let subsysWin = new Ext.Window({ + title: _('Select Subsystems'), + iconCls: 'debug', + layout: 'fit', + width: 500, + height: windowHeight, + constrainHeader: true, + buttons: buttons, + buttonAlign: 'center', + autoScroll: true, + items: windowItems + }); + + //Display the subsystem selection window. + subsysWin.show(); + + }, //END AJAX OK + failure: function(response, options) { + Ext.MessageBox.alert(_('Listing Subsystems'), response.statusText); + return ""; + } + }); //END Ajax request for subsystems list. + } //END button callback. + }; //END button object. + + //END SUBSYSTEM SELECTION WINDOW CODE + + //This is the standard debug config screen. tvheadend.idnode_simple(panel, { url: 'api/tvhlog/config', title: _('Configuration'), iconCls: 'debug', + tbar: [subsystemsButton], //Add the button to list the subsystems tabIndex: index, comet: 'tvhlog_conf', labelWidth: 180, diff --git a/src/webui/static/icons/list.png b/src/webui/static/icons/list.png new file mode 100644 index 000000000..f8e50f3c4 Binary files /dev/null and b/src/webui/static/icons/list.png differ