From d610405ecb5ba1a162ac1ee31162779b45d5523c Mon Sep 17 00:00:00 2001 From: Manoj Patel Date: Sat, 9 Sep 2017 07:38:24 -0700 Subject: [PATCH] Panel devtools extension (#21) * v1 of panel extension * Rename folder to devtools * Adding README.md * Update README.md * Icons and screenshots * Add a mouseenter handler to force a UI update * Clear last state * Adding publish-devtools.js script * Adding publish-devtools script * lint fixes * Adding eslint for editor to show squigglies * eslint fix devtools scripts * mixpabel config doesn't like eslint 4.5.0 * remove eslint since node 4.2 will install peer dependency * fs uses sync version rather than promisified version and some eslint comments --- .eslintrc.json | 3 ++ .gitignore | 2 ++ devtools/README.md | 9 ++++++ devtools/assets/icon128.png | Bin 0 -> 5779 bytes devtools/assets/icon16.png | Bin 0 -> 963 bytes devtools/assets/icon48.png | Bin 0 -> 2394 bytes devtools/devtools.html | 5 +++ devtools/devtools.js | 35 +++++++++++++++++++++ devtools/manifest.json | 13 ++++++++ package.json | 11 ++++++- scripts/publish-devtools.js | 59 ++++++++++++++++++++++++++++++++++++ 11 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 .eslintrc.json create mode 100644 devtools/README.md create mode 100644 devtools/assets/icon128.png create mode 100644 devtools/assets/icon16.png create mode 100644 devtools/assets/icon48.png create mode 100644 devtools/devtools.html create mode 100644 devtools/devtools.js create mode 100644 devtools/manifest.json create mode 100644 scripts/publish-devtools.js diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..51f799b7 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "mixpanel" +} diff --git a/.gitignore b/.gitignore index 3a747149..bdfc9d88 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ node_modules build test/fixtures/build.js npm-debug.log +.DS_Store +/.vscode /isorender diff --git a/devtools/README.md b/devtools/README.md new file mode 100644 index 00000000..c5fdf9b0 --- /dev/null +++ b/devtools/README.md @@ -0,0 +1,9 @@ +# Installing in devmode +* Open chrome://extensions in a chrome tab +* Make sure "developer mode" is checked +* Click on "Load unpacked extension..." and choose the 'devtools' folder in repo + +# Publishing to Chrome store + 1. Someone from mixpanel-chrome-extensions@googlegroups.com can publish this. (@iron-council members are part of thr group) + 2. Run `node run publish-devtools` + 3. Sanity check webstore dashboard at https://chrome.google.com/webstore/developer/dashboard diff --git a/devtools/assets/icon128.png b/devtools/assets/icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..c8a1767f3a0b417c7dbd42e50bf6d58ee86ac284 GIT binary patch literal 5779 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 Bga`lt literal 0 HcmV?d00001 diff --git a/devtools/assets/icon16.png b/devtools/assets/icon16.png new file mode 100644 index 0000000000000000000000000000000000000000..7692d0dfce590ca20d096b61d31267faf6efb085 GIT binary patch literal 963 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 literal 0 HcmV?d00001 diff --git a/devtools/devtools.html b/devtools/devtools.html new file mode 100644 index 00000000..bcf0413f --- /dev/null +++ b/devtools/devtools.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/devtools/devtools.js b/devtools/devtools.js new file mode 100644 index 00000000..d948fb51 --- /dev/null +++ b/devtools/devtools.js @@ -0,0 +1,35 @@ +/* global chrome */ +// The function below is executed in the context of the inspected page. +function getPanelElementState() { + if (!window[`__$panelDevToolsReady`] && 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); + window[`__$panelDevToolsReady`] = true; + } + + // $0 is not available if called via event listeners + const selectedElem = window[`$0`] || window[`__$panelDevToolsLastSelectedElem`]; + + if (selectedElem && selectedElem.update && selectedElem.state) { + window[`__$panelDevToolsLastSelectedElem`] = selectedElem; + selectedElem.update(); // Force a refresh so UI reflects latest state + return selectedElem.state; + } + + // No panel component selected, remove references + window[`__$panelDevToolsLastSelectedElem`] = null; + return {error: `component state not found`}; +} + +chrome.devtools.panels.elements.createSidebarPane(`Panel State`, function(sidebar) { + function updateTabExpression() { + // setExpression just shows result of a nested expression that is editable + // Chrome doesn't expose an API to detect when the result is changed by manual editing + // The work around is to unselect the element and re-select it so $0.update() is called + sidebar.setExpression(`(` + getPanelElementState.toString() + `)()`); + } + + chrome.devtools.panels.elements.onSelectionChanged.addListener(updateTabExpression); + updateTabExpression(); +}); diff --git a/devtools/manifest.json b/devtools/manifest.json new file mode 100644 index 00000000..1164392b --- /dev/null +++ b/devtools/manifest.json @@ -0,0 +1,13 @@ +{ + "version": "1.3", + "manifest_version": 2, + "name": "Panel State", + "description": "Shows Mixpanel's Panel component state", + "devtools_page": "devtools.html", + "author": "dev@mixpanel.com", + "icons": { + "16": "assets/icon16.png", + "48": "assets/icon48.png", + "128": "assets/icon128.png" + } +} \ No newline at end of file diff --git a/package.json b/package.json index 5bf33317..45c7ccb7 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,15 @@ "version": "0.10.0", "description": "Web Components with Virtual DOM: lightweight composable web apps", "main": "build/index.js", + "files": [ + "build" + ], "scripts": { "build": "babel lib -d build && cp -r build/isorender .", "build-test": "webpack --config test/fixtures/webpack.config.js", "docs": "rm -rf docs && jsdoc lib lib/isorender -t node_modules/minami -R README-API.md -d docs", "prepublish": "npm run build", + "publish-devtools": "node scripts/publish-devtools.js", "test": "npm run build-test && npm run test-server && npm run test-browser-local", "test-browser-local": "wct --plugin local test/browser/index.html", "test-browser-p": "wct --plugin local --persistent test/browser/index.html", @@ -47,11 +51,16 @@ "babel-polyfill": "^6.13.0", "babel-preset-es2015": "^6.6.0", "chai": "^3.5.0", + "chrome-store-api": "^1.0.5", + "eslint-config-mixpanel": "^2.4.0", "jsdoc": "^3.4.0", "minami": "^1.1.1", "mocha": "^2.5.3", + "promisify-node": "^0.4.0", + "readline-sync": "^1.4.7", "web-component-tester": "5.0.0", "webcomponents.js": "0.7.22", - "webpack": "1.13.0" + "webpack": "1.13.0", + "zip-folder": "^1.0.0" } } diff --git a/scripts/publish-devtools.js b/scripts/publish-devtools.js new file mode 100644 index 00000000..17beed32 --- /dev/null +++ b/scripts/publish-devtools.js @@ -0,0 +1,59 @@ +/** + * Usage: node scripts/publish-devtools.js + */ +/* global require, __dirname */ +/*eslint no-console: off */ +const promisify = require(`promisify-node`); +const fs = require(`fs`); +const fsPath = require(`path`); +const readlineSync = require(`readline-sync`); +const zipFolder = promisify(require(`zip-folder`)); +const WebstoreApi = require(`chrome-store-api`).Webstore; +const TokenManager = require(`chrome-store-api`).TokenManager; + +const googleOauthUrl = `https://accounts.google.com/o/oauth2`; +const redirectUri = `urn:ietf:wg:oauth:2.0:oob`; // cli app +const webstoreClientId = `839233470602-9vanoggafqre5cpcav7su73dn339ejcb.apps.googleusercontent.com`; +const webstoreClientSecret = `DQA9I0jEDJsh7ndGGjqyd70-`; +const webstoreExtensionId = `mooaaejpdfdebnddpokcdimcobepahlg`; +const devtoolsDir = fsPath.resolve(`${__dirname}/../devtools`); +const devtoolsZipPath = `${devtoolsDir}.zip`; +const manifestPath = `${devtoolsDir}/manifest.json`; + +// Main wrapped in async since top-level await is not supported +(async function() { + try{ + // Write new version to manifest + const manifest = JSON.parse(fs.readFileSync(manifestPath, `utf-8`)); + console.log(`Current manifest:\n`, manifest); + + const newVersion = readlineSync.question(`Enter new version: `); + manifest.version = newVersion; + console.log(`New manifest:\n`, manifest); + fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, ` `), `utf-8`); + + // Zip file + await zipFolder(devtoolsDir, devtoolsZipPath); + console.log(`\nBundling to a zip file`); + const zipContents = fs.readFileSync(devtoolsZipPath); + fs.unlinkSync(devtoolsZipPath); // Delete generated zip + + // Authenticate with webstore + console.log(`NOTE: Only users of mixpanel-chrome-extensions@googlegroups.com can publish this item.`); + console.log(`Paste following url in browser, authenticate and paste generate code\n`); + console.log(`${googleOauthUrl}/auth?response_type=code&scope=https://www.googleapis.com/auth/chromewebstore&client_id=${webstoreClientId}&redirect_uri=${redirectUri}`); + const oauthCode = readlineSync.question(`\ncode: `); + const api = new WebstoreApi(new TokenManager(oauthCode, webstoreClientId, webstoreClientSecret)); + + // Upload new item and publish + console.log(`\nUploading and publishing ...`); + await api.update(webstoreExtensionId, zipContents); + await api.publish(webstoreExtensionId); + console.log(`Published. Item should be available in a few minutes`); + console.log(`Check status at https://chrome.google.com/webstore/developer/dashboard`); + + } catch (err) { + console.error(err); + } +})(); +