diff --git a/app/client/components/GridView.js b/app/client/components/GridView.js index f64f27a0a8..2ec5367d13 100644 --- a/app/client/components/GridView.js +++ b/app/client/components/GridView.js @@ -1150,6 +1150,7 @@ GridView.prototype.buildDom = function() { let vHorizontalGridlines = v.optionsObj.prop('horizontalGridlines'); let vVerticalGridlines = v.optionsObj.prop('verticalGridlines'); let vZebraStripes = v.optionsObj.prop('zebraStripes'); + let vFormulaIcon = v.optionsObj.prop('formulaIcon'); var renameCommands = { nextField: function() { @@ -1559,8 +1560,12 @@ GridView.prototype.buildDom = function() { //a cell in that row becomes larger kd.style('borderRightWidth', v.borderWidthPx), kd.toggleClass('selected', isSelected), - // Optional icon. Currently only use to show formula icon. - dom('div.field-icon'), + // The field-icon is presently only used for "=" in formula fields. + // The record-icon class isolates the "=" being applied to the formula fields. + // Allowing additional field icons to be added as field-icon class if desired. + dom('div.field-icon', + kd.toggleClass('record-icon', vFormulaIcon), // Also grabbed from v.optionsObj at start of GridView buildDom + ), fieldBuilder.buildDomWithCursor(row, isCellActive, isCellSelected), dom('div.selection'), ); diff --git a/app/client/models/entities/ViewSectionRec.ts b/app/client/models/entities/ViewSectionRec.ts index 714b4a3c16..4f9fd5d905 100644 --- a/app/client/models/entities/ViewSectionRec.ts +++ b/app/client/models/entities/ViewSectionRec.ts @@ -398,6 +398,7 @@ export function createViewSectionRec(this: ViewSectionRec, docModel: DocModel): const defaultOptions = { verticalGridlines: true, horizontalGridlines: true, + formulaIcon: true, // formula icons are enable by default consistent with the default app behaviour zebraStripes: false, customView: '', numFrozen: 0 diff --git a/app/client/ui/GridOptions.ts b/app/client/ui/GridOptions.ts index 2afc118027..49ae427cee 100644 --- a/app/client/ui/GridOptions.ts +++ b/app/client/ui/GridOptions.ts @@ -34,6 +34,12 @@ export class GridOptions extends Disposable { testId('h-grid-button') ), + cssRow( + checkbox(setSaveValueFromKo(this, section.optionsObj.prop('formulaIcon'))), + t("Formula Icons"), + testId('formula-icon-button'), + ), + cssRow( checkbox(setSaveValueFromKo(this, section.optionsObj.prop('zebraStripes'))), t("Zebra Stripes"), diff --git a/app/client/widgets/TextBox.css b/app/client/widgets/TextBox.css index 9229805a7c..112baf3987 100644 --- a/app/client/widgets/TextBox.css +++ b/app/client/widgets/TextBox.css @@ -3,15 +3,19 @@ } @media not print { - .formula_field, .formula_field_edit { + .formula_field:has(.record-icon), + .formula_field_edit:has(> .record-icon), + .g_record_detail_value.formula_field:has(> .field-icon) { padding-left: 18px; } .formula_field_edit { color: #D0D0D0; } - .formula_field .field-icon, - .formula_field_edit::before, + .formula_field .record-icon, + .g_record_detail_value.formula_field .field-icon, + .formula_field_edit:has(> .record-icon)::before, + .formula_editor.formula_field_edit::before, .formula_field_sidepane::before { /* based on standard icon styles */ content: ""; @@ -30,9 +34,11 @@ cursor: pointer; } + .g_record_detail_value.formula_field .field-icon, .formula_field .field-icon, .formula_field_edit::before { background-color: #D0D0D0; } + .transform_field.formula_field > .field-icon, .formula_field_edit:not(.readonly)::before { background-color: var(--grist-color-cursor); } diff --git a/test/nbrowser/GridOptions.ntest.js b/test/nbrowser/GridOptions.ntest.js index 1e3045b7fc..37ac938d00 100644 --- a/test/nbrowser/GridOptions.ntest.js +++ b/test/nbrowser/GridOptions.ntest.js @@ -19,9 +19,9 @@ describe("GridOptions.ntest", function() { /* Test that styles on the given section match the specified flags * sec: index into secNames - * hor/vert/zebra: boolean flags + * hor/vert/icon/zebra: boolean flags */ - async function assertHVZ(sec, hor, vert, zebra) { + async function assertHVCZ(sec, hor, vert, icon, zebra) { let testClasses = ['record-hlines', 'record-vlines', 'record-zebra']; let flags = [hor, vert, zebra]; @@ -33,6 +33,11 @@ describe("GridOptions.ntest", function() { if(flags[i]) { assert.include(rowClasses, cls);} else { assert.notInclude(rowClasses, cls); } }); + // Check for the presence of 'record-icon' class on the div.field-icon element + const fieldIcon = await row.find('.field-icon'); + const iconClasses = await fieldIcon.classList(); + if (icon) { assert.include(iconClasses, 'record-icon'); } + else { assert.notInclude(iconClasses, 'record-icon'); } } @@ -84,10 +89,11 @@ describe("GridOptions.ntest", function() { // get handles on elements let h = ".test-h-grid-button input"; let v = ".test-v-grid-button input"; + let c = ".test-formula-icon-button input"; let z = ".test-zebra-stripe-button input"; // should start with v+h gridlines, no zebra - await assertHVZ(0, true, true, false); + await assertHVCZ(0, true, true, true, false); // change values on all the sections await switchTo(0); @@ -96,24 +102,26 @@ describe("GridOptions.ntest", function() { await switchTo(1); await $(h).click(); await $(v).click(); + await $(c).click(); await switchTo(2); await $(h).click(); // turn off + await $(c).click(); // turn off await $(z).click(); // turn on await gu.waitForServer(); - await assertHVZ(0, true, true, true); // all on - await assertHVZ(1, false, false, false); // all off - await assertHVZ(2, false, true, true); // -h +v +z + await assertHVCZ(0, true, true, true, true); // all on + await assertHVCZ(1, false, false, false, false); // all off + await assertHVCZ(2, false, true, false, true); // -h +v -c +z // ensure that values persist after reload await driver.navigate().refresh(); //await $.injectIntoPage(); await gu.waitForDocToLoad(); await gu.hideBanners(); - await assertHVZ(0, true, true, true); // all on - await assertHVZ(1, false, false, false); // all off - await assertHVZ(2, false, true, true); // -h +v +z + await assertHVCZ(0, true, true, true, true); // all on + await assertHVCZ(1, false, false, false, false); // all off + await assertHVCZ(2, false, true, false, true); // -h +v -c +z });