From 886f75a44ecaec22ea7d3c53a5fe3644e9fa3938 Mon Sep 17 00:00:00 2001 From: olivier dufour Date: Wed, 27 Dec 2023 10:27:54 +0100 Subject: [PATCH] =?UTF-8?q?Automatically=20request=20SObject=20type=20when?= =?UTF-8?q?=20data=20export=20from=20an=20SObject=20r=E2=80=A6=20(#179)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ecord (#45) --------- Co-authored-by: Thomas Prouvot --- CHANGES.md | 1 + addon/data-import.js | 3 ++ addon/inspect.js | 4 +-- addon/popup.js | 66 ++++++++++++++++++++++++++++++++++---------- 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 327201c9..c3bfd0e8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Version 1.22 +- Automatically request SObject type for data import and SObject record id for data export [feature 45](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/45) SObject record (#45)) (contribution by [Olivier Dufour](https://github.com/dufoli)) - Add support to Hyperforce China Organizations [PR141](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/141) (contribution by [Yaacov Elbaz](https://github.com/yaacov9)) ## Version 1.21 diff --git a/addon/data-import.js b/addon/data-import.js index 85d7a7b3..081085c8 100644 --- a/addon/data-import.js +++ b/addon/data-import.js @@ -34,6 +34,9 @@ class Model { Succeeded: true, Failed: true }; + if (args.has("sobject")) { + this.importType = args.get("sobject"); + } if (localStorage.getItem(sfHost + "_isSandbox") != "true") { //change background color for production document.body.classList.add("prod"); diff --git a/addon/inspect.js b/addon/inspect.js index 49fb7e41..e4445537 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -236,9 +236,9 @@ class Model { if (!objectName) { return undefined; } - let query = "select Id from " + objectName; + let query = "SELECT Id FROM " + objectName; if (this.recordData && this.recordData.Id) { - query += " where Id = '" + this.recordData.Id + "'"; + query += " WHERE Id = '" + this.recordData.Id + "'"; } return this.dataExportUrl(query); } diff --git a/addon/popup.js b/addon/popup.js index cbc1e156..58050bad 100644 --- a/addon/popup.js +++ b/addon/popup.js @@ -52,15 +52,44 @@ function initLinks({sfHost}){ class App extends React.PureComponent { constructor(props) { super(props); + let {sfHost} = this.props; + let hostArg = new URLSearchParams(); + hostArg.set("host", sfHost); this.state = { isInSetup: false, contextUrl: null, apiVersionInput: apiVersion, - isFieldsPresent: false + isFieldsPresent: false, + exportHref: "data-export.html?" + hostArg, + importHref: "data-import.html?" + hostArg, + limitsHref: "limits.html?" + hostArg }; this.onContextUrlMessage = this.onContextUrlMessage.bind(this); this.onShortcutKey = this.onShortcutKey.bind(this); this.onChangeApi = this.onChangeApi.bind(this); + this.onContextRecordChange = this.onContextRecordChange.bind(this); + } + onContextRecordChange(e) { + let {sfHost} = this.props; + let limitsArg = new URLSearchParams(); + let exportArg = new URLSearchParams(); + let importArg = new URLSearchParams(); + exportArg.set("host", sfHost); + importArg.set("host", sfHost); + limitsArg.set("host", sfHost); + if (e.contextSobject) { + let query = "SELECT Id FROM " + e.contextSobject; + if (e.contextRecordId && (e.contextRecordId.length == 15 || e.contextRecordId.length == 18)) { + query += " WHERE Id = '" + e.contextRecordId + "'"; + } + exportArg.set("query", query); + importArg.set("sobject", e.contextSobject); + } + this.setState({ + exportHref: "data-export.html?" + exportArg, + importHref: "data-import.html?" + importArg, + limitsHref: "limits.html?" + limitsArg + }); } onContextUrlMessage(e) { if (e.source == parent && e.data.insextUpdateRecordId) { @@ -171,7 +200,7 @@ class App extends React.PureComponent { inInspector, addonVersion } = this.props; - let {isInSetup, contextUrl, apiVersionInput, isFieldsPresent} = this.state; + let {isInSetup, contextUrl, apiVersionInput, exportHref, importHref, limitsHref, isFieldsPresent} = this.state; let clientId = localStorage.getItem(sfHost + "_clientId"); let hostArg = new URLSearchParams(); hostArg.set("host", sfHost); @@ -198,16 +227,16 @@ class App extends React.PureComponent { ) ), h("div", {className: "main"}, - h(AllDataBox, {ref: "showAllDataBox", sfHost, showDetailsSupported: !inLightning && !inInspector, linkTarget, contextUrl, isFieldsPresent}), + h(AllDataBox, {ref: "showAllDataBox", sfHost, showDetailsSupported: !inLightning && !inInspector, linkTarget, contextUrl, onContextRecordChange: this.onContextRecordChange, isFieldsPresent}), h("div", {className: "slds-p-vertical_x-small slds-p-horizontal_x-small slds-border_bottom"}, h("div", {className: "slds-m-bottom_xx-small"}, - h("a", {ref: "dataExportBtn", href: "data-export.html?" + hostArg, target: linkTarget, className: "page-button slds-button slds-button_neutral"}, h("span", {}, "Data ", h("u", {}, "E"), "xport")) + h("a", {ref: "dataExportBtn", href: exportHref, target: linkTarget, className: "page-button slds-button slds-button_neutral"}, h("span", {}, "Data ", h("u", {}, "E"), "xport")) ), h("div", {className: "slds-m-bottom_xx-small"}, - h("a", {ref: "dataImportBtn", href: "data-import.html?" + hostArg, target: linkTarget, className: "page-button slds-button slds-button_neutral"}, h("span", {}, "Data ", h("u", {}, "I"), "mport")) + h("a", {ref: "dataImportBtn", href: importHref, target: linkTarget, className: "page-button slds-button slds-button_neutral"}, h("span", {}, "Data ", h("u", {}, "I"), "mport")) ), h("div", {}, - h("a", {ref: "limitsBtn", href: "limits.html?" + hostArg, target: linkTarget, className: "page-button slds-button slds-button_neutral"}, h("span", {}, "Org ", h("u", {}, "L"), "imits")) + h("a", {ref: "limitsBtn", href: limitsHref, target: linkTarget, className: "page-button slds-button slds-button_neutral"}, h("span", {}, "Org ", h("u", {}, "L"), "imits")) ), ), h("div", {className: "slds-p-vertical_x-small slds-p-horizontal_x-small"}, @@ -330,16 +359,18 @@ class AllDataBox extends React.PureComponent { } ensureKnownBrowserContext() { - let {contextUrl} = this.props; + let {contextUrl, onContextRecordChange} = this.props; if (contextUrl) { let recordId = getRecordId(contextUrl); let path = getSfPathFromUrl(contextUrl); let sobject = getSobject(contextUrl); - this.setState({ + let context = { contextRecordId: recordId, contextPath: path, contextSobject: sobject - }); + }; + this.setState(context); + onContextRecordChange(context); } } @@ -488,7 +519,7 @@ class AllDataBox extends React.PureComponent { render() { let {activeSearchAspect, sobjectsLoading, contextRecordId, contextSobject, contextUserId, contextOrgId, contextPath, sobjectsList} = this.state; - let {sfHost, showDetailsSupported, linkTarget, isFieldsPresent} = this.props; + let {sfHost, showDetailsSupported, linkTarget, onContextRecordChange, isFieldsPresent} = this.props; return ( h("div", {className: "slds-p-top_small slds-p-horizontal_x-small slds-p-bottom_x-small slds-border_bottom" + (this.isLoading() ? " loading " : "")}, @@ -499,7 +530,7 @@ class AllDataBox extends React.PureComponent { h("li", {ref: "orgTab", onClick: this.onAspectClick, "data-aspect": this.SearchAspectTypes.org, className: (activeSearchAspect == this.SearchAspectTypes.org) ? "active" : ""}, h("span", {}, "O", h("u", {}, "r"), "g")) ), (activeSearchAspect == this.SearchAspectTypes.sobject) - ? h(AllDataBoxSObject, {ref: "showAllDataBoxSObject", sfHost, showDetailsSupported, sobjectsList, sobjectsLoading, contextRecordId, contextSobject, linkTarget, isFieldsPresent}) + ? h(AllDataBoxSObject, {ref: "showAllDataBoxSObject", sfHost, showDetailsSupported, sobjectsList, sobjectsLoading, contextRecordId, contextSobject, linkTarget, onContextRecordChange, isFieldsPresent}) : (activeSearchAspect == this.SearchAspectTypes.users) ? h(AllDataBoxUsers, {ref: "showAllDataBoxUsers", sfHost, linkTarget, contextUserId, contextOrgId, contextPath, setIsLoading: (value) => { this.setIsLoading("usersBox", value); }}, "Users") : (activeSearchAspect == this.SearchAspectTypes.shortcuts) @@ -814,8 +845,12 @@ class AllDataBoxSObject extends React.PureComponent { } onDataSelect(value) { + let {onContextRecordChange} = this.props; this.setState({selectedValue: value}, () => { this.loadRecordIdDetails(); + if (value) { + onContextRecordChange({contextSobject: value.sobject.name, contextRecordId: value.recordId}); + } }); } @@ -1910,10 +1945,11 @@ function getRecordId(href) { function getSobject(href) { let url = new URL(href); - if (url.pathname && url.pathname.endsWith("/list")){ - let sobject = url.pathname.substring(0, url.pathname.lastIndexOf("/list")); - sobject = sobject.substring(sobject.lastIndexOf("/") + 1); - return sobject; + if (url.pathname) { + let match = url.pathname.match(/\/lightning\/[r|o]\/([a-zA-Z0-9_]+)\/[a-zA-Z0-9]+/); + if (match) { + return match[1]; + } } return null; }