From fca0963e5425841d502de226d324adbcf43dad46 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Mon, 17 Apr 2023 10:00:43 +0200 Subject: [PATCH 01/21] Update extension version and shortcut for mac --- CHANGES.md | 8 ++++++++ addon/manifest-template.json | 2 +- addon/manifest.json | 2 +- addon/popup.js | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bcfc878b..f564dfa8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,11 @@ +Version 1.17 +=========== + +General +------- +* Update shortcut indication for mac users + + Version 1.16 =========== diff --git a/addon/manifest-template.json b/addon/manifest-template.json index 680abe77..fea4aaae 100644 --- a/addon/manifest-template.json +++ b/addon/manifest-template.json @@ -1,7 +1,7 @@ { "name": "Salesforce Inspector reloaded", "description": "Productivity tools for Salesforce administrators and developers to inspect data and metadata directly from the Salesforce UI.", - "version": "1.16", + "version": "1.17", "icons": { "128": "icon128.png" }, diff --git a/addon/manifest.json b/addon/manifest.json index a0a22b99..1fb7c2e6 100644 --- a/addon/manifest.json +++ b/addon/manifest.json @@ -1,7 +1,7 @@ { "name": "Salesforce Inspector reloaded", "description": "Productivity tools for Salesforce administrators and developers to inspect data and metadata directly from the Salesforce UI.", - "version": "1.16", + "version": "1.17", "icons": { "128": "icon128.png" }, diff --git a/addon/popup.js b/addon/popup.js index 227cf8bd..4a792993 100644 --- a/addon/popup.js +++ b/addon/popup.js @@ -179,7 +179,7 @@ class App extends React.PureComponent { value: apiVersionInput.split(".0")[0] }), ), - h("div", { className: "tip" }, "[ctrl+alt+i] to open"), + h("div", { className: "tip" }, navigator.userAgentData.platform.indexOf("mac") > -1 ? "[ctrl+option+i]" : "[ctrl+alt+i]" + " to open"), h("a", { className: "about", href: "https://github.com/tprouvot/Chrome-Salesforce-inspector", target: linkTarget }, "About"), h("a", { className: "about", href: "https://github.com/tprouvot/Chrome-Salesforce-inspector/wiki", target: linkTarget }, "Wiki") ), From 6bc956918b71c4fa211dbec8d98304b2924bac5f Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Mon, 17 Apr 2023 11:12:18 +0200 Subject: [PATCH 02/21] Update doc --- README.md | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 1dc6dfff..46025dc6 100644 --- a/README.md +++ b/README.md @@ -6,25 +6,18 @@ Extension based on [Salesforce Inspector](https://github.com/sorenkrabbe/Chrome- Chrome and Firefox extension to add a metadata layout on top of the standard Salesforce UI to improve the productivity and joy of Salesforce configuration, development, and integration work. -New Features / Fix +Release Note ----- [List of changes](CHANGES.md) -Features +New Features ----- -* Quickly view field information directly from a record detail page, edit page or Visualforce page. -* Quickly view and edit all data for a record, even data that is not on the page layout. -* Perform quick one-off data exports and imports directly from within Salesforce. Data can be easily copied to and from Excel. No need to log in again when you are already logged in with your browser. -* View current limits consumption -* Simple access to user record details incl. simpler access to "login as". E.g. when hopping between test users. -* And more... - -Inspector menu -Show field metadata -Show all data for record -Data exporter -Data importer -Monitor limits +* Allow users to update API Version [feature 58](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/58) +* Add new "Shortcuts" tab to accelerate setup navigation [feature 42](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/42) +* Add shortcuts links to (list of record types, current SObject RecordType and objet details, show all data from user tab) from popup [feature 34](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/34) +* Control access to Salesforce Inspector reloaded with profiles / permissions (Implement Auth2 flow to generate access token for connected App) [how to](https://github.com/tprouvot/Chrome-Salesforce-inspector/wiki/How-to#use-sf-inspector-with-a-connected-app) +* Update manifest version from [v2](https://developer.chrome.com/docs/extensions/mv3/mv2-sunset/) to v3 (extensions using manifest v2 will be removed from the store) +* New UI for Export / Import Security and Privacy ----- @@ -41,11 +34,16 @@ Follow steps described in [wiki](https://github.com/tprouvot/Chrome-Salesforce-i Installation ----- -1. Download or clone the repo locally. -2. Open `chrome://extensions/`. -3. Enable `Developer mode`. -4. Click `Load unpacked extension...`. -5. Select the `addon` subdirectory of this repository. +From the Chrome Web Store : [Salesforce Inspector reloaded](https://chrome.google.com/webstore/detail/salesforce-inspector-relo/hpijlohoihegkfehhibggnkbjhoemldh) + +If you want to try it locally (to test the release candidate): + +1. Download or clone the repo. +2. Checkout the releaseCandidate branch. +3. Open `chrome://extensions/`. +4. Enable `Developer mode`. +5. Click `Load unpacked extension...`. +6. Select the `addon` subdirectory of this repository. Troubleshooting ----- From 490a6fd3a30f6e8ea5150dd331bc4529d47903ac Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Mon, 17 Apr 2023 16:47:15 +0200 Subject: [PATCH 03/21] Update links after repo renaming --- CHANGES.md | 26 +++++++++++++------------- README.md | 12 ++++++------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f564dfa8..7b50531b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,18 +11,18 @@ Version 1.16 General ------- -* Select "Update" action by default when the data paste in data-import page contains Id column [feature 60](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/60) (by Bilel Morsli) -* Allow users to update API Version [feature 58](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/58) -* Add org instance in the popup and a link to Salesforce trust status website [feature 53](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/53) (by [Camille Guillory](https://github.com/CamilleGuillory) ) -* Fix saved query when it contains ":" [issue 55](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/55) (by [Victor Garcia](https://github.com/victorgz/) ) +* Select "Update" action by default when the data paste in data-import page contains Id column [feature 60](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/60) (by Bilel Morsli) +* Allow users to update API Version [feature 58](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/58) +* Add org instance in the popup and a link to Salesforce trust status website [feature 53](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/53) (by [Camille Guillory](https://github.com/CamilleGuillory) ) +* Fix saved query when it contains ":" [issue 55](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/55) (by [Victor Garcia](https://github.com/victorgz/) ) Version 1.15 =========== General ------- -* Add "PSet" button to access user permission set assignment from User tab [feature 49](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/49) -* Add shortcut tab to access setup quick links [feature 42](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/42) +* Add "PSet" button to access user permission set assignment from User tab [feature 49](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/49) +* Add shortcut tab to access setup quick links [feature 42](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/42) Version 1.14 =========== @@ -33,13 +33,13 @@ General ![image](https://user-images.githubusercontent.com/96471586/226161542-cbedec0a-8988-4559-9152-d067ea6f9cb6.png) -* Fix links (object fields and object list) for custom metadata objects [issue 39](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/39) +* Fix links (object fields and object list) for custom metadata objects [issue 39](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/39) * Add shortcut link to object list from popup (idea by [Samuel Krissi](https://github.com/samuelkrissi) ) -* Add shortcuts links to (list of record types, current SObject RecordType and objet details, show all data from user tab) from popup [feature 34](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/34) +* Add shortcuts links to (list of record types, current SObject RecordType and objet details, show all data from user tab) from popup [feature 34](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/34) * Update manifest version from [v2](https://developer.chrome.com/docs/extensions/mv3/mv2-sunset/) to v3 -* Auto detect SObject on import page when posting data which contain SObject header [feature 30](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/30) +* Auto detect SObject on import page when posting data which contain SObject header [feature 30](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/30) * Update to Salesforce API v 57.0 (Spring '23) -* [Switch background color on import page to alert users that it's a production environnement](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/20) +* [Switch background color on import page to alert users that it's a production environnement](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/20) * Implement Auth2 flow to generate access token for connected App Version 1.13 @@ -47,7 +47,7 @@ Version 1.13 General ------- -* [Automatically remove spaces from column name in import](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/23) +* [Automatically remove spaces from column name in import](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/23) * Update to Salesforce API v 56.0 (Winter '23) * Add "Skip all unknown fields" to import page * Add User Id to pop-up @@ -55,13 +55,13 @@ General Inspector menu * Support Enhanced Domain [issue #222](https://github.com/sorenkrabbe/Chrome-Salesforce-inspector/issues/222) from [PR223](https://github.com/sorenkrabbe/Chrome-Salesforce-inspector/pull/223) -* [Add inactive users to search result](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/21) +* [Add inactive users to search result](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/21) Inspector menu * Update to Salesforce API v 55.0 (Summer '22) * Update to Salesforce API v 54.0 (Spring '22) -* [Sticked table header to the top on export](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/10) +* [Sticked table header to the top on export](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/10) * Update to Salesforce API v 53.0 (Winter '22) * Add label to saved query and sort list. * Remove extra comma when autocomplete query in data export, or select a field from suggested fields juste before 'FROM' keyword. diff --git a/README.md b/README.md index 46025dc6..c3206fa1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + Salesforce inspector reloaded =========================== @@ -12,10 +12,10 @@ Release Note New Features ----- -* Allow users to update API Version [feature 58](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/58) -* Add new "Shortcuts" tab to accelerate setup navigation [feature 42](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/42) -* Add shortcuts links to (list of record types, current SObject RecordType and objet details, show all data from user tab) from popup [feature 34](https://github.com/tprouvot/Chrome-Salesforce-inspector/issues/34) -* Control access to Salesforce Inspector reloaded with profiles / permissions (Implement Auth2 flow to generate access token for connected App) [how to](https://github.com/tprouvot/Chrome-Salesforce-inspector/wiki/How-to#use-sf-inspector-with-a-connected-app) +* Allow users to update API Version [feature 58](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/58) +* Add new "Shortcuts" tab to accelerate setup navigation [feature 42](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/42) +* Add shortcuts links to (list of record types, current SObject RecordType and objet details, show all data from user tab) from popup [feature 34](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/34) +* Control access to Salesforce Inspector reloaded with profiles / permissions (Implement Auth2 flow to generate access token for connected App) [how to](https://github.com/tprouvot/Salesforce-Inspector-reloaded/wiki/How-to#use-sf-inspector-with-a-connected-app) * Update manifest version from [v2](https://developer.chrome.com/docs/extensions/mv3/mv2-sunset/) to v3 (extensions using manifest v2 will be removed from the store) * New UI for Export / Import @@ -30,7 +30,7 @@ To validate the accuracy of this description, inspect the source code, monitor t Use Salesforce Inspector with a Connected App ----- -Follow steps described in [wiki](https://github.com/tprouvot/Chrome-Salesforce-inspector/wiki/How-to#use-sf-inspector-with-a-connected-app) +Follow steps described in [wiki](https://github.com/tprouvot/Salesforce-Inspector-reloaded/wiki/How-to#use-sf-inspector-with-a-connected-app) Installation ----- From 0de6581f6060c9b019fd9b97487f5fe90b60288b Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Mon, 17 Apr 2023 17:37:09 +0200 Subject: [PATCH 04/21] Fix NaN when divided 0 by 0 --- addon/limits.js | 75 +++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/addon/limits.js b/addon/limits.js index 2b3bcc62..c0b592fc 100644 --- a/addon/limits.js +++ b/addon/limits.js @@ -1,5 +1,5 @@ /* global React ReactDOM */ -import {sfConn, apiVersion} from "./inspector.js"; +import { sfConn, apiVersion } from "./inspector.js"; /* global initButton */ class Model { @@ -76,19 +76,19 @@ class LimitData extends React.Component { h("div", { className: "gauge" }, - h("div", { - className: "meter", - ref: "meter" - }, - "" - ), - h("div", { - className: "meter-value-container" - }, - h("div", { - className: "meter-value" - }, Math.round((1 - (this.props.remaining / this.props.max)) * 100) + "%") - ) + h("div", { + className: "meter", + ref: "meter" + }, + "" + ), + h("div", { + className: "meter-value-container" + }, + h("div", { + className: "meter-value" + }, Math.round((1 - this.divide(this.props.remaining, this.props.max)) * 100) + "%") + ) ), h("figcaption", {}, this.props.label, h("div", {}, (this.props.max - this.props.remaining).toLocaleString() + " of " + (this.props.max).toLocaleString() + " consumed", @@ -98,9 +98,12 @@ class LimitData extends React.Component { ) ); } + divide(a, b) { + return (a / b) ? (a / b) : 0; + } componentDidMount() { // Animate gauge to relevant value - let targetDegree = (this.props.max == 0) ? "180deg" : ((1 - (this.props.remaining / this.props.max)) * 180) + "deg"; //180deg = 100%, 0deg = 0% + let targetDegree = (this.props.max == 0) ? "180deg" : ((1 - this.divide(this.props.remaining, this.props.max)) * 180) + "deg"; //180deg = 100%, 0deg = 0% this.refs.meter.animate([{ transform: "rotate(0deg)" }, { @@ -121,31 +124,31 @@ class App extends React.Component { h("div", { className: "object-bar" }, - h("img", { - id: "spinner", - src: "data:image/gif;base64,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", - hidden: vm.spinnerCount == 0 - }), - h("a", { - href: vm.sfLink, - className: "sf-link" - }, - h("svg", { - viewBox: "0 0 24 24" - }, - h("path", { - d: "M18.9 12.3h-1.5v6.6c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-5.1h-3.6v5.1c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-6.6H5.1c-.1 0-.3-.1-.3-.2s0-.2.1-.3l6.9-7c.1-.1.3-.1.4 0l7 7v.3c0 .1-.2.2-.3.2z" - }) - ), - " Salesforce Home" - ) + h("img", { + id: "spinner", + src: "data:image/gif;base64,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", + hidden: vm.spinnerCount == 0 + }), + h("a", { + href: vm.sfLink, + className: "sf-link" + }, + h("svg", { + viewBox: "0 0 24 24" + }, + h("path", { + d: "M18.9 12.3h-1.5v6.6c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-5.1h-3.6v5.1c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-6.6H5.1c-.1 0-.3-.1-.3-.2s0-.2.1-.3l6.9-7c.1-.1.3-.1.4 0l7 7v.3c0 .1-.2.2-.3.2z" + }) + ), + " Salesforce Home" + ) ), h("div", { className: "body" }, - vm.allLimitData.map(limitData => - h(LimitData, limitData) - ) + vm.allLimitData.map(limitData => + h(LimitData, limitData) + ) ) ) ); From 43f32905b172365d652992c324d859940e2f5a64 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Tue, 18 Apr 2023 08:31:06 +0200 Subject: [PATCH 05/21] Doc update --- CHANGES.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7b50531b..77576e9b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,10 +11,10 @@ Version 1.16 General ------- -* Select "Update" action by default when the data paste in data-import page contains Id column [feature 60](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/60) (by Bilel Morsli) +* Select "Update" action by default when the data paste in data-import page contains Id column [feature 60](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/60) (idea by Bilel Morsli) * Allow users to update API Version [feature 58](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/58) -* Add org instance in the popup and a link to Salesforce trust status website [feature 53](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/53) (by [Camille Guillory](https://github.com/CamilleGuillory) ) -* Fix saved query when it contains ":" [issue 55](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/55) (by [Victor Garcia](https://github.com/victorgz/) ) +* Add org instance in the popup and a link to Salesforce trust status website [feature 53](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/53) (idea by [Camille Guillory](https://github.com/CamilleGuillory) ) +* Fix saved query when it contains ":" [issue 55](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/55) (bug found by [Victor Garcia](https://github.com/victorgz/) ) Version 1.15 =========== From e2fe046b99f026488ed66e80c7dfd30ed0facf74 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Tue, 18 Apr 2023 10:02:37 +0200 Subject: [PATCH 06/21] Ignore sfdx folder --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a3ece17b..8934cf55 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ npm-debug.log target/ .idea/ yarn.lock -.history/ \ No newline at end of file +.history/ +.sfdx/ \ No newline at end of file From 16a7c46b95e153e98d521725c0f04ec57776a20d Mon Sep 17 00:00:00 2001 From: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Date: Tue, 18 Apr 2023 14:53:06 +0200 Subject: [PATCH 07/21] [fix] Set the focus on suggested fields when pressing tab key in query editor (#67) #66 --- CHANGES.md | 1 + addon/data-export.js | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 77576e9b..c378c52a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ Version 1.17 General ------- +* Restore focus on suggested fields when pressing tab key in query editor ([issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) created by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) * Update shortcut indication for mac users diff --git a/addon/data-export.js b/addon/data-export.js index 171ab0da..cc2c94a9 100644 --- a/addon/data-export.js +++ b/addon/data-export.js @@ -1162,9 +1162,9 @@ class App extends React.Component { h("div", { className: "autocomplete-header" }, h("span", {}, model.autocompleteResults.title), h("div", { className: "flex-right" }, - h("button", { disabled: model.isWorking, onClick: this.onExport, title: "Ctrl+Enter / F5", className: "highlighted" }, "Run Export"), - h("a", { className: "button", hidden: !model.autocompleteResults.sobjectName, href: model.showDescribeUrl(), target: "_blank", title: "Show field info for the " + model.autocompleteResults.sobjectName + " object" }, model.autocompleteResults.sobjectName + " Field Info"), - h("button", { href: "#", className: model.expandAutocomplete ? "toggle contract" : "toggle expand", onClick: this.onToggleExpand, title: "Show all suggestions or only the first line" }, + h("button", { tabIndex: 1, disabled: model.isWorking, onClick: this.onExport, title: "Ctrl+Enter / F5", className: "highlighted" }, "Run Export"), + h("a", { tabIndex: 2, className: "button", hidden: !model.autocompleteResults.sobjectName, href: model.showDescribeUrl(), target: "_blank", title: "Show field info for the " + model.autocompleteResults.sobjectName + " object" }, model.autocompleteResults.sobjectName + " Field Info"), + h("button", { tabIndex: 3, href: "#", className: model.expandAutocomplete ? "toggle contract" : "toggle expand", onClick: this.onToggleExpand, title: "Show all suggestions or only the first line" }, h("div", { className: "button-icon" }), h("div", { className: "button-toggle-icon" }) ) @@ -1172,7 +1172,7 @@ class App extends React.Component { ), h("div", { className: "autocomplete-results" }, model.autocompleteResults.results.map(r => - h("div", { className: "autocomplete-result", key: r.value }, h("a", { title: r.title, onClick: e => { e.preventDefault(); model.autocompleteClick(r); model.didUpdate(); }, href: "#", className: r.autocompleteType + ' ' + r.dataType }, h("div", { className: "autocomplete-icon" }), r.value), " ") + h("div", { className: "autocomplete-result", key: r.value }, h("a", { tabIndex: 0, title: r.title, onClick: e => { e.preventDefault(); model.autocompleteClick(r); model.didUpdate(); }, href: "#", className: r.autocompleteType + ' ' + r.dataType }, h("div", { className: "autocomplete-icon" }), r.value), " ") ) ), ), From 5034cf6401d1c918cef07027e7915d3486902abc Mon Sep 17 00:00:00 2001 From: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Date: Fri, 21 Apr 2023 16:34:35 +0200 Subject: [PATCH 08/21] [fix] Typo data export (#72) Fix #71 --- .gitignore | 3 ++- addon/data-export.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8934cf55..a0898479 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ target/ .idea/ yarn.lock .history/ -.sfdx/ \ No newline at end of file +.sfdx/ +venv/ \ No newline at end of file diff --git a/addon/data-export.js b/addon/data-export.js index cc2c94a9..63534815 100644 --- a/addon/data-export.js +++ b/addon/data-export.js @@ -1129,7 +1129,7 @@ class App extends React.Component { h("button", { onClick: this.onClearHistory, title: "Clear Query History" }, "Clear") ), h("div", { className: "pop-menu saveOptions", hidden: !model.expandSavedOptions }, - h("a", { href: "#", onClick: this.onRemoveFromHistory, title: "Remove query from saved history" }, "Removed Saved Query"), + h("a", { href: "#", onClick: this.onRemoveFromHistory, title: "Remove query from saved history" }, "Remove Saved Query"), h("a", { href: "#", onClick: this.onClearSavedHistory, title: "Clear saved history" }, "Clear Saved Queries") ), h("div", { className: "button-group" }, From c2a3849212716501a8547cdb4e553f0e71024db3 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Date: Mon, 24 Apr 2023 08:28:10 +0200 Subject: [PATCH 09/21] [fix] Import action auto update (#74) Fix #73 --- CHANGES.md | 1 + addon/data-import.js | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index c378c52a..5c629838 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ Version 1.17 General ------- +* Fix auto update action on data import ([issue 73](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/73) ) * Restore focus on suggested fields when pressing tab key in query editor ([issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) created by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) * Update shortcut indication for mac users diff --git a/addon/data-import.js b/addon/data-import.js index 68af2877..cc90e8df 100644 --- a/addon/data-import.js +++ b/addon/data-import.js @@ -18,6 +18,7 @@ class Model { this.dataError = ""; this.useToolingApi = false; this.dataFormat = "excel"; + this.importActionSelected = false; this.importAction = "create"; this.importActionName = "Insert"; this.importType = "Account"; @@ -132,7 +133,7 @@ class Model { this.importType = sobj; } //automatically select update if header contains id - if (this.hasIdColumn(header)) { + if (this.hasIdColumn(header) && !this.importActionSelected) { this.importAction = "update"; } } @@ -723,6 +724,7 @@ class App extends React.Component { let { model } = this.props; model.importAction = e.target.value; model.importActionName = e.target.options[e.target.selectedIndex].text; + model.importActionSelected = true; model.didUpdate(); } onImportTypeChange(e) { From 2bc4d8926ec9b41423e0b922b11da6549685196a Mon Sep 17 00:00:00 2001 From: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Date: Tue, 25 Apr 2023 09:42:50 +0200 Subject: [PATCH 10/21] [data-import] Import as json (#79) Fix #75 --- CHANGES.md | 1 + addon/data-import.js | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5c629838..7061118d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ Version 1.17 General ------- +* Import data as JSON ([feature 75](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/75) ) * Fix auto update action on data import ([issue 73](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/73) ) * Restore focus on suggested fields when pressing tab key in query editor ([issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) created by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) * Update shortcut indication for mac users diff --git a/addon/data-import.js b/addon/data-import.js index cc90e8df..82805e9f 100644 --- a/addon/data-import.js +++ b/addon/data-import.js @@ -86,13 +86,16 @@ class Model { } message() { - return this.dataFormat == "excel" ? "Paste Excel data here" : "Paste CSV data here"; + return "Paste " + this.dataFormat.toUpperCase() + " data here"; } setData(text) { if (this.isWorking()) { return; } + if (this.dataFormat == "json") { + text = this.getDataFromJson(text); + } let separator = this.dataFormat == "excel" ? "\t" : ","; let data; try { @@ -135,7 +138,31 @@ class Model { //automatically select update if header contains id if (this.hasIdColumn(header) && !this.importActionSelected) { this.importAction = "update"; + this.importActionName = "Update"; + } + } + + getDataFromJson(json) { + json = JSON.parse(json); + let csv; + let fields = ["_"].concat(Object.keys(json[0])); + fields = fields.filter(field => field != "attributes"); + + let sobject = json[0]["attributes"]["type"]; + if (sobject) { + csv = json.map(function (row) { + return fields.map(function (fieldName) { + let value = row[fieldName]; + if (value && typeof value === "string") { + return fieldName == "_" ? '"[' + sobject + ']"' : JSON.stringify(value) + } + }).join(",") + }) + fields = fields.map(str => '"' + str + '"'); + csv.unshift(fields.join(",")); + csv = csv.join("\r\n"); } + return csv; } copyOptions() { @@ -915,7 +942,9 @@ class App extends React.Component { h("span", { className: "conf-label" }, "Format"), h("label", {}, h("input", { type: "radio", name: "data-input-format", value: "excel", checked: model.dataFormat == "excel", onChange: this.onDataFormatChange, disabled: model.isWorking() }), " ", h("span", {}, "Excel")), " ", - h("label", {}, h("input", { type: "radio", name: "data-input-format", value: "csv", checked: model.dataFormat == "csv", onChange: this.onDataFormatChange, disabled: model.isWorking() }), " ", h("span", {}, "CSV")) + h("label", {}, h("input", { type: "radio", name: "data-input-format", value: "csv", checked: model.dataFormat == "csv", onChange: this.onDataFormatChange, disabled: model.isWorking() }), " ", h("span", {}, "CSV")), + " ", + h("label", {}, h("input", { type: "radio", name: "data-input-format", value: "json", checked: model.dataFormat == "json", onChange: this.onDataFormatChange, disabled: model.isWorking() }), " ", h("span", {}, "JSON")) ), h("div", { className: "conf-line" }, h("label", { className: "conf-input" }, From 126c98434ed0b5a6868e409b4ae0ba827ece249d Mon Sep 17 00:00:00 2001 From: MD931 Date: Thu, 27 Apr 2023 13:42:12 +0200 Subject: [PATCH 11/21] fix links for custom object (#80) Fix "Fields" and "RecordTypes" links in Object tab from popup. The links did not allow users to continue navigation, for example create a field --------- Signed-off-by: dependabot[bot] Co-authored-by: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Thomas Prouvot --- .github/workflows/ci.yml | 22 +++++++ CHANGES.md | 2 +- addon/popup.js | 14 +++- docs/assets/images/icon128.png | Bin 0 -> 11016 bytes docs/index.md | 114 +++++++++++++++++++++++++++++++++ docs/release-note.md | 57 +++++++++++++++++ mkdocs.yml | 56 ++++++++++++++++ package-lock.json | 104 ++++++++++++++++++++++++++---- package.json | 2 +- 9 files changed, 353 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 docs/assets/images/icon128.png create mode 100644 docs/index.md create mode 100644 docs/release-note.md create mode 100644 mkdocs.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..42e02406 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +name: ci +on: + push: + branches: + - master + - main +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - uses: actions/cache@v2 + with: + key: ${{ github.ref }} + path: .cache + - run: pip install mkdocs-material + - run: mkdocs gh-deploy --force \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index 7061118d..eab2fa0d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,7 +7,7 @@ General * Fix auto update action on data import ([issue 73](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/73) ) * Restore focus on suggested fields when pressing tab key in query editor ([issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) created by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) * Update shortcut indication for mac users - +* Fix links for custom object [PR80](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/80) (by [Mouloud Habchi](https://github.com/MD931) ) Version 1.16 =========== diff --git a/addon/popup.js b/addon/popup.js index 4a792993..1b8301e5 100644 --- a/addon/popup.js +++ b/addon/popup.js @@ -989,6 +989,8 @@ class AllDataSelection extends React.PureComponent { getObjectSetupLink(sobjectName, durableId) { if (sobjectName.endsWith("__mdt")) { return this.getCustomMetadataLink(durableId); + } else if (sobjectName.endsWith("__c")) { + return "https://" + this.props.sfHost + "/lightning/setup/ObjectManager/" + durableId + "/Details/view"; } else { return "https://" + this.props.sfHost + "/lightning/setup/ObjectManager/" + sobjectName + "/Details/view"; } @@ -999,6 +1001,8 @@ class AllDataSelection extends React.PureComponent { getObjectFieldsSetupLink(sobjectName, durableId) { if (sobjectName.endsWith("__mdt")) { return this.getCustomMetadataLink(durableId); + } else if (sobjectName.endsWith("__c")) { + return "https://" + this.props.sfHost + "/lightning/setup/ObjectManager/" + durableId + "/FieldsAndRelationships/view"; } else { return "https://" + this.props.sfHost + "/lightning/setup/ObjectManager/" + sobjectName + "/FieldsAndRelationships/view"; } @@ -1010,8 +1014,12 @@ class AllDataSelection extends React.PureComponent { return "https://" + this.props.sfHost + "/lightning/o/" + sobjectName + "/list"; } } - getRecordTypesLink(sfHost, sobjectName) { - return "https://" + sfHost + "/lightning/setup/ObjectManager/" + sobjectName + "/RecordTypes/view"; + getRecordTypesLink(sfHost, sobjectName, durableId) { + if (sobjectName.endsWith("__c")) { + return "https://" + sfHost + "/lightning/setup/ObjectManager/" + durableId + "/RecordTypes/view"; + } else { + return "https://" + sfHost + "/lightning/setup/ObjectManager/" + sobjectName + "/RecordTypes/view"; + } } render() { let { sfHost, showDetailsSupported, contextRecordId, selectedValue, linkTarget, recordIdDetails } = this.props; @@ -1037,7 +1045,7 @@ class AllDataSelection extends React.PureComponent { h("th", {}, "Links:"), h("td", {}, h("a", { href: this.getObjectFieldsSetupLink(selectedValue.sobject.name, selectedValue.sobject.durableId), target: linkTarget }, "Fields / "), - h("a", { href: this.getRecordTypesLink(sfHost, selectedValue.sobject.name), target: linkTarget }, "Record Types / "), + h("a", { href: this.getRecordTypesLink(sfHost, selectedValue.sobject.name, selectedValue.sobject.durableId), target: linkTarget }, "Record Types / "), h("a", { href: this.getObjectListLink(selectedValue.sobject.name, selectedValue.sobject.keyPrefix), target: linkTarget }, "Object List") ), ), diff --git a/docs/assets/images/icon128.png b/docs/assets/images/icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..01e07a01ab9e87cfcd0230e953dc6b885b9c1e3b GIT binary patch literal 11016 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 + +* Support Enhanced Domain [issue #222](https://github.com/sorenkrabbe/Chrome-Salesforce-inspector/issues/222) from [PR223](https://github.com/sorenkrabbe/Chrome-Salesforce-inspector/pull/223) +* [Add inactive users to search result](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/21) + +Inspector menu + +* Update to Salesforce API v 55.0 (Summer '22) +* Update to Salesforce API v 54.0 (Spring '22) +* [Sticked table header to the top on export](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/10) +* Update to Salesforce API v 53.0 (Winter '22) +* Add label to saved query and sort list. +* Remove extra comma when autocomplete query in data export, or select a field from suggested fields just before 'FROM' keyword. + +Inspector menu + +* Add "Copy Id" option when clicking on a SObject field or Id in data export page. + +Inspector menu + +* Integrate UI updates from [Garywoo's fork](https://github.com/Garywoo/Chrome-Salesforce-inspector) \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..07a11034 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,56 @@ +site_name: Salesforce Inspector reloaded +theme: + name: material + logo: ./assets/images/icon128.png + favicon: ./assets/images/icon128.png + features: + - navigation.tabs + - navigation.sections + - toc.integrate + - navigation.top + - search.suggest + - search.highlight + - content.tabs.link + - content.code.annotation + - content.code.copy + language: en + palette: + - scheme: default + toggle: + icon: material/toggle-switch-off-outline + name: Switch to dark mode + primary: blue + accent: indigo + - scheme: slate + toggle: + icon: material/toggle-switch + name: Switch to light mode + primary: blue + accent: indigo + +extra: + social: + - icon: fontawesome/brands/github-alt + link: https://github.com/tprouvot + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/in/thomasprouvot/ + +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - admonition + - pymdownx.arithmatex: + generic: true + - footnotes + - pymdownx.details + - pymdownx.superfences + - pymdownx.mark + - attr_list + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + +copyright: | + © 2023 Thomas Prouvot diff --git a/package-lock.json b/package-lock.json index 457a399b..ed3bff49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "eslint": "^6.3.0", "fs-extra": "2.0.0", "replace-in-file": "2.2.2", - "zip-dir": "1.0.2" + "zip-dir": "2.0.0" } }, "node_modules/@babel/code-frame": { @@ -151,9 +151,9 @@ } }, "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, "node_modules/balanced-match": { @@ -243,6 +243,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, "node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -677,6 +683,12 @@ "node": ">= 4" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -863,6 +875,12 @@ "node": ">=0.10.0" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -910,12 +928,15 @@ } }, "node_modules/jszip": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.7.0.tgz", - "integrity": "sha512-JIsRKRVC3gTRo2vM4Wy9WBC3TRcfnIZU8k65Phi3izkvPH975FowRYtKGT6PxevA0XnJ/yO8b0QwV0ydVyQwfw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "dev": true, "dependencies": { - "pako": "~1.0.2" + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" } }, "node_modules/levn": { @@ -931,6 +952,15 @@ "node": ">= 0.8.0" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -1098,6 +1128,12 @@ "node": ">= 0.8.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -1116,6 +1152,21 @@ "node": ">=6" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -1189,6 +1240,12 @@ "npm": ">=2.0.0" } }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -1204,6 +1261,12 @@ "semver": "bin/semver.js" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, "node_modules/shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -1260,6 +1323,15 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -1435,6 +1507,12 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -1481,13 +1559,13 @@ } }, "node_modules/zip-dir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/zip-dir/-/zip-dir-1.0.2.tgz", - "integrity": "sha512-OZ4WThDcFqvamrq4e2lSdz+q6a9fnD55ktBzsfQ95R0YrnZDd7Cz1gTI8OMveqlASz8PXVN0av8Bi7Ky+uJ+SA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/zip-dir/-/zip-dir-2.0.0.tgz", + "integrity": "sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==", "dev": true, "dependencies": { - "async": "^1.5.2", - "jszip": "^2.4.0" + "async": "^3.2.0", + "jszip": "^3.2.2" } } } diff --git a/package.json b/package.json index a0325247..2d1374d3 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,6 @@ "eslint": "^6.3.0", "fs-extra": "2.0.0", "replace-in-file": "2.2.2", - "zip-dir": "1.0.2" + "zip-dir": "2.0.0" } } From cd920c1b8d0fb65345e66205ccee15e1a8a8ebfb Mon Sep 17 00:00:00 2001 From: MD931 Date: Tue, 2 May 2023 14:43:50 +0200 Subject: [PATCH 12/21] [fix] link custom setting (#82) This PR fixes the redirection links for custom settings to redirect to the custom setting setup page instead object manager page. --------- Signed-off-by: dependabot[bot] Co-authored-by: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Thomas Prouvot --- CHANGES.md | 1 + addon/popup.js | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index eab2fa0d..299e87d9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ General * Restore focus on suggested fields when pressing tab key in query editor ([issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) created by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) * Update shortcut indication for mac users * Fix links for custom object [PR80](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/80) (by [Mouloud Habchi](https://github.com/MD931) ) +* Fix links for custom setting [PR82](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/82) (by [Mouloud Habchi](https://github.com/MD931) ) Version 1.16 =========== diff --git a/addon/popup.js b/addon/popup.js index 1b8301e5..958c2646 100644 --- a/addon/popup.js +++ b/addon/popup.js @@ -282,7 +282,7 @@ class AllDataBox extends React.PureComponent { loadSobjects() { let entityMap = new Map(); - function addEntity({ name, label, keyPrefix, durableId }, api) { + function addEntity({ name, label, keyPrefix, durableId, isCustomSetting }, api) { label = label || ""; // Avoid null exceptions if the object does not have a label (some don't). All objects have a name. Not needed for keyPrefix since we only do equality comparisons on those. let entity = entityMap.get(name); if (entity) { @@ -299,6 +299,7 @@ class AllDataBox extends React.PureComponent { label, keyPrefix, durableId, + isCustomSetting, availableKeyPrefix: null, }; entityMap.set(name, entity); @@ -322,14 +323,15 @@ class AllDataBox extends React.PureComponent { } function getEntityDefinitions(bucket) { - let query = "select QualifiedApiName, Label, KeyPrefix, DurableId from EntityDefinition" + bucket; + let query = "select QualifiedApiName, Label, KeyPrefix, DurableId, IsCustomSetting from EntityDefinition" + bucket; return sfConn.rest("/services/data/v" + apiVersion + "/tooling/query?q=" + encodeURIComponent(query)).then(res => { for (let record of res.records) { addEntity({ name: record.QualifiedApiName, label: record.Label, keyPrefix: record.KeyPrefix, - durableId: record.DurableId + durableId: record.DurableId, + isCustomSetting: record.IsCustomSetting }, null); } }).catch(err => { @@ -986,9 +988,11 @@ class AllDataSelection extends React.PureComponent { /** * Optimistically generate lightning setup uri for the provided object api name. */ - getObjectSetupLink(sobjectName, durableId) { + getObjectSetupLink(sobjectName, durableId, isCustomSetting) { if (sobjectName.endsWith("__mdt")) { return this.getCustomMetadataLink(durableId); + } else if (isCustomSetting) { + return "https://" + this.props.sfHost + "/lightning/setup/CustomSettings/page?address=%2F" + durableId + "?setupid=CustomSettings"; } else if (sobjectName.endsWith("__c")) { return "https://" + this.props.sfHost + "/lightning/setup/ObjectManager/" + durableId + "/Details/view"; } else { @@ -998,18 +1002,24 @@ class AllDataSelection extends React.PureComponent { getCustomMetadataLink(durableId) { return "https://" + this.props.sfHost + "/lightning/setup/CustomMetadata/page?address=%2F" + durableId + "%3Fsetupid%3DCustomMetadata"; } - getObjectFieldsSetupLink(sobjectName, durableId) { + getObjectFieldsSetupLink(sobjectName, durableId, isCustomSetting) { if (sobjectName.endsWith("__mdt")) { return this.getCustomMetadataLink(durableId); + } else if (isCustomSetting) { + return "https://" + this.props.sfHost + "/lightning/setup/CustomSettings/page?address=%2F" + durableId + "?setupid=CustomSettings"; + } else if (sobjectName.endsWith("__c")) { return "https://" + this.props.sfHost + "/lightning/setup/ObjectManager/" + durableId + "/FieldsAndRelationships/view"; } else { return "https://" + this.props.sfHost + "/lightning/setup/ObjectManager/" + sobjectName + "/FieldsAndRelationships/view"; } } - getObjectListLink(sobjectName, keyPrefix) { + getObjectListLink(sobjectName, keyPrefix, isCustomSetting) { if (sobjectName.endsWith("__mdt")) { return "https://" + this.props.sfHost + "/lightning/setup/CustomMetadata/page?address=%2F" + keyPrefix; + } else if (isCustomSetting) { + return "https://" + this.props.sfHost + "/lightning/setup/CustomSettings/page?address=%2Fsetup%2Fui%2FlistCustomSettingsData.apexp?id=" + keyPrefix; + } else { return "https://" + this.props.sfHost + "/lightning/o/" + sobjectName + "/list"; } @@ -1038,15 +1048,15 @@ class AllDataSelection extends React.PureComponent { h("tr", {}, h("th", {}, "Name:"), h("td", {}, - h("a", { href: this.getObjectSetupLink(selectedValue.sobject.name, selectedValue.sobject.durableId), target: linkTarget }, selectedValue.sobject.name) + h("a", { href: this.getObjectSetupLink(selectedValue.sobject.name, selectedValue.sobject.durableId, selectedValue.sobject.isCustomSetting), target: linkTarget }, selectedValue.sobject.name) ) ), h("tr", {}, h("th", {}, "Links:"), h("td", {}, - h("a", { href: this.getObjectFieldsSetupLink(selectedValue.sobject.name, selectedValue.sobject.durableId), target: linkTarget }, "Fields / "), + h("a", { href: this.getObjectFieldsSetupLink(selectedValue.sobject.name, selectedValue.sobject.durableId, selectedValue.sobject.isCustomSetting), target: linkTarget }, "Fields / "), h("a", { href: this.getRecordTypesLink(sfHost, selectedValue.sobject.name, selectedValue.sobject.durableId), target: linkTarget }, "Record Types / "), - h("a", { href: this.getObjectListLink(selectedValue.sobject.name, selectedValue.sobject.keyPrefix), target: linkTarget }, "Object List") + h("a", { href: this.getObjectListLink(selectedValue.sobject.name, selectedValue.sobject.keyPrefix, selectedValue.sobject.isCustomSetting), target: linkTarget }, "Object List") ), ), h("tr", {}, From 57893b0ec9f54c086853c0e161cba4a3acc49208 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Date: Fri, 5 May 2023 15:12:43 +0200 Subject: [PATCH 13/21] [feat] General : add option to open links in new tab (#84) Fix #78 --- CHANGES.md | 1 + addon/popup.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 299e87d9..84bab2d8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ Version 1.17 General ------- +* Add a configuration option for links to open in a new tab ([feature 78](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/75) ) * Import data as JSON ([feature 75](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/75) ) * Fix auto update action on data import ([issue 73](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/73) ) * Restore focus on suggested fields when pressing tab key in query editor ([issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) created by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) diff --git a/addon/popup.js b/addon/popup.js index 958c2646..22b4e12f 100644 --- a/addon/popup.js +++ b/addon/popup.js @@ -131,7 +131,8 @@ class App extends React.PureComponent { let orgInstance = this.getOrgInstance(sfHost); let hostArg = new URLSearchParams(); hostArg.set("host", sfHost); - let linkTarget = inDevConsole ? "_blank" : "_top"; + let linkInNewTab = localStorage.getItem("openLinksInNewTab"); + let linkTarget = inDevConsole || linkInNewTab ? "_blank" : "_top"; return ( h("div", {}, h("div", { className: "header" }, From 34aea41bcee7ffd1c4525abdfc54b96f26a7bb47 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Fri, 5 May 2023 15:20:15 +0200 Subject: [PATCH 14/21] Fix feature 78 link --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 84bab2d8..86fa3a39 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,7 +3,7 @@ Version 1.17 General ------- -* Add a configuration option for links to open in a new tab ([feature 78](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/75) ) +* Add a configuration option for links to open in a new tab ([feature 78](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/78) ) * Import data as JSON ([feature 75](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/75) ) * Fix auto update action on data import ([issue 73](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/73) ) * Restore focus on suggested fields when pressing tab key in query editor ([issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) created by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) From 11061ff6812b8ae52e3197e6133d71b846b17ed2 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Date: Fri, 5 May 2023 16:33:53 +0200 Subject: [PATCH 15/21] [feat] Inspect : Show copy id from inspect view (#85) Fix #12 --- CHANGES.md | 1 + addon/inspect.js | 414 ++++++++++++++++++++++++----------------------- 2 files changed, 212 insertions(+), 203 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 86fa3a39..4fe5df13 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ Version 1.17 General ------- +* Show "Copy Id" from Inspect page ([feature 12](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/12) ) * Add a configuration option for links to open in a new tab ([feature 78](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/78) ) * Import data as JSON ([feature 75](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/75) ) * Fix auto update action on data import ([issue 73](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/73) ) diff --git a/addon/inspect.js b/addon/inspect.js index 6ca0508d..b632bd04 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -1,7 +1,7 @@ /* global React ReactDOM */ -import {sfConn, apiVersion} from "./inspector.js"; +import { sfConn, apiVersion } from "./inspector.js"; /* global initButton */ -import {getObjectSetupLinks, getFieldSetupLinks} from "./setup-links.js"; +import { getObjectSetupLinks, getFieldSetupLinks } from "./setup-links.js"; class Model { constructor(sfHost) { @@ -105,13 +105,13 @@ class Model { } }); } - this.detailsBox = {rows: fieldDetails, name, detailsFilterList}; + this.detailsBox = { rows: fieldDetails, name, detailsFilterList }; } showObjectMetadata() { let objectDescribe = this.objectData; let props = {}; - addProperties(props, objectDescribe, "desc.", {fields: true, childRelationships: true}); - addProperties(props, this.layoutInfo, "layout.", {detailLayoutSections: true, editLayoutSections: true, relatedLists: true}); + addProperties(props, objectDescribe, "desc.", { fields: true, childRelationships: true }); + addProperties(props, this.layoutInfo, "layout.", { detailLayoutSections: true, editLayoutSections: true, relatedLists: true }); this.showDetailsBox(this.objectName(), props, null); } canUpdate() { @@ -142,7 +142,7 @@ class Model { let recordUrl = this.objectData.urls.rowTemplate.replace("{ID}", this.recordData.Id); this.spinFor( "saving record", - sfConn.rest(recordUrl, {method: "PATCH", body: record}).then(() => { + sfConn.rest(recordUrl, { method: "PATCH", body: record }).then(() => { this.endEdit(); this.clearRecordData(); this.setRecordData(sfConn.rest(recordUrl)); @@ -152,7 +152,7 @@ class Model { let recordUrl = this.objectData.urls.rowTemplate.replace("{ID}", this.recordData.Id); this.spinFor( "deleting record", - sfConn.rest(recordUrl, {method: "DELETE"}).then(() => { + sfConn.rest(recordUrl, { method: "DELETE" }).then(() => { this.endEdit(); let args = new URLSearchParams(); args.set("host", this.sfHost); @@ -169,7 +169,7 @@ class Model { let recordUrl = this.objectData.urls.sobject; this.spinFor( "creating record", - sfConn.rest(recordUrl, {method: "POST", body: record}).then(result => { + sfConn.rest(recordUrl, { method: "POST", body: record }).then(result => { this.endEdit(); let args = new URLSearchParams(); args.set("host", this.sfHost); @@ -275,7 +275,7 @@ class Model { return undefined; }).then(layoutDescribe => { if (layoutDescribe) { - for (let layoutType of [{sections: "detailLayoutSections", property: "detailLayoutInfo"}, {sections: "editLayoutSections", property: "editLayoutInfo"}]) { + for (let layoutType of [{ sections: "detailLayoutSections", property: "detailLayoutInfo" }, { sections: "editLayoutSections", property: "editLayoutInfo" }]) { layoutDescribe[layoutType.sections].forEach((section, sectionIndex) => { section.layoutRows.forEach((row, rowIndex) => { row.layoutItems.forEach((item, itemIndex) => { @@ -407,8 +407,8 @@ class RowList { resortRows() { let s = v => v === undefined ? "\uFFFD" - : v == null ? "" - : String(v).trim(); + : v == null ? "" + : String(v).trim(); this.rows.sort((a, b) => this._sortDir * s(a.sortKey(this._sortCol)).localeCompare(s(b.sortKey(this._sortCol)))); } initColumns(cols) { @@ -462,20 +462,20 @@ class FieldRowList extends RowList { name: col, label: col == "name" ? "Field API Name" - : col == "label" ? "Label" - : col == "type" ? "Type" - : col == "value" ? "Value" - : col == "helptext" ? "Help text" - : col == "desc" ? "Description" - : col, + : col == "label" ? "Label" + : col == "type" ? "Type" + : col == "value" ? "Value" + : col == "helptext" ? "Help text" + : col == "desc" ? "Description" + : col, className: col == "name" ? "field-name" - : col == "label" ? "field-label" - : "field-column", + : col == "label" ? "field-label" + : "field-column", reactElement: col == "value" ? FieldValueCell - : col == "type" ? FieldTypeCell - : DefaultCell, + : col == "type" ? FieldTypeCell + : DefaultCell, columnFilter: "" }; } @@ -507,10 +507,10 @@ class ChildRowList extends RowList { name: col, label: col == "name" ? "Relationship Name" - : col == "object" ? "Child Object" - : col == "field" ? "Field" - : col == "label" ? "Label" - : col, + : col == "object" ? "Child Object" + : col == "field" ? "Field" + : col == "label" ? "Label" + : col, className: "child-column", reactElement: col == "object" ? ChildObjectCell : DefaultCell, columnFilter: "" @@ -559,7 +559,7 @@ class FieldRow extends TableRow { rowProperties() { let props = {}; if (typeof this.dataTypedValue != "undefined") { - addProperties(props, {dataValue: this.dataTypedValue}, "", {}); + addProperties(props, { dataValue: this.dataTypedValue }, "", {}); } if (this.fieldDescribe) { addProperties(props, this.fieldDescribe, "desc.", {}); @@ -572,21 +572,21 @@ class FieldRow extends TableRow { } if (this.detailLayoutInfo) { addProperties(props, this.detailLayoutInfo.indexes, "layout.", {}); - addProperties(props, this.detailLayoutInfo.section, "layoutSection.", {layoutRows: true}); - addProperties(props, this.detailLayoutInfo.row, "layoutRow.", {layoutItems: true}); - addProperties(props, this.detailLayoutInfo.item, "layoutItem.", {layoutComponents: true}); - addProperties(props, this.detailLayoutInfo.component, "layoutComponent.", {details: true, components: true}); + addProperties(props, this.detailLayoutInfo.section, "layoutSection.", { layoutRows: true }); + addProperties(props, this.detailLayoutInfo.row, "layoutRow.", { layoutItems: true }); + addProperties(props, this.detailLayoutInfo.item, "layoutItem.", { layoutComponents: true }); + addProperties(props, this.detailLayoutInfo.component, "layoutComponent.", { details: true, components: true }); } else if (this.rowList.model.layoutInfo) { - addProperties(props, {shownOnLayout: false}, "layout.", {}); + addProperties(props, { shownOnLayout: false }, "layout.", {}); } if (this.editLayoutInfo) { addProperties(props, this.editLayoutInfo.indexes, "editLayout.", {}); - addProperties(props, this.editLayoutInfo.section, "editLayoutSection.", {layoutRows: true}); - addProperties(props, this.editLayoutInfo.row, "editLayoutRow.", {layoutItems: true}); - addProperties(props, this.editLayoutInfo.item, "editLayoutItem.", {layoutComponents: true}); - addProperties(props, this.editLayoutInfo.component, "editLayoutComponent.", {details: true, components: true}); + addProperties(props, this.editLayoutInfo.section, "editLayoutSection.", { layoutRows: true }); + addProperties(props, this.editLayoutInfo.row, "editLayoutRow.", { layoutItems: true }); + addProperties(props, this.editLayoutInfo.item, "editLayoutItem.", { layoutComponents: true }); + addProperties(props, this.editLayoutInfo.component, "editLayoutComponent.", { details: true, components: true }); } else if (this.rowList.model.layoutInfo) { - addProperties(props, {shownOnLayout: false}, "editLayout.", {}); + addProperties(props, { shownOnLayout: false }, "editLayout.", {}); } return props; } @@ -696,7 +696,7 @@ class FieldRow extends TableRow { + (fieldDescribe.calculatedFormula ? "Formula: " + fieldDescribe.calculatedFormula + "\n" : "") + (fieldDescribe.inlineHelpText ? "Help text: " + fieldDescribe.inlineHelpText + "\n" : "") + (fieldDescribe.picklistValues && fieldDescribe.picklistValues.length > 0 ? "Picklist values: " + fieldDescribe.picklistValues.map(pickval => pickval.value).join(", ") + "\n" : "") - ; + ; } // Entity particle does not contain any of this information return this.fieldName + "\n(Details not available)"; @@ -767,12 +767,13 @@ class FieldRow extends TableRow { args.set("useToolingApi", "1"); } args.set("recordId", recordId); - return {href: "inspect.html?" + args, text: "Show all data (" + sobject.name + ")"}; + return { href: "inspect.html?" + args, text: "Show all data (" + sobject.name + ")" }; }); } else { links = []; } - links.push({href: this.idLink(), text: "View in Salesforce"}); + links.push({ href: this.idLink(), text: "View in Salesforce" }); + links.push({ href: "#", text: "Copy Id", className: "copy-id", id: this.dataTypedValue }); this.recordIdPop = links; } showReferenceUrl(type) { @@ -828,7 +829,7 @@ class ChildRow extends TableRow { if (this.relatedListInfo) { addProperties(props, this.relatedListInfo, "layout.", {}); } else if (this.rowList.model.layoutInfo) { - addProperties(props, {shownOnLayout: false}, "layout.", {}); + addProperties(props, { shownOnLayout: false }, "layout.", {}); } return props; } @@ -949,133 +950,133 @@ class App extends React.Component { this.refs.rowsFilter.focus(); } onUseAllTab(e) { - let {model} = this.props; + let { model } = this.props; e.preventDefault(); model.useTab = "all"; model.didUpdate(); } onUseFieldsTab(e) { - let {model} = this.props; + let { model } = this.props; e.preventDefault(); model.useTab = "fields"; model.didUpdate(); } onUseChildsTab(e) { - let {model} = this.props; + let { model } = this.props; e.preventDefault(); model.useTab = "childs"; model.didUpdate(); } onRowsFilterInput(e) { - let {model} = this.props; + let { model } = this.props; model.rowsFilter = e.target.value; model.didUpdate(); } onClearAndFocusFilter(e) { e.preventDefault(); - let {model} = this.props; + let { model } = this.props; model.rowsFilter = ""; this.refs.rowsFilter.focus(); model.didUpdate(); } onShowObjectMetadata(e) { e.preventDefault(); - let {model} = this.props; + let { model } = this.props; model.showObjectMetadata(); model.didUpdate(); } onToggleObjectActions() { - let {model} = this.props; + let { model } = this.props; model.toggleObjectActions(); model.didUpdate(); } onDoUpdate() { - let {model} = this.props; + let { model } = this.props; model.doUpdate(); model.didUpdate(); } onDoDelete() { - let {model} = this.props; + let { model } = this.props; model.doDelete(); model.didUpdate(); } onDoCreate() { - let {model} = this.props; + let { model } = this.props; model.doCreate(); model.didUpdate(); } onDoSave() { - let {model} = this.props; + let { model } = this.props; model.doSave(); model.didUpdate(); } onCancelEdit() { - let {model} = this.props; + let { model } = this.props; model.cancelEdit(); model.didUpdate(); } render() { - let {model} = this.props; + let { model } = this.props; document.title = model.title(); return ( h("div", {}, - h("div", {className: "object-bar"}, - h("img", {id: "spinner", src: "data:image/gif;base64,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", hidden: model.spinnerCount == 0}), - h("a", {href: model.sfLink, className: "sf-link"}, - h("svg", {viewBox: "0 0 24 24"}, - h("path", {d: "M18.9 12.3h-1.5v6.6c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-5.1h-3.6v5.1c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-6.6H5.1c-.1 0-.3-.1-.3-.2s0-.2.1-.3l6.9-7c.1-.1.3-.1.4 0l7 7v.3c0 .1-.2.2-.3.2z"}) + h("div", { className: "object-bar" }, + h("img", { id: "spinner", src: "data:image/gif;base64,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", hidden: model.spinnerCount == 0 }), + h("a", { href: model.sfLink, className: "sf-link" }, + h("svg", { viewBox: "0 0 24 24" }, + h("path", { d: "M18.9 12.3h-1.5v6.6c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-5.1h-3.6v5.1c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-6.6H5.1c-.1 0-.3-.1-.3-.2s0-.2.1-.3l6.9-7c.1-.1.3-.1.4 0l7 7v.3c0 .1-.2.2-.3.2z" }) ), " Salesforce Home" ), - h("span", {className: "object-tab" + (model.useTab == "all" ? " active-tab" : "")}, - h("a", {href: "about:blank", onClick: this.onUseAllTab}, "All") + h("span", { className: "object-tab" + (model.useTab == "all" ? " active-tab" : "") }, + h("a", { href: "about:blank", onClick: this.onUseAllTab }, "All") ), - h("span", {className: "object-tab" + (model.useTab == "fields" ? " active-tab" : "")}, - h("a", {href: "about:blank", className: "tab-with-icon", onClick: this.onUseFieldsTab}, "Fields"), + h("span", { className: "object-tab" + (model.useTab == "fields" ? " active-tab" : "") }, + h("a", { href: "about:blank", className: "tab-with-icon", onClick: this.onUseFieldsTab }, "Fields"), h(ColumnsVisibiltyBox, { rowList: model.fieldRows, label: "Field columns", content: () => [ - h(ColumnVisibiltyToggle, {rowList: model.fieldRows, key: "name", name: "name", disabled: true}), - h(ColumnVisibiltyToggle, {rowList: model.fieldRows, key: "label", name: "label"}), - h(ColumnVisibiltyToggle, {rowList: model.fieldRows, key: "type", name: "type"}), - h(ColumnVisibiltyToggle, {rowList: model.fieldRows, key: "value", name: "value", disabled: !model.canView()}), - h(ColumnVisibiltyToggle, {rowList: model.fieldRows, key: "helptext", name: "helptext"}), - h(ColumnVisibiltyToggle, {rowList: model.fieldRows, key: "desc", name: "desc", disabled: !model.hasEntityParticles}), - h("hr", {key: "---"}), - model.fieldRows.availableColumns.map(col => h(ColumnVisibiltyToggle, {key: col, name: col, label: col, rowList: model.fieldRows})) + h(ColumnVisibiltyToggle, { rowList: model.fieldRows, key: "name", name: "name", disabled: true }), + h(ColumnVisibiltyToggle, { rowList: model.fieldRows, key: "label", name: "label" }), + h(ColumnVisibiltyToggle, { rowList: model.fieldRows, key: "type", name: "type" }), + h(ColumnVisibiltyToggle, { rowList: model.fieldRows, key: "value", name: "value", disabled: !model.canView() }), + h(ColumnVisibiltyToggle, { rowList: model.fieldRows, key: "helptext", name: "helptext" }), + h(ColumnVisibiltyToggle, { rowList: model.fieldRows, key: "desc", name: "desc", disabled: !model.hasEntityParticles }), + h("hr", { key: "---" }), + model.fieldRows.availableColumns.map(col => h(ColumnVisibiltyToggle, { key: col, name: col, label: col, rowList: model.fieldRows })) ] }) ), - h("span", {className: "object-tab" + (model.useTab == "childs" ? " active-tab" : "")}, - h("a", {href: "about:blank", className: "tab-with-icon", onClick: this.onUseChildsTab}, "Relations"), + h("span", { className: "object-tab" + (model.useTab == "childs" ? " active-tab" : "") }, + h("a", { href: "about:blank", className: "tab-with-icon", onClick: this.onUseChildsTab }, "Relations"), h(ColumnsVisibiltyBox, { rowList: model.childRows, label: "Relationship columns", content: () => [ - ["name", "object", "field", "label"].map(col => h(ColumnVisibiltyToggle, {key: col, rowList: model.childRows, name: col})), - h("hr", {key: "---"}), - model.childRows.availableColumns.map(col => h(ColumnVisibiltyToggle, {key: col, rowList: model.childRows, name: col})) + ["name", "object", "field", "label"].map(col => h(ColumnVisibiltyToggle, { key: col, rowList: model.childRows, name: col })), + h("hr", { key: "---" }), + model.childRows.availableColumns.map(col => h(ColumnVisibiltyToggle, { key: col, rowList: model.childRows, name: col })) ] }) ), - model.useTab != "all" ? null : h("div", {className: "filter-box"}, - h("svg", {className: "filter-icon"}, - h("use", {xlinkHref: "symbols.svg#search"}) + model.useTab != "all" ? null : h("div", { className: "filter-box" }, + h("svg", { className: "filter-icon" }, + h("use", { xlinkHref: "symbols.svg#search" }) ), - h("input", {className: "filter-input", placeholder: "Filter", value: model.rowsFilter, onChange: this.onRowsFilterInput, ref: "rowsFilter"}), - h("a", {href: "about:blank", className: "filter-clear", onClick: this.onClearAndFocusFilter}, - h("svg", {className: "filter-clear-icon"}, - h("use", {xlinkHref: "symbols.svg#clear"}) + h("input", { className: "filter-input", placeholder: "Filter", value: model.rowsFilter, onChange: this.onRowsFilterInput, ref: "rowsFilter" }), + h("a", { href: "about:blank", className: "filter-clear", onClick: this.onClearAndFocusFilter }, + h("svg", { className: "filter-clear-icon" }, + h("use", { xlinkHref: "symbols.svg#clear" }) ) ) ), - h("h1", {className: "object-name"}, - h("span", {className: "quick-select"}, model.objectName()), + h("h1", { className: "object-name" }, + h("span", { className: "quick-select" }, model.objectName()), " ", model.recordHeading() ), - h("span", {className: "object-actions"}, + h("span", { className: "object-actions" }, model.editMode == null && model.recordData && (model.useTab == "all" || model.useTab == "fields") ? h("button", { title: "Inline edit the values of this record", className: "button", @@ -1094,59 +1095,59 @@ class App extends React.Component { disabled: !model.canCreate(), onClick: this.onDoCreate }, model.recordData ? "Clone" : "New") : null, - model.exportLink() ? h("a", {href: model.exportLink(), title: "Export data from this object", className: "button"}, "Export") : null, - model.objectName() ? h("a", {href: "about:blank", onClick: this.onShowObjectMetadata, className: "button"}, "More") : null, - h("button", {className: "button", onClick: this.onToggleObjectActions}, - h("svg", {className: "button-icon"}, - h("use", {xlinkHref: "symbols.svg#down"}) + model.exportLink() ? h("a", { href: model.exportLink(), title: "Export data from this object", className: "button" }, "Export") : null, + model.objectName() ? h("a", { href: "about:blank", onClick: this.onShowObjectMetadata, className: "button" }, "More") : null, + h("button", { className: "button", onClick: this.onToggleObjectActions }, + h("svg", { className: "button-icon" }, + h("use", { xlinkHref: "symbols.svg#down" }) ) ), - model.objectActionsOpen && h("div", {className: "pop-menu"}, - model.viewLink() ? h("a", {href: model.viewLink()}, "View record in Salesforce") : null, - model.editLayoutLink() ? h("a", {href: model.editLayoutLink()}, "Edit page layout") : null, - model.objectSetupLinks && h("a", {href: model.objectSetupLinks.lightningSetupLink}, "Object setup (Lightning)"), - model.objectSetupLinks && h("a", {href: model.objectSetupLinks.classicSetupLink}, "Object setup (Classic)") + model.objectActionsOpen && h("div", { className: "pop-menu" }, + model.viewLink() ? h("a", { href: model.viewLink() }, "View record in Salesforce") : null, + model.editLayoutLink() ? h("a", { href: model.editLayoutLink() }, "Edit page layout") : null, + model.objectSetupLinks && h("a", { href: model.objectSetupLinks.lightningSetupLink }, "Object setup (Lightning)"), + model.objectSetupLinks && h("a", { href: model.objectSetupLinks.classicSetupLink }, "Object setup (Classic)") ) ) ), - h("div", {className: "body " + (model.fieldRows.selectedColumnMap.size < 2 && model.childRows.selectedColumnMap.size < 2 ? "empty " : "")}, - h("div", {hidden: model.errorMessages.length == 0, className: "error-message"}, model.errorMessages.map((data, index) => h("div", {key: index}, data))), + h("div", { className: "body " + (model.fieldRows.selectedColumnMap.size < 2 && model.childRows.selectedColumnMap.size < 2 ? "empty " : "") }, + h("div", { hidden: model.errorMessages.length == 0, className: "error-message" }, model.errorMessages.map((data, index) => h("div", { key: index }, data))), model.useTab == "all" || model.useTab == "fields" ? h(RowTable, { rowList: model.fieldRows, - actionsColumn: {className: "field-actions", reactElement: FieldActionsCell}, + actionsColumn: { className: "field-actions", reactElement: FieldActionsCell }, classNameForRow: row => (row.fieldIsCalculated() ? "fieldCalculated " : "") + (row.fieldIsHidden() ? "fieldHidden " : "") }) : null, model.useTab == "all" ? h("hr", {}) : null, model.useTab == "all" || model.useTab == "childs" ? h(RowTable, { rowList: model.childRows, - actionsColumn: {className: "child-actions", reactElement: ChildActionsCell}, + actionsColumn: { className: "child-actions", reactElement: ChildActionsCell }, classNameForRow: () => "" }) : null ), - model.editMode != null && (model.useTab == "all" || model.useTab == "fields") ? h("span", {className: "edit-bar"}, + model.editMode != null && (model.useTab == "all" || model.useTab == "fields") ? h("span", { className: "edit-bar" }, h("button", { title: model.editMode == "update" ? "Cancel editing this record" - : model.editMode == "delete" ? "Cancel deleting this record" - : model.editMode == "create" ? "Cancel creating this record" - : null, + : model.editMode == "delete" ? "Cancel deleting this record" + : model.editMode == "create" ? "Cancel creating this record" + : null, className: "button", onClick: this.onCancelEdit }, "Cancel"), h("button", { title: model.editMode == "update" ? "Save the values of this record" - : model.editMode == "delete" ? "Delete this record" - : model.editMode == "create" ? "Save the values as a new record" - : null, + : model.editMode == "delete" ? "Delete this record" + : model.editMode == "create" ? "Save the values as a new record" + : null, className: "button " + (model.editMode == "delete" ? "button-destructive" : "button-brand"), onClick: this.onDoSave }, model.editMode == "update" ? "Save" - : model.editMode == "delete" ? "Confirm delete" - : model.editMode == "create" ? "Save new" - : "???") + : model.editMode == "delete" ? "Confirm delete" + : model.editMode == "create" ? "Save new" + : "???") ) : null, - model.detailsBox ? h(DetailsBox, {model}) : null + model.detailsBox ? h(DetailsBox, { model }) : null ) ); } @@ -1159,21 +1160,21 @@ class ColumnsVisibiltyBox extends React.Component { } onAvailableColumnsClick(e) { e.preventDefault(); - let {rowList} = this.props; + let { rowList } = this.props; rowList.toggleAvailableColumns(); rowList.model.didUpdate(); } render() { - let {rowList, label, content} = this.props; - return h("span", {className: "column-button-outer"}, - h("a", {href: "about:blank", onClick: this.onAvailableColumnsClick, className: "button-icon-link"}, - h("svg", {className: "button-icon"}, - h("use", {xlinkHref: "symbols.svg#chevrondown"}) + let { rowList, label, content } = this.props; + return h("span", { className: "column-button-outer" }, + h("a", { href: "about:blank", onClick: this.onAvailableColumnsClick, className: "button-icon-link" }, + h("svg", { className: "button-icon" }, + h("use", { xlinkHref: "symbols.svg#chevrondown" }) ) ), - rowList.availableColumns ? h("div", {className: "column-popup"}, - h("div", {className: "column-popup-inner"}, - h("span", {className: "menu-item"}, label), + rowList.availableColumns ? h("div", { className: "column-popup" }, + h("div", { className: "column-popup-inner" }, + h("span", { className: "menu-item" }, label), content() ) ) : null @@ -1187,13 +1188,13 @@ class ColumnVisibiltyToggle extends React.Component { this.onShowColumnChange = this.onShowColumnChange.bind(this); } onShowColumnChange(e) { - let {rowList, name} = this.props; + let { rowList, name } = this.props; rowList.showHideColumn(e.target.checked, name); rowList.model.didUpdate(); } render() { - let {rowList, name, disabled} = this.props; - return h("label", {className: "menu-item"}, + let { rowList, name, disabled } = this.props; + return h("label", { className: "menu-item" }, h("input", { type: "checkbox", checked: rowList.selectedColumnMap.has(name), @@ -1207,29 +1208,29 @@ class ColumnVisibiltyToggle extends React.Component { class RowTable extends React.Component { render() { - let {rowList, actionsColumn, classNameForRow} = this.props; + let { rowList, actionsColumn, classNameForRow } = this.props; let selectedColumns = Array.from(rowList.selectedColumnMap.values()); return h("table", {}, h("thead", {}, h("tr", {}, selectedColumns.map(col => - h(HeaderCell, {key: col.name, col, rowList}) + h(HeaderCell, { key: col.name, col, rowList }) ), - h("th", {className: actionsColumn.className}, "") + h("th", { className: actionsColumn.className }, "") ), rowList.model.useTab != "all" ? h("tr", {}, selectedColumns.map(col => - h(FilterCell, {key: col.name, col, rowList}) + h(FilterCell, { key: col.name, col, rowList }) ), - h("th", {className: actionsColumn.className}) + h("th", { className: actionsColumn.className }) ) : null ), h("tbody", {}, rowList.rows.map(row => - h("tr", {className: classNameForRow(row), hidden: !row.visible(), title: row.summary(), key: row.reactKey}, + h("tr", { className: classNameForRow(row), hidden: !row.visible(), title: row.summary(), key: row.reactKey }, selectedColumns.map(col => - h(col.reactElement, {key: col.name, row, col}) + h(col.reactElement, { key: col.name, row, col }) ), - h(actionsColumn.reactElement, {row}) + h(actionsColumn.reactElement, { row }) ) )) ); @@ -1242,12 +1243,12 @@ class HeaderCell extends React.Component { this.onSortRowsBy = this.onSortRowsBy.bind(this); } onSortRowsBy() { - let {rowList, col} = this.props; + let { rowList, col } = this.props; rowList.sortRowsBy(col.name); rowList.model.didUpdate(); } render() { - let {col} = this.props; + let { col } = this.props; return h("th", { className: col.className, @@ -1265,13 +1266,13 @@ class FilterCell extends React.Component { this.onColumnFilterInput = this.onColumnFilterInput.bind(this); } onColumnFilterInput(e) { - let {rowList, col} = this.props; + let { rowList, col } = this.props; col.columnFilter = e.target.value; rowList.model.didUpdate(); } render() { - let {col} = this.props; - return h("th", {className: col.className}, + let { col } = this.props; + return h("th", { className: col.className }, h("input", { placeholder: "Filter", className: "column-filter-box", @@ -1284,9 +1285,9 @@ class FilterCell extends React.Component { class DefaultCell extends React.Component { render() { - let {row, col} = this.props; - return h("td", {className: col.className}, - h(TypedValue, {value: row.sortKey(col.name)}) + let { row, col } = this.props; + return h("td", { className: col.className }, + h(TypedValue, { value: row.sortKey(col.name) }) ); } } @@ -1298,48 +1299,55 @@ class FieldValueCell extends React.Component { this.onDataEditValueInput = this.onDataEditValueInput.bind(this); this.onCancelEdit = this.onCancelEdit.bind(this); this.onRecordIdClick = this.onRecordIdClick.bind(this); + this.onLinkClick = this.onLinkClick.bind(this); } onTryEdit(e) { - let {row} = this.props; + let { row } = this.props; if (row.tryEdit()) { let td = e.currentTarget; row.rowList.model.didUpdate(() => td.querySelector("textarea").focus()); } } onDataEditValueInput(e) { - let {row} = this.props; + let { row } = this.props; row.dataEditValue = e.target.value; row.rowList.model.didUpdate(); } onCancelEdit(e) { e.preventDefault(); - let {row} = this.props; + let { row } = this.props; row.dataEditValue = null; row.rowList.model.didUpdate(); } onRecordIdClick(e) { e.preventDefault(); - let {row} = this.props; + let { row } = this.props; row.toggleRecordIdPop(); row.rowList.model.didUpdate(); } + onLinkClick(e) { + if (e.target.className?.includes("copy-id")) { + navigator.clipboard.writeText(e.target.id); + } + this.onRecordIdClick(e); + } render() { - let {row, col} = this.props; + let { row, col } = this.props; if (row.isEditing()) { - return h("td", {className: col.className}, - h("textarea", {value: row.dataEditValue, onChange: this.onDataEditValueInput}), - h("a", {href: "about:blank", onClick: this.onCancelEdit, className: "undo-button"}, "\u21B6") + return h("td", { className: col.className }, + h("textarea", { value: row.dataEditValue, onChange: this.onDataEditValueInput }), + h("a", { href: "about:blank", onClick: this.onCancelEdit, className: "undo-button" }, "\u21B6") ); } else if (row.isId()) { - return h("td", {className: col.className, onDoubleClick: this.onTryEdit}, - h("div", {className: "pop-menu-container"}, - h("div", {className: "value-text quick-select"}, h("a", {href: row.idLink() /*used to show visited color*/, onClick: this.onRecordIdClick}, row.dataStringValue())), - row.recordIdPop == null ? null : h("div", {className: "pop-menu"}, row.recordIdPop.map(link => h("a", {key: link.href, href: link.href}, link.text))) + return h("td", { className: col.className, onDoubleClick: this.onTryEdit }, + h("div", { className: "pop-menu-container" }, + h("div", { className: "value-text quick-select" }, h("a", { href: row.idLink() /*used to show visited color*/, onClick: this.onRecordIdClick }, row.dataStringValue())), + row.recordIdPop == null ? null : h("div", { className: "pop-menu" }, row.recordIdPop.map(link => h("a", { key: link.href, href: link.href, className: link.className, id: link.id, onClick: this.onLinkClick }, link.text))) ) ); } else { - return h("td", {className: col.className, onDoubleClick: this.onTryEdit}, - h(TypedValue, {value: row.sortKey(col.name)}) + return h("td", { className: col.className, onDoubleClick: this.onTryEdit }, + h(TypedValue, { value: row.sortKey(col.name) }) ); } } @@ -1347,21 +1355,21 @@ class FieldValueCell extends React.Component { class FieldTypeCell extends React.Component { render() { - let {row, col} = this.props; - return h("td", {className: col.className + " quick-select"}, + let { row, col } = this.props; + return h("td", { className: col.className + " quick-select" }, row.referenceTypes() ? row.referenceTypes().map(data => - h("span", {key: data}, h("a", {href: row.showReferenceUrl(data)}, data), " ") + h("span", { key: data }, h("a", { href: row.showReferenceUrl(data) }, data), " ") ) : null, - !row.referenceTypes() ? h(TypedValue, {value: row.sortKey(col.name)}) : null + !row.referenceTypes() ? h(TypedValue, { value: row.sortKey(col.name) }) : null ); } } class ChildObjectCell extends React.Component { render() { - let {row, col} = this.props; - return h("td", {className: col.className + " quick-select", key: col.name}, - h("a", {href: row.showChildObjectUrl()}, row.childObject()) + let { row, col } = this.props; + return h("td", { className: col.className + " quick-select", key: col.name }, + h("a", { href: row.showChildObjectUrl() }, row.childObject()) ); } } @@ -1379,10 +1387,10 @@ let TypedValue = props => + (props.value === true ? "value-is-boolean-true " : "") + (props.value === undefined || props.value === null ? "" : "quick-select ") }, - props.value === undefined ? "(Unknown)" - : props.value === null ? "(Blank)" - : typeof props.value == "object" ? JSON.stringify(props.value, null, " ") - : "" + props.value + props.value === undefined ? "(Unknown)" + : props.value === null ? "(Blank)" + : typeof props.value == "object" ? JSON.stringify(props.value, null, " ") + : "" + props.value ); class FieldActionsCell extends React.Component { @@ -1393,28 +1401,28 @@ class FieldActionsCell extends React.Component { } onOpenDetails(e) { e.preventDefault(); - let {row} = this.props; + let { row } = this.props; row.showFieldMetadata(); row.rowList.model.didUpdate(); } onToggleFieldActions() { - let {row} = this.props; + let { row } = this.props; row.toggleFieldActions(); row.rowList.model.didUpdate(); } render() { - let {row} = this.props; - return h("td", {className: "field-actions"}, - h("div", {className: "pop-menu-container"}, - h("button", {className: "actions-button", onClick: this.onToggleFieldActions}, - h("svg", {className: "actions-icon"}, - h("use", {xlinkHref: "symbols.svg#down"}) + let { row } = this.props; + return h("td", { className: "field-actions" }, + h("div", { className: "pop-menu-container" }, + h("button", { className: "actions-button", onClick: this.onToggleFieldActions }, + h("svg", { className: "actions-icon" }, + h("use", { xlinkHref: "symbols.svg#down" }) ), ), - row.fieldActionsOpen && h("div", {className: "pop-menu"}, - h("a", {href: "about:blank", onClick: this.onOpenDetails}, "All field metadata"), - row.fieldSetupLinks && h("a", {href: row.fieldSetupLinks.lightningSetupLink}, "Field setup (Lightning)"), - row.fieldSetupLinks && h("a", {href: row.fieldSetupLinks.classicSetupLink}, "Field setup (Classic)") + row.fieldActionsOpen && h("div", { className: "pop-menu" }, + h("a", { href: "about:blank", onClick: this.onOpenDetails }, "All field metadata"), + row.fieldSetupLinks && h("a", { href: row.fieldSetupLinks.lightningSetupLink }, "Field setup (Lightning)"), + row.fieldSetupLinks && h("a", { href: row.fieldSetupLinks.classicSetupLink }, "Field setup (Classic)") ) ) ); @@ -1429,29 +1437,29 @@ class ChildActionsCell extends React.Component { } onOpenDetails(e) { e.preventDefault(); - let {row} = this.props; + let { row } = this.props; row.showChildMetadata(); row.rowList.model.didUpdate(); } onToggleChildActions() { - let {row} = this.props; + let { row } = this.props; row.toggleChildActions(); row.rowList.model.didUpdate(); } render() { - let {row} = this.props; - return h("td", {className: "child-actions"}, - h("div", {className: "pop-menu-container"}, - h("button", {className: "actions-button", onClick: this.onToggleChildActions}, - h("svg", {className: "actions-icon"}, - h("use", {xlinkHref: "symbols.svg#down"}) + let { row } = this.props; + return h("td", { className: "child-actions" }, + h("div", { className: "pop-menu-container" }, + h("button", { className: "actions-button", onClick: this.onToggleChildActions }, + h("svg", { className: "actions-icon" }, + h("use", { xlinkHref: "symbols.svg#down" }) ), ), - row.childActionsOpen && h("div", {className: "pop-menu"}, - h("a", {href: "about:blank", onClick: this.onOpenDetails}, "All relationship metadata"), - row.queryListUrl() ? h("a", {href: row.queryListUrl(), title: "Export records in this related list"}, "Export related records") : null, - row.childSetupLinks && h("a", {href: row.childSetupLinks.lightningSetupLink}, "Setup (Lightning)"), - row.childSetupLinks && h("a", {href: row.childSetupLinks.classicSetupLink}, "Setup (Classic)") + row.childActionsOpen && h("div", { className: "pop-menu" }, + h("a", { href: "about:blank", onClick: this.onOpenDetails }, "All relationship metadata"), + row.queryListUrl() ? h("a", { href: row.queryListUrl(), title: "Export records in this related list" }, "Export related records") : null, + row.childSetupLinks && h("a", { href: row.childSetupLinks.lightningSetupLink }, "Setup (Lightning)"), + row.childSetupLinks && h("a", { href: row.childSetupLinks.classicSetupLink }, "Setup (Classic)") ) ) ); @@ -1470,41 +1478,41 @@ class DetailsBox extends React.Component { } onCloseDetailsBox(e) { e.preventDefault(); - let {model} = this.props; + let { model } = this.props; model.detailsBox = null; model.didUpdate(); } onDetailsFilterInput(e) { - let {model} = this.props; + let { model } = this.props; model.detailsFilter = e.target.value; model.didUpdate(); } onDetailsFilterClick(e, row, detailsFilterList) { e.preventDefault(); - let {model} = this.props; + let { model } = this.props; model.detailsBox = null; detailsFilterList.showColumn(row.key, row.value); model.didUpdate(); } render() { - let {model} = this.props; + let { model } = this.props; return h("div", {}, - h("div", {id: "fieldDetailsView"}, - h("div", {className: "container"}, - h("a", {href: "about:blank", className: "closeLnk", onClick: this.onCloseDetailsBox}, "X"), - h("div", {className: "mainContent"}, + h("div", { id: "fieldDetailsView" }, + h("div", { className: "container" }, + h("a", { href: "about:blank", className: "closeLnk", onClick: this.onCloseDetailsBox }, "X"), + h("div", { className: "mainContent" }, h("h3", {}, "All available metadata for \"" + model.detailsBox.name + "\""), - h("input", {placeholder: "Filter", value: model.detailsFilter, onChange: this.onDetailsFilterInput, ref: "detailsFilter"}), + h("input", { placeholder: "Filter", value: model.detailsFilter, onChange: this.onDetailsFilterInput, ref: "detailsFilter" }), h("table", {}, h("thead", {}, h("tr", {}, h("th", {}, "Key"), h("th", {}, "Value"))), h("tbody", {}, model.detailsBox.rows.map(row => - h("tr", {hidden: !row.visible(), key: row.key}, + h("tr", { hidden: !row.visible(), key: row.key }, h("td", {}, - h("a", {href: "about:blank", onClick: e => this.onDetailsFilterClick(e, row, model.detailsBox.detailsFilterList), hidden: !model.detailsBox.detailsFilterList, title: "Show fields with this property"}, "🔍"), + h("a", { href: "about:blank", onClick: e => this.onDetailsFilterClick(e, row, model.detailsBox.detailsFilterList), hidden: !model.detailsBox.detailsFilterList, title: "Show fields with this property" }, "🔍"), " ", - h("span", {className: "quick-select"}, row.key) + h("span", { className: "quick-select" }, row.key) ), - h("td", {}, h(TypedValue, {value: row.value})) + h("td", {}, h(TypedValue, { value: row.value })) ) )) ) @@ -1529,9 +1537,9 @@ class DetailsBox extends React.Component { model.recordId = args.get("recordId"); model.startLoading(); model.reactCallback = cb => { - ReactDOM.render(h(App, {model}), root, cb); + ReactDOM.render(h(App, { model }), root, cb); }; - ReactDOM.render(h(App, {model}), root); + ReactDOM.render(h(App, { model }), root); }); From fbf5ed4c4f15508c00858e0c81c396e23b2b29a6 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Fri, 5 May 2023 16:40:59 +0200 Subject: [PATCH 16/21] Fix target link on version --- addon/popup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/popup.js b/addon/popup.js index 22b4e12f..88c48ce4 100644 --- a/addon/popup.js +++ b/addon/popup.js @@ -168,7 +168,7 @@ class App extends React.PureComponent { h("div", { className: "footer" }, h("div", { className: "meta" }, h("div", { className: "version" }, - h("a", { href: "https://github.com/tprouvot/Chrome-Salesforce-inspector/blob/master/CHANGES.md", title: "Release note" }, "v" + addonVersion), + h("a", { href: "https://github.com/tprouvot/Chrome-Salesforce-inspector/blob/master/CHANGES.md", title: "Release note", target: linkTarget }, "v" + addonVersion), " / ", h("a", { href: "https://status.salesforce.com/instances/" + orgInstance, title: "Instance status", target: linkTarget }, orgInstance), " / ", From 72e600ae45b54be1631452d9a4349b24c48ff286 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Tue, 9 May 2023 11:06:22 +0200 Subject: [PATCH 17/21] Fix on copy id from inspect view --- addon/inspect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/inspect.js b/addon/inspect.js index b632bd04..d142b3d2 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -1328,8 +1328,8 @@ class FieldValueCell extends React.Component { onLinkClick(e) { if (e.target.className?.includes("copy-id")) { navigator.clipboard.writeText(e.target.id); + this.onRecordIdClick(e); } - this.onRecordIdClick(e); } render() { let { row, col } = this.props; From 199b17545ea7c24475dbb8d795ec077b42ddc98f Mon Sep 17 00:00:00 2001 From: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Date: Wed, 10 May 2023 10:45:48 +0200 Subject: [PATCH 18/21] [feat] Add spinner and disable button when save in show all data (#86) Fix #69 --- CHANGES.md | 15 +-- addon/inspect.css | 228 ++++++++++++++++++++++++++++++++++----------- addon/inspect.html | 30 +++--- addon/inspect.js | 26 +++++- 4 files changed, 220 insertions(+), 79 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4fe5df13..531a28da 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,14 +3,15 @@ Version 1.17 General ------- -* Show "Copy Id" from Inspect page ([feature 12](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/12) ) -* Add a configuration option for links to open in a new tab ([feature 78](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/78) ) -* Import data as JSON ([feature 75](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/75) ) -* Fix auto update action on data import ([issue 73](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/73) ) -* Restore focus on suggested fields when pressing tab key in query editor ([issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) created by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) +* Update spinner on inspect page when loading or saving records and disable button [feature 69](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/69) (idea by [Camille Guillory](https://github.com/CamilleGuillory)) +* Show "Copy Id" from Inspect page [feature 12](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/12) +* Add a configuration option for links to open in a new tab [feature 78](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/78) (idea by [Henri Vilminko](https://github.com/hvilminko)) +* Import data as JSON [feature 75](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/75) (idea by [gaelguimini](https://github.com/gaelguimini)) +* Fix auto update action on data import [issue 73](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/73) (issue by [Juul1](https://github.com/Juul1)) +* Restore focus on suggested fields when pressing tab key in query editor [issue 66](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/66) (idea by [Enrique Muñoz](https://github.com/emunoz-at-wiris)) * Update shortcut indication for mac users -* Fix links for custom object [PR80](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/80) (by [Mouloud Habchi](https://github.com/MD931) ) -* Fix links for custom setting [PR82](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/82) (by [Mouloud Habchi](https://github.com/MD931) ) +* Fix links for custom object [PR80](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/80) (contribution by [Mouloud Habchi](https://github.com/MD931)) +* Fix links for custom setting [PR82](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/82) (contribution by [Mouloud Habchi](https://github.com/MD931)) Version 1.16 =========== diff --git a/addon/inspect.css b/addon/inspect.css index a29e29e1..d298f38c 100644 --- a/addon/inspect.css +++ b/addon/inspect.css @@ -1,74 +1,97 @@ @font-face { - font-family:'Salesforce Sans'; - src:url(fonts/SalesforceSans-Light.woff2); - font-weight:300 + font-family: 'Salesforce Sans'; + src: url(fonts/SalesforceSans-Light.woff2); + font-weight: 300 } + @font-face { - font-family:'Salesforce Sans'; - src:url(fonts/SalesforceSans-LightItalic.woff2); - font-style:italic; - font-weight:300 + font-family: 'Salesforce Sans'; + src: url(fonts/SalesforceSans-LightItalic.woff2); + font-style: italic; + font-weight: 300 } + @font-face { - font-family:'Salesforce Sans'; - src:url(fonts/SalesforceSans-Regular.woff2); - font-weight:400 + font-family: 'Salesforce Sans'; + src: url(fonts/SalesforceSans-Regular.woff2); + font-weight: 400 } + @font-face { - font-family:'Salesforce Sans'; - src:url(fonts/SalesforceSans-Italic.woff2); - font-style:italic; - font-weight:400 + font-family: 'Salesforce Sans'; + src: url(fonts/SalesforceSans-Italic.woff2); + font-style: italic; + font-weight: 400 } + @font-face { - font-family:'Salesforce Sans'; - src:url(fonts/SalesforceSans-Bold.woff2); - font-weight:700 + font-family: 'Salesforce Sans'; + src: url(fonts/SalesforceSans-Bold.woff2); + font-weight: 700 } + @font-face { - font-family:'Salesforce Sans'; - src:url(fonts/SalesforceSans-BoldItalic.woff2); - font-style:italic; - font-weight:700 + font-family: 'Salesforce Sans'; + src: url(fonts/SalesforceSans-BoldItalic.woff2); + font-style: italic; + font-weight: 700 } + * { box-sizing: border-box; } -html, body, #root, [data-reactroot] { + +html, +body, +#root, +[data-reactroot] { height: 100%; } + [data-reactroot] { display: flex; flex-direction: column; } + html { - font-family: "Salesforce Sans",Arial,sans-serif; + font-family: "Salesforce Sans", Arial, sans-serif; font-size: 100%; line-height: 1.5; background: #fff; color: #16325c; } + body { - font-family: "Salesforce Sans",Arial,sans-serif; + font-family: "Salesforce Sans", Arial, sans-serif; font-size: .8125rem; margin: 0; } + a { color: #0070d2; text-decoration: none; transition: color .1s linear; } + a:active { color: #00396b; } -a:focus, a:hover { + +a:focus, +a:hover { text-decoration: underline; color: #005fb2; } -a:active, a:hover { + +a:active, +a:hover { outline: 0; } -.sf-link, .sf-link:active, .sf-link:focus, .sf-link:hover { + +.sf-link, +.sf-link:active, +.sf-link:focus, +.sf-link:hover { margin-right: 1em; background-color: rgb(6, 28, 63); border-radius: 3px; @@ -80,6 +103,7 @@ a:active, a:hover { padding-right: 1em; margin-right: 20px; } + .sf-link svg { width: 1.8em; height: 1.8em; @@ -91,59 +115,78 @@ a:active, a:hover { border-radius: 2px; fill: white; } + table { width: 100%; border-spacing: 0px; } + .value-text { word-wrap: break-word; white-space: pre-wrap; } + .value-text.value-is-object { color: #990; } + .value-text.value-is-number { color: #909; } + .value-text.value-is-boolean { color: #900; } + .value-text.value-is-boolean-true { color: #099; } + .value-text.value-is-blank { color: #aaa; font-style: italic; } + .value-text.value-is-unknown { color: #aaa; font-style: italic; } + tr.fieldCalculated { font-style: italic; } -tr.fieldHidden, tr.fieldHidden a[href] { + +tr.fieldHidden, +tr.fieldHidden a[href] { color: #777; } + tr:hover { background-color: lightblue; } + th { text-align: left; } + .field-label { white-space: nowrap; } + .field-name { white-space: nowrap; } + .field-column { - max-width: 200px; /* To handle long words. This is not actually 200px but scales with the table. Table layout magic. */ + max-width: 200px; + /* To handle long words. This is not actually 200px but scales with the table. Table layout magic. */ } + .field-column textarea { width: calc(100% - 20px); resize: vertical; } + .undo-button { background-color: #eee; border-radius: 3px; @@ -157,13 +200,16 @@ th { vertical-align: top; margin-top: 5px; } + .undo-button[hidden] { display: none; } + .field-actions { text-align: right; white-space: nowrap; } + .actions-button { width: 1.25rem; height: 1.25rem; @@ -181,40 +227,46 @@ th { white-space: normal; cursor: pointer; } + .actions-button:hover, .actions-button:active, .actions-button:focus { color: #005fb2; } + .actions-button:focus { outline: 0; box-shadow: 0 0 3px #0070d2; } + .actions-icon { width: .75rem; height: .75rem; overflow: hidden; fill: #b0adab; } + th[tabindex] { text-decoration: underline; cursor: pointer; color: darkblue; } + .column-filter-box { width: 100%; } + #fieldDetailsView { position: fixed; top: 0; right: 0; bottom: 0; left: 0; - background: rgba(0,0,0,0.8); + background: rgba(0, 0, 0, 0.8); z-index: 99999; } -#fieldDetailsView > div.container { +#fieldDetailsView>div.container { width: 600px; height: 500px; position: relative; @@ -222,11 +274,13 @@ th[tabindex] { border-radius: 10px; background: #fff; } -#fieldDetailsView > div.container > div.mainContent { + +#fieldDetailsView>div.container>div.mainContent { overflow: auto; height: 470px; padding: 5px 20px 13px 20px; } + .closeLnk { background: #606061; color: #FFFFFF; @@ -241,17 +295,21 @@ th[tabindex] { border-radius: 12px; box-shadow: 1px 1px 3px #000; } + .closeLnk:hover { background: #00d9ff; } + #fieldDetailsView td { white-space: pre; } + .filter-box { white-space: nowrap; margin: 0 1rem; position: relative; } + .filter-input { width: 20em; padding: 0 3rem; @@ -259,26 +317,30 @@ th[tabindex] { color: #16325c; border: 1px solid #d8dde6; border-radius: .25rem; - transition: border .1s linear,background-color .1s linear; + transition: border .1s linear, background-color .1s linear; display: inline-block; line-height: 1.875rem; min-height: calc(1.875rem + (1px * 2)); } -.filter-input:active, .filter-input:focus { + +.filter-input:active, +.filter-input:focus { outline: 0; border-color: #1589ee; background-color: #fff; box-shadow: 0 0 3px #0070D2; } + .filter-icon { - left: 1.25rem; - width: 1rem; - height: 1rem; - position: absolute; - top: 50%; - margin-top: -.5rem; - fill: #9faab5; + left: 1.25rem; + width: 1rem; + height: 1rem; + position: absolute; + top: 50%; + margin-top: -.5rem; + fill: #9faab5; } + .filter-clear { right: 1.25rem; width: 1rem; @@ -295,13 +357,15 @@ th[tabindex] { border-radius: .25rem; font-size: .75rem; text-decoration: none; - transition: color 50ms linear,background-color 50ms linear; + transition: color 50ms linear, background-color 50ms linear; } + .filter-clear-icon { width: .875rem; height: .875rem; fill: currentColor; } + .error-message { font-size: 1.2em; font-weight: bold; @@ -311,11 +375,13 @@ th[tabindex] { border: 1px solid red; border-radius: 7px; } + +/* #spinner { position: absolute; left: -15px; top: -15px; -} +}*/ .object-bar { background: #f7f9fb; width: 100%; @@ -324,10 +390,12 @@ th[tabindex] { padding: 0 1.5rem; flex-wrap: wrap; } + .object-tab { position: relative; align-self: flex-end; } + .object-tab a { color: #54698d; padding: 0 .75rem; @@ -336,19 +404,27 @@ th[tabindex] { line-height: 3rem; display: inline-block; } -.object-tab a , .object-tab a:focus, .object-tab a:active, .object-tab a:hover { + +.object-tab a, +.object-tab a:focus, +.object-tab a:active, +.object-tab a:hover { text-decoration: none; } + .object-tab:hover::after, .object-tab.active-tab::after { background-color: #0070d2; } + .object-tab.active-tab a { color: #16325c; } + .object-tab * { vertical-align: middle; } + .object-tab::after { display: block; content: ''; @@ -359,18 +435,22 @@ th[tabindex] { height: 2px; align-self: stretch; } + .object-tab .tab-with-icon { padding-right: .375rem; } + .object-tab .button-icon-link { padding-left: .375rem; } + .button-icon { width: .875rem; height: .875rem; fill: currentColor; vertical-align: middle; } + .object-name { flex: 1 1 0; margin: 0 1em; @@ -381,6 +461,7 @@ th[tabindex] { overflow: hidden; position: relative; } + .button { background-color: #fff; color: #0070d2; @@ -394,77 +475,101 @@ th[tabindex] { font: unset; font-size: .75rem; line-height: 1.875rem; - transition: color 50ms linear,background-color 50ms linear; + transition: color 50ms linear, background-color 50ms linear; } + .button[disabled] { cursor: default; - color: #dddbda; - background-color: #fff; + background-color: var(--slds-g-color-neutral-base-80, #c9c7c5); + border-color: var(--slds-g-color-neutral-base-80, #c9c7c5); + color: var(--slds-g-color-neutral-base-100, #fff); } + .object-actions { position: relative; } + .object-actions .button:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; border-left: none; } + .object-actions .button:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } + .button:active:not([disabled]) { background-color: #eef1f6; color: #00396b; } + .button:focus { outline: 0; box-shadow: 0 0 3px #0070D2; } -.button:focus:not([disabled]), .button:hover:not([disabled]) { + +.button:focus:not([disabled]), +.button:hover:not([disabled]) { background-color: #f4f6f9; color: #005fb2; } -.button:active, .button:focus, .button:hover, .button:visited { + +.button:active, +.button:focus, +.button:hover, +.button:visited { text-decoration: none; } + .button-brand { background-color: #0070d2; border-color: #0070d2; color: #fff; } -.button-brand:focus:not([disabled]), .button-brand:hover:not([disabled]) { + +.button-brand:focus:not([disabled]), +.button-brand:hover:not([disabled]) { background-color: #005fb2; border-color: #005fb2; color: #fff; } + .button-brand:active:not([disabled]) { background-color: #005fb2; border-color: #005fb2; color: #fff; } + .button-destructive { background-color: #c23934; border-color: #c23934; color: #fff; } -.button-destructive:focus:not([disabled]), .button-destructive:hover:not([disabled]) { + +.button-destructive:focus:not([disabled]), +.button-destructive:hover:not([disabled]) { background-color: #a61a14; color: #fff; } + .button-destructive:active:not([disabled]) { background-color: #870500; border-color: #870500; color: #fff; } + .column-button-outer { position: relative; display: inline-block; } + .column-popup-inner { overflow: auto; max-height: 500px; } + .column-popup { position: absolute; z-index: 7000; @@ -477,9 +582,10 @@ th[tabindex] { padding: .25rem 0; font-size: .75rem; background: #fff; - box-shadow: 0 2px 3px 0 rgba(0,0,0,.16); + box-shadow: 0 2px 3px 0 rgba(0, 0, 0, .16); margin-top: .5rem; } + .column-popup::before { width: 1rem; height: 1rem; @@ -491,8 +597,9 @@ th[tabindex] { top: -.5rem; margin-left: -.5rem; } + .column-popup::after { - box-shadow: -1px -1px 0 0 rgba(0,0,0,.16); + box-shadow: -1px -1px 0 0 rgba(0, 0, 0, .16); z-index: -1; width: 1rem; height: 1rem; @@ -504,10 +611,12 @@ th[tabindex] { top: -.5rem; margin-left: -.5rem; } + .column-popup label.menu-item { display: block; padding: .2rem .75rem; } + .column-popup span.menu-item { display: block; padding: .5rem .75rem; @@ -517,36 +626,45 @@ th[tabindex] { text-transform: uppercase; letter-spacing: .0625rem; } + .column-popup label.menu-item:hover { background-color: #f4f6f9; } + .body { padding: 8px; overflow: auto; flex: 1 1 0; } + @keyframes spin { 100% { transform: rotate(360deg); } } + .body.empty { animation: spin 4s linear infinite; } + .edit-bar { text-align: center; padding: 1rem 0; } + .edit-bar .button { margin: 0 .25rem; } + .child-actions { text-align: right; white-space: nowrap; } + .pop-menu-container { position: relative; } + .pop-menu { z-index: 10; position: absolute; @@ -556,12 +674,14 @@ th[tabindex] { margin-left: 5px; margin-top: -5px; } + .pop-menu a { display: block; } + .object-actions .pop-menu, .field-actions .pop-menu, .child-actions .pop-menu { right: 0; text-align: right; -} +} \ No newline at end of file diff --git a/addon/inspect.html b/addon/inspect.html index 6fc3a6a2..2f89076d 100644 --- a/addon/inspect.html +++ b/addon/inspect.html @@ -1,16 +1,20 @@ - - - ... - - - - -
- - - - - + + + + ... + + + + + + +
+ + + + + + \ No newline at end of file diff --git a/addon/inspect.js b/addon/inspect.js index d142b3d2..ac6da7c1 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -990,25 +990,33 @@ class App extends React.Component { model.toggleObjectActions(); model.didUpdate(); } - onDoUpdate() { + onDoUpdate(e) { + e.currentTarget.disabled = true; let { model } = this.props; model.doUpdate(); model.didUpdate(); + e.currentTarget.disabled = false; } - onDoDelete() { + onDoDelete(e) { + e.currentTarget.disabled = true; let { model } = this.props; model.doDelete(); model.didUpdate(); + e.currentTarget.disabled = false; } - onDoCreate() { + onDoCreate(e) { + e.currentTarget.disabled = true; let { model } = this.props; model.doCreate(); model.didUpdate(); + e.currentTarget.disabled = false; } - onDoSave() { + onDoSave(e) { + e.currentTarget.disabled = true; let { model } = this.props; model.doSave(); model.didUpdate(); + e.currentTarget.disabled = false; } onCancelEdit() { let { model } = this.props; @@ -1021,7 +1029,13 @@ class App extends React.Component { return ( h("div", {}, h("div", { className: "object-bar" }, - h("img", { id: "spinner", src: "data:image/gif;base64,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", hidden: model.spinnerCount == 0 }), + h("div", { className: "flex-right" }, + h("div", { id: "spinner", role: "status", className: "slds-spinner slds-spinner_large", hidden: model.spinnerCount == 0 }, + h("span", { className: "slds-assistive-text" }), + h("div", { className: "slds-spinner__dot-a" }), + h("div", { className: "slds-spinner__dot-b" }), + ) + ), h("a", { href: model.sfLink, className: "sf-link" }, h("svg", { viewBox: "0 0 24 24" }, h("path", { d: "M18.9 12.3h-1.5v6.6c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-5.1h-3.6v5.1c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-6.6H5.1c-.1 0-.3-.1-.3-.2s0-.2.1-.3l6.9-7c.1-.1.3-.1.4 0l7 7v.3c0 .1-.2.2-.3.2z" }) @@ -1135,12 +1149,14 @@ class App extends React.Component { onClick: this.onCancelEdit }, "Cancel"), h("button", { + name: "saveBtn", title: model.editMode == "update" ? "Save the values of this record" : model.editMode == "delete" ? "Delete this record" : model.editMode == "create" ? "Save the values as a new record" : null, className: "button " + (model.editMode == "delete" ? "button-destructive" : "button-brand"), + disabled: model.spinnerCount != 0 ? true : false, onClick: this.onDoSave }, model.editMode == "update" ? "Save" : model.editMode == "delete" ? "Confirm delete" From d39ff54c481108e4a06a00a9bdcef77b4c07dc9e Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Wed, 10 May 2023 10:53:04 +0200 Subject: [PATCH 19/21] Add contribution section --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index c3206fa1..b3aee8da 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,18 @@ Troubleshooting * If Salesforce Inspector is not available after installation, the most likely issue is that your browser is not up to date. See [instructions for Google Chrome](https://productforums.google.com/forum/#!topic/chrome/YK1-o4KoSjc). * When you enable the My Domain feature in Salesforce, Salesforce Inspector may not work until you have restarted your browser (or until you have deleted the "sid" cookie for the old Salesforce domain by other means). + +Contributions +----- + +Contributions are welcomed ! + +To submit a PR, please create a branch from releaseCandidate which is the work in progress next version. +This branch will be merge into master when the new version is published on web store. + +Linting : to assure indentation, formatting and best practices coherence, please install ESLint extension. + + Development ----- From c571339986ddc5b3160d6b3ab92acf57091ca478 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot Date: Wed, 10 May 2023 11:54:29 +0200 Subject: [PATCH 20/21] Fix test --- addon/data-import-test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addon/data-import-test.js b/addon/data-import-test.js index 9640eb57..e74dd9f7 100644 --- a/addon/data-import-test.js +++ b/addon/data-import-test.js @@ -170,6 +170,7 @@ export async function dataImportTest(test) { vm.dataFormat = "csv"; vm.didUpdate(); vm.importAction = "delete"; + vm.importActionSelected = true; vm.didUpdate(); vm.setData("Id,_foo*,__Status\r\n" + records[5].Id + ",foo,Queued\r\n" + records[6].Id + ",foo,Succeeded"); assertEquals({ Queued: 1, Processing: 0, Succeeded: 1, Failed: 0 }, vm.importCounts()); From 4b6e2a74ca41d7ddeece708df3db7adf2193c9a2 Mon Sep 17 00:00:00 2001 From: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> Date: Fri, 12 May 2023 14:32:50 +0200 Subject: [PATCH 21/21] Add toLabel function among suggested autocomplete options (#91) Fix #90 --- CHANGES.md | 1 + addon/data-export.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 531a28da..eccd850b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ Version 1.17 General ------- +* Add toLabel function among autocomplete query suggestions [feature 90](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/90) (idea by [Mickael Gudin](https://github.com/mickaelgudin)) * Update spinner on inspect page when loading or saving records and disable button [feature 69](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/69) (idea by [Camille Guillory](https://github.com/CamilleGuillory)) * Show "Copy Id" from Inspect page [feature 12](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/12) * Add a configuration option for links to open in a new tab [feature 78](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/78) (idea by [Henri Vilminko](https://github.com/hvilminko)) diff --git a/addon/data-export.js b/addon/data-export.js index 63534815..466a5c97 100644 --- a/addon/data-export.js +++ b/addon/data-export.js @@ -704,7 +704,7 @@ class Model { } }) .concat( - new Enumerable(["FIELDS(ALL)", "FIELDS(STANDARD)", "FIELDS(CUSTOM)", "AVG", "COUNT", "COUNT_DISTINCT", "MIN", "MAX", "SUM", "CALENDAR_MONTH", "CALENDAR_QUARTER", "CALENDAR_YEAR", "DAY_IN_MONTH", "DAY_IN_WEEK", "DAY_IN_YEAR", "DAY_ONLY", "FISCAL_MONTH", "FISCAL_QUARTER", "FISCAL_YEAR", "HOUR_IN_DAY", "WEEK_IN_MONTH", "WEEK_IN_YEAR", "convertTimezone"]) + new Enumerable(["FIELDS(ALL)", "FIELDS(STANDARD)", "FIELDS(CUSTOM)", "AVG", "COUNT", "COUNT_DISTINCT", "MIN", "MAX", "SUM", "CALENDAR_MONTH", "CALENDAR_QUARTER", "CALENDAR_YEAR", "DAY_IN_MONTH", "DAY_IN_WEEK", "DAY_IN_YEAR", "DAY_ONLY", "FISCAL_MONTH", "FISCAL_QUARTER", "FISCAL_YEAR", "HOUR_IN_DAY", "WEEK_IN_MONTH", "WEEK_IN_YEAR", "convertTimezone", "toLabel"]) .filter(fn => fn.toLowerCase().startsWith(searchTerm.toLowerCase())) .map(fn => { if (fn.includes(")")) { //Exception to easily support functions with hardcoded parameter options