From 36e58403651a31ebb3a580ba4f293f4176e1cb0b Mon Sep 17 00:00:00 2001 From: "Noj Vek (Manoj P)" Date: Fri, 31 Aug 2018 13:03:28 -0700 Subject: [PATCH] Show state, component, appState and attrs in panel devtools (#40) * Show state, component, appState and attrs in panel devtools * simplify while loop logic * scope comment * show config as well * manifest.json --- devtools/devtools.js | 54 ++++++++++++++++++++++++++++++------------ devtools/manifest.json | 6 ++--- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/devtools/devtools.js b/devtools/devtools.js index 8c127d28..0b58ca4a 100644 --- a/devtools/devtools.js +++ b/devtools/devtools.js @@ -1,7 +1,8 @@ /* global chrome */ // The function below is executed in the context of the inspected page. +// Event listener global scope is different to inspector scope, so we test for window[`$0`] function getPanelElementState() { - if (!window[`__$panelDevToolsReady`] && window.document.body) { + if (!window[`__$panelDevToolsReady`] && window[`$0`] && window.document.body) { // Chrome extension api doesn't let us know when expression has been edited // Work around is to refresh the UI with latest state on mouseenter window.document.body.addEventListener(`mouseenter`, getPanelElementState); @@ -9,25 +10,48 @@ function getPanelElementState() { } // $0 is not available if called via event listeners - const selectedElem = window[`$0`] || window[`__$panelDevToolsLastSelectedElem`]; - - if (selectedElem) { - // Force an update so UI refreshes to latest edited state - if (selectedElem.controller && selectedElem.controller.state) { - window[`__$panelDevToolsLastSelectedElem`] = selectedElem; - selectedElem.controller._update(); - return selectedElem.controller.state; + let panelElem = window[`$0`] || window[`__$panelDevToolsLastElem`]; + + // Go through ancestors to find a panel element. panelID is used as signifier for a panel component + // This is so user can right click -> inspect element anywhere inside a panel component and see its debug info + while (panelElem) { + if (!panelElem.panelID) { + // using getRootNode().host to jump through shadow dom boundaries as well + panelElem = panelElem.parentElement || panelElem.getRootNode().host; } - else if (selectedElem.state && selectedElem.update) { - window[`__$panelDevToolsLastSelectedElem`] = selectedElem; - selectedElem.update(); - return selectedElem.state; + else { + window[`__$panelDevToolsLastElem`] = panelElem; + const debugInfo = Object.create(null); // Don't show extra __proto__ key in extension tab + debugInfo.$component = panelElem; // so it appears first + debugInfo.config = panelElem.config; + + // Force an update so UI refreshes to latest edited state + if (panelElem.controller && panelElem.controller._update) { + panelElem.controller._update(); + debugInfo.state = panelElem.controller.state; + debugInfo.controller = panelElem.controller; + } + else if (panelElem.update) { + panelElem.update(); + debugInfo.state = panelElem.state; + } + + if (!panelElem.isStateShared && panelElem.appState) { + debugInfo.appState = panelElem.appState; + } + + if (panelElem.attrs && Object.keys(panelElem.attrs).length) { + debugInfo.attrs = panelElem.attrs; + debugInfo.attrsSchema = panelElem.constructor.attrsSchema; + } + + return debugInfo; } } // No panel component selected, remove references - window[`__$panelDevToolsLastSelectedElem`] = null; - return {error: `component state not found`}; + window[`__$panelDevToolsLastElem`] = null; + return {error: `No panel component found`}; } chrome.devtools.panels.elements.createSidebarPane(`Panel State`, function(sidebar) { diff --git a/devtools/manifest.json b/devtools/manifest.json index 1cc01ec2..16432177 100644 --- a/devtools/manifest.json +++ b/devtools/manifest.json @@ -1,8 +1,8 @@ { - "version": "1.5", + "version": "1.7", "manifest_version": 2, - "name": "Panel State", - "description": "Shows Mixpanel's Panel component state", + "name": "Panel Components", + "description": "Shows debug info and internal state for Panel components", "devtools_page": "devtools.html", "author": "dev@mixpanel.com", "icons": {