From ebb6a472113fa1d45c782c2974abaa2fbd01f9e6 Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Mon, 22 May 2023 16:37:18 +0200 Subject: [PATCH 1/9] add background, restyle table with sticky header, restyle footer --- addon/inspect.css | 67 ++++++++++++++++++++++++++++++++++++++--------- addon/inspect.js | 21 +++++++-------- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/addon/inspect.css b/addon/inspect.css index d298f38c..38cc41ae 100644 --- a/addon/inspect.css +++ b/addon/inspect.css @@ -65,6 +65,11 @@ body { font-family: "Salesforce Sans", Arial, sans-serif; font-size: .8125rem; margin: 0; + background-color: #B0C4DF; + background-image: url('chrome-extension://__MSG_@@extension_id__/images/lightning_blue_background.png'); + background-repeat: no-repeat; + background-size: contain; + background-position: 0px 48px; } a { @@ -101,7 +106,7 @@ a:hover { padding: 2px; color: white; padding-right: 1em; - margin-right: 20px; + margin-right: 4px; } .sf-link svg { @@ -119,6 +124,9 @@ a:hover { table { width: 100%; border-spacing: 0px; + position: relative; + text-align: left; + overflow: scroll; } .value-text { @@ -162,13 +170,32 @@ tr.fieldHidden a[href] { } tr:hover { - background-color: lightblue; + background-color: #f3f3f3; } th { text-align: left; } +textarea { + font: inherit; +} + +thead{ + top: 0; + position: sticky; + z-index: 1; +} + +.th-filter-row { + background-color: #FFFFFF; +} + +.field-label, .field-name, .field-column, .field-actions, .child-column, .child-actions { + border-bottom: 1px solid #DDDBDA; + padding: 1px 4px; +} + .field-label { white-space: nowrap; } @@ -247,9 +274,10 @@ th { } th[tabindex] { - text-decoration: underline; cursor: pointer; - color: darkblue; + font-weight: 700; + background: #eeeeee; + background-color: #eeeeee; } .column-filter-box { @@ -306,13 +334,14 @@ th[tabindex] { .filter-box { white-space: nowrap; - margin: 0 1rem; + margin: 0 0.5rem; position: relative; } .filter-input { + font: inherit; width: 20em; - padding: 0 3rem; + padding: 0 2.5rem; background-color: #fff; color: #16325c; border: 1px solid #d8dde6; @@ -332,7 +361,7 @@ th[tabindex] { } .filter-icon { - left: 1.25rem; + left: 0.75rem; width: 1rem; height: 1rem; position: absolute; @@ -342,7 +371,7 @@ th[tabindex] { } .filter-clear { - right: 1.25rem; + right: 0.75rem; width: 1rem; height: 1rem; position: absolute; @@ -387,8 +416,9 @@ th[tabindex] { width: 100%; display: flex; align-items: center; - padding: 0 1.5rem; + padding: 0 8px; flex-wrap: wrap; + border-bottom: 1px solid #d8dde6; } .object-tab { @@ -453,13 +483,15 @@ th[tabindex] { .object-name { flex: 1 1 0; - margin: 0 1em; + margin: 0 0.5em; font-size: 1.2em; font-weight: normal; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; position: relative; + display: flex; + justify-content: center; } .button { @@ -632,9 +664,12 @@ th[tabindex] { } .body { - padding: 8px; + margin: 6px; overflow: auto; flex: 1 1 0; + border-radius: 3px; + border: 1px solid #d8dde6; + background-color: #ffffff; } @keyframes spin { @@ -649,7 +684,15 @@ th[tabindex] { .edit-bar { text-align: center; - padding: 1rem 0; + padding: 4px; +} + +.footer-edit-bar { + display: flex; + padding: 4px; + border: 1px solid #d8dde6; + background-color: #f7f9fb;; + justify-content: flex-end; } .edit-bar .button { diff --git a/addon/inspect.js b/addon/inspect.js index ac6da7c1..1483ee84 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -1074,6 +1074,11 @@ class App extends React.Component { ] }) ), + h("div", { className: "object-name" }, + h("span", { className: "quick-select" }, model.objectName()), + " ", + model.recordHeading() + ), model.useTab != "all" ? null : h("div", { className: "filter-box" }, h("svg", { className: "filter-icon" }, h("use", { xlinkHref: "symbols.svg#search" }) @@ -1085,11 +1090,6 @@ class App extends React.Component { ) ) ), - h("h1", { className: "object-name" }, - h("span", { className: "quick-select" }, model.objectName()), - " ", - model.recordHeading() - ), 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", @@ -1131,14 +1131,13 @@ class App extends React.Component { 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 }, 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("div", { className: "footer-edit-bar" }, h("span", { className: "edit-bar" }, h("button", { title: model.editMode == "update" ? "Cancel editing this record" @@ -1162,7 +1161,7 @@ class App extends React.Component { : model.editMode == "delete" ? "Confirm delete" : model.editMode == "create" ? "Save new" : "???") - ) : null, + )) : null, model.detailsBox ? h(DetailsBox, { model }) : null ) ); @@ -1232,13 +1231,13 @@ class RowTable extends React.Component { selectedColumns.map(col => h(HeaderCell, { key: col.name, col, rowList }) ), - h("th", { className: actionsColumn.className }, "") + h("th", { className: actionsColumn.className, tabIndex: 0 }, "") ), rowList.model.useTab != "all" ? h("tr", {}, selectedColumns.map(col => h(FilterCell, { key: col.name, col, rowList }) ), - h("th", { className: actionsColumn.className }) + h("th", { className: actionsColumn.className + " " + "th-filter-row"}) ) : null ), h("tbody", {}, rowList.rows.map(row => @@ -1288,7 +1287,7 @@ class FilterCell extends React.Component { } render() { let { col } = this.props; - return h("th", { className: col.className }, + return h("th", { className: col.className + " " + "th-filter-row" }, h("input", { placeholder: "Filter", className: "column-filter-box", From 21fe2875f583ea91a09472e30d7ff9cbafd2d9dd Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Thu, 8 Jun 2023 16:54:20 +0200 Subject: [PATCH 2/9] align object name to the left (better UX with reactive components) --- addon/inspect.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon/inspect.css b/addon/inspect.css index 38cc41ae..3cc6a30d 100644 --- a/addon/inspect.css +++ b/addon/inspect.css @@ -483,7 +483,7 @@ th[tabindex] { .object-name { flex: 1 1 0; - margin: 0 0.5em; + margin: 0 1em; font-size: 1.2em; font-weight: normal; text-overflow: ellipsis; @@ -491,7 +491,7 @@ th[tabindex] { overflow: hidden; position: relative; display: flex; - justify-content: center; + justify-content: left; } .button { From ab2f951518c7081ec5b2687f4b04d782c6c384f0 Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Fri, 9 Jun 2023 11:56:38 +0200 Subject: [PATCH 3/9] adjust table margin --- addon/inspect.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/inspect.css b/addon/inspect.css index 3cc6a30d..8c19ae1e 100644 --- a/addon/inspect.css +++ b/addon/inspect.css @@ -664,7 +664,7 @@ th[tabindex] { } .body { - margin: 6px; + margin: 12px; overflow: auto; flex: 1 1 0; border-radius: 3px; From 7f827462d045ead2a999413d9f44e3875453d44d Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Fri, 9 Jun 2023 12:04:13 +0200 Subject: [PATCH 4/9] add prod background color --- addon/inspect.css | 9 +++++++-- addon/inspect.js | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/addon/inspect.css b/addon/inspect.css index 8c19ae1e..4909e173 100644 --- a/addon/inspect.css +++ b/addon/inspect.css @@ -48,6 +48,11 @@ body, height: 100%; } +.prod { + background-color: #e0a4b5; + background-image: url('chrome-extension://__MSG_@@extension_id__/images/lightning_red_background.png'); +} + [data-reactroot] { display: flex; flex-direction: column; @@ -663,7 +668,7 @@ th[tabindex] { background-color: #f4f6f9; } -.body { +.table-container { margin: 12px; overflow: auto; flex: 1 1 0; @@ -678,7 +683,7 @@ th[tabindex] { } } -.body.empty { +.table-container.empty { animation: spin 4s linear infinite; } diff --git a/addon/inspect.js b/addon/inspect.js index 1483ee84..cf0a4bac 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -35,6 +35,10 @@ class Model { this.objectActionsOpen = false; this.objectSetupLinks = null; this.objectSetupLinksRequested = false; + if (localStorage.getItem(sfHost + "_isSandbox") != "true") { + //change background color for production + document.body.classList.add("prod"); + } } /** * Notify React that we changed something, so it will rerender the view. @@ -1124,7 +1128,7 @@ class App extends React.Component { ) ) ), - h("div", { className: "body " + (model.fieldRows.selectedColumnMap.size < 2 && model.childRows.selectedColumnMap.size < 2 ? "empty " : "") }, + h("div", { className: "table-container " + (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, From 76d99dd4e8fb2749f91d7eac320822e92cf1d1a7 Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Fri, 9 Jun 2023 12:14:45 +0200 Subject: [PATCH 5/9] add padding to header container --- addon/inspect.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/inspect.css b/addon/inspect.css index 4909e173..c8a047ea 100644 --- a/addon/inspect.css +++ b/addon/inspect.css @@ -421,7 +421,7 @@ th[tabindex] { width: 100%; display: flex; align-items: center; - padding: 0 8px; + padding: 0 12px; flex-wrap: wrap; border-bottom: 1px solid #d8dde6; } From 71adaeafb1f523756d30896e26cb07a62bb53061 Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Mon, 12 Jun 2023 16:57:35 +0200 Subject: [PATCH 6/9] setting to conditionally show/hide table borders --- addon/images/settings.svg | 13 +++++++ addon/inspect.css | 25 +++++++++++- addon/inspect.js | 81 ++++++++++++++++++++++++++++++++------- 3 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 addon/images/settings.svg diff --git a/addon/images/settings.svg b/addon/images/settings.svg new file mode 100644 index 00000000..9b14d226 --- /dev/null +++ b/addon/images/settings.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/addon/inspect.css b/addon/inspect.css index c8a047ea..f816e2c5 100644 --- a/addon/inspect.css +++ b/addon/inspect.css @@ -197,10 +197,13 @@ thead{ } .field-label, .field-name, .field-column, .field-actions, .child-column, .child-actions { - border-bottom: 1px solid #DDDBDA; padding: 1px 4px; } +.border-cell { + border-bottom: 1px solid #DDDBDA; +} + .field-label { white-space: nowrap; } @@ -278,6 +281,26 @@ thead{ fill: #b0adab; } +.table-settings-button { + border: 0px solid transparent; + padding: 0px 3px 0px 0px; +} + +.table-settings-icon { + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: 1rem; + background-color: #706E6B; + display: inline-block; + width: 16px; + height: 16px; + -webkit-mask-image: url('chrome-extension://__MSG_@@extension_id__/images/settings.svg'); + margin: 3px 0px -3px 0px; +} + +.table-settings-link { + font-weight: normal; +} + th[tabindex] { cursor: pointer; font-weight: 700; diff --git a/addon/inspect.js b/addon/inspect.js index cf0a4bac..7049489b 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -26,6 +26,7 @@ class Model { this.errorMessages = []; this.rowsFilter = ""; this.useTab = "all"; + this.showTableBorder = localStorage.getItem("displayInspectTableBorders") == "true"; this.fieldRows = new FieldRowList(this); this.childRows = new ChildRowList(this); this.detailsFilter = ""; @@ -375,6 +376,16 @@ class Model { ); } + updateShowTableBorder() { + this.showTableBorder = !this.showTableBorder; + localStorage.setItem("displayInspectTableBorders", "true"); // Save to local storage + + } + reloadTables() { + this.fieldRows = new FieldRowList(this); + this.childRows = new ChildRowList(this); + this.startLoading(); + } } class RowList { @@ -461,6 +472,17 @@ class FieldRowList extends RowList { this.initColumns(["name", "label", "type"]); this.fetchFieldDescriptions = true; } + getColumnClassName(col) { + let className = this.model.showTableBorder ? "border-cell " : ""; + if (col == "name") { + className += "field-name"; + } else if (col == "label") { + className += "field-label"; + } else { + className += "field-column"; + } + return className; + } createColumn(col) { return { name: col, @@ -472,10 +494,7 @@ class FieldRowList extends RowList { : col == "helptext" ? "Help text" : col == "desc" ? "Description" : col, - className: - col == "name" ? "field-name" - : col == "label" ? "field-label" - : "field-column", + className: this.getColumnClassName(col), reactElement: col == "value" ? FieldValueCell : col == "type" ? FieldTypeCell @@ -515,7 +534,7 @@ class ChildRowList extends RowList { : col == "field" ? "Field" : col == "label" ? "Label" : col, - className: "child-column", + className: "child-column" + (this.model.showTableBorder ? " border-cell" : ""), reactElement: col == "object" ? ChildObjectCell : DefaultCell, columnFilter: "" }; @@ -949,6 +968,7 @@ class App extends React.Component { this.onDoCreate = this.onDoCreate.bind(this); this.onDoSave = this.onDoSave.bind(this); this.onCancelEdit = this.onCancelEdit.bind(this); + this.onUpdateTableBorderSettings = this.onUpdateTableBorderSettings.bind(this); } componentDidMount() { this.refs.rowsFilter.focus(); @@ -1027,6 +1047,13 @@ class App extends React.Component { model.cancelEdit(); model.didUpdate(); } + onUpdateTableBorderSettings() { + let { model } = this.props; + model.updateShowTableBorder(); + model.reloadTables(); + model.didUpdate(); + // Save to local storage + } render() { let { model } = this.props; document.title = model.title(); @@ -1131,14 +1158,18 @@ class App extends React.Component { h("div", { className: "table-container " + (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, { + model, rowList: model.fieldRows, - actionsColumn: { className: "field-actions", reactElement: FieldActionsCell }, - classNameForRow: row => (row.fieldIsCalculated() ? "fieldCalculated " : "") + (row.fieldIsHidden() ? "fieldHidden " : "") + actionsColumn: { className: "field-actions" + (model.showTableBorder ? " border-cell" : ""), reactElement: FieldActionsCell }, + classNameForRow: row => (row.fieldIsCalculated() ? "fieldCalculated " : "") + (row.fieldIsHidden() ? "fieldHidden " : ""), + onUpdateTableBorderSettings: this.onUpdateTableBorderSettings }) : null, model.useTab == "all" || model.useTab == "childs" ? h(RowTable, { + model, rowList: model.childRows, - actionsColumn: { className: "child-actions", reactElement: ChildActionsCell }, - classNameForRow: () => "" + actionsColumn: { className: "child-actions" + (model.showTableBorder ? " border-cell" : ""), reactElement: ChildActionsCell }, + classNameForRow: () => "", + onUpdateTableBorderSettings: this.onUpdateTableBorderSettings }) : null ), model.editMode != null && (model.useTab == "all" || model.useTab == "fields") ? h("div", { className: "footer-edit-bar" }, h("span", { className: "edit-bar" }, @@ -1226,6 +1257,21 @@ class ColumnVisibiltyToggle extends React.Component { } class RowTable extends React.Component { + constructor(props) { + super(props); + this.onToggleTableSettings = this.onToggleTableSettings.bind(this); + this.onClickTableBorderSettings = this.onClickTableBorderSettings.bind(this); + this.showTableBorder = this.props.model.showTableBorder; + this.tableSettingsOpen = false; + } + onToggleTableSettings() { + this.tableSettingsOpen = !this.tableSettingsOpen; + this.props.model.didUpdate(); + } + onClickTableBorderSettings() { + this.props.onUpdateTableBorderSettings(); + this.tableSettingsOpen = false; + } render() { let { rowList, actionsColumn, classNameForRow } = this.props; let selectedColumns = Array.from(rowList.selectedColumnMap.values()); @@ -1235,7 +1281,16 @@ class RowTable extends React.Component { selectedColumns.map(col => h(HeaderCell, { key: col.name, col, rowList }) ), - h("th", { className: actionsColumn.className, tabIndex: 0 }, "") + h("th", { className: actionsColumn.className, tabIndex: 0 }, + h("button", { className: "table-settings-button", onClick: this.onToggleTableSettings }, + h("div", { className: "table-settings-icon" }) + ), + this.tableSettingsOpen && h("div", { className: "pop-menu-container" }, + h("div", { className: "pop-menu" }, + h("a", { className: "table-settings-link", onClick: this.onClickTableBorderSettings }, "Show / Hide table borders"), + ) + ), + ), ), rowList.model.useTab != "all" ? h("tr", {}, selectedColumns.map(col => @@ -1249,7 +1304,7 @@ class RowTable extends React.Component { selectedColumns.map(col => h(col.reactElement, { key: col.name, row, col }) ), - h(actionsColumn.reactElement, { row }) + h(actionsColumn.reactElement, { className: actionsColumn.className, row }) ) )) ); @@ -1430,8 +1485,8 @@ class FieldActionsCell extends React.Component { row.rowList.model.didUpdate(); } render() { - let { row } = this.props; - return h("td", { className: "field-actions" }, + let { row, className } = this.props; + return h("td", { className }, h("div", { className: "pop-menu-container" }, h("button", { className: "actions-button", onClick: this.onToggleFieldActions }, h("svg", { className: "actions-icon" }, From 6b85858213e66ad9a9cf0a06a1997ef97302d71d Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Thu, 22 Jun 2023 12:45:49 +0200 Subject: [PATCH 7/9] Update addon/inspect.js Co-authored-by: Thomas Prouvot <35368290+tprouvot@users.noreply.github.com> --- addon/inspect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/inspect.js b/addon/inspect.js index 7049489b..b981cce0 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -378,7 +378,7 @@ class Model { } updateShowTableBorder() { this.showTableBorder = !this.showTableBorder; - localStorage.setItem("displayInspectTableBorders", "true"); // Save to local storage + localStorage.setItem("displayInspectTableBorders", this.showTableBorder); // Save to local storage } reloadTables() { From 9669c2b008805e0f718aa94f49b316b3c2be5bc4 Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Fri, 7 Jul 2023 15:31:20 +0200 Subject: [PATCH 8/9] update changes.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 402b1af4..5b5fb7e2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ Version 1.19 General ------- +* Inspect Page Restyling [PR105](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/105) (contribution by [Pietro Martino](https://github.com/pietromartino)) * Fix country codes from LocalSidKey convention [PR117](https://github.com/tprouvot/Salesforce-Inspector-reloaded/pull/117) (contribution by [Luca Bassani](https://github.com/baslu93)) * Use custom shortcuts [feature 115](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/115) * Add Export Query button [feature 109](https://github.com/tprouvot/Salesforce-Inspector-reloaded/issues/109) (idea by [Ryan Sherry](https://github.com/rpsherry-starburst)) From a196f3b536f45f96894ee0b2e0c38ef371413cee Mon Sep 17 00:00:00 2001 From: Pietro Martino Date: Fri, 7 Jul 2023 15:44:50 +0200 Subject: [PATCH 9/9] fix no border in relationship table actions col --- addon/inspect.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon/inspect.js b/addon/inspect.js index b981cce0..77918d52 100644 --- a/addon/inspect.js +++ b/addon/inspect.js @@ -1521,8 +1521,8 @@ class ChildActionsCell extends React.Component { row.rowList.model.didUpdate(); } render() { - let { row } = this.props; - return h("td", { className: "child-actions" }, + let { row, className } = this.props; + return h("td", { className }, h("div", { className: "pop-menu-container" }, h("button", { className: "actions-button", onClick: this.onToggleChildActions }, h("svg", { className: "actions-icon" },