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] [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); });