mirror of
				https://github.com/gristlabs/grist-core.git
				synced 2025-06-13 20:53:59 +00:00 
			
		
		
		
	(core) Improve highlighting of previewed formula
Summary: Also improves highlighting of columns when the "Click to insert" tooltip is shown, and improves highlighting of transforming columns. Test Plan: Manual. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D3962
This commit is contained in:
		
							parent
							
								
									5a703a1972
								
							
						
					
					
						commit
						beffd02c41
					
				| @ -346,23 +346,23 @@ | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* Column hover effect */ | ||||
| /* Highlight the entire column when the "Click to insert" tooltip is shown. */ | ||||
| .column_name.hover-column > .selection, | ||||
| .column_name.hover-column.selected > .selection, | ||||
| .gridview_row .field.hover-column > .selection { | ||||
|   background-color: var(--grist-theme-selection, var(--grist-color-selection)); | ||||
|   inset: 0; | ||||
|   position: absolute; | ||||
| } | ||||
| 
 | ||||
| .gridview_row .field.hover-column, /* normal field in a row */ | ||||
| .gridview_row .field.hover-column .field_clip, | ||||
| .column_name.hover-column, /* column name */ | ||||
| .column_name.hover-column.selected, /* selected column name */ | ||||
| .gridview_row .field.frozen.hover-column /* frozen field in a row */ { | ||||
|   /* for frozen fields can't use alpha channel */ | ||||
|   background-color: var(--grist-theme-selection-opaque-bg, var(--grist-color-selection-opaque)); | ||||
|   color: var(--grist-theme-selection-opaque-fg, unset); | ||||
| /* Use a darker highlight if the column is being transformed. */ | ||||
| .gridview_row .field.transform_field.hover-column > .selection { | ||||
|   background-color: var(--grist-theme-selection-darkest, rgba(22,179,120,0.35)); | ||||
|   inset: 0; | ||||
|   position: absolute; | ||||
| } | ||||
| /* For zebra stripes, make the selection little darker */ | ||||
| .record-zebra.record-even .field.hover-column { | ||||
|   background-color: var(--grist-theme-selection-opaque-dark-bg, var(--grist-color-selection-darker-opaque)); | ||||
|   color: var(--grist-theme-selection-opaque-fg, unset); | ||||
| } | ||||
| /* When column has a hover, remove menu button. */ | ||||
| 
 | ||||
| /* And hide the column menu button. */ | ||||
| .column_name.hover-column .menu_toggle { | ||||
|   visibility: hidden; | ||||
| } | ||||
|  | ||||
| @ -1139,7 +1139,8 @@ GridView.prototype.buildDom = function() { | ||||
|                   }, | ||||
|                   menu(ctl => this.columnContextMenu(ctl, this.getSelection(), field, filterTriggerCtl)), | ||||
|                   testId('column-menu-trigger'), | ||||
|                 ) | ||||
|                 ), | ||||
|                 dom('div.selection'), | ||||
|               ); | ||||
|             }), | ||||
|             this.isPreview ? null : kd.maybe(() => !this.gristDoc.isReadonlyKo(), () => ( | ||||
| @ -1346,7 +1347,7 @@ GridView.prototype.buildDom = function() { | ||||
| 
 | ||||
|             kd.toggleClass('selected', isSelected), | ||||
|             fieldBuilder.buildDomWithCursor(row, isCellActive, isCellSelected), | ||||
|             dom('div.field_selection') | ||||
|             dom('div.selection'), | ||||
|           ); | ||||
|         }) | ||||
|       ) | ||||
|  | ||||
| @ -110,13 +110,20 @@ | ||||
|   color: var(--grist-actual-cell-color, unset); | ||||
| } | ||||
| 
 | ||||
| .field.selected > .field_selection { | ||||
| .gridview_row .field.selected > .selection { | ||||
|   background-color: var(--grist-theme-selection, var(--grist-color-selection)); | ||||
|   position: absolute; | ||||
|   inset: 0; | ||||
|   pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .field.transform_field > .selection { | ||||
|   background-color: var(--grist-theme-selection-darker, rgba(22,179,120,0.25)); | ||||
|   position: absolute; | ||||
|   inset: 0; | ||||
|   pointer-events: none; | ||||
| } | ||||
| 
 | ||||
| .field_clip.invalid, .field_clip.field-error-from-style { | ||||
|   background-color: #ffb6c1; | ||||
|   color: black; | ||||
| @ -126,6 +133,10 @@ | ||||
|   background-color: unset; | ||||
| } | ||||
| 
 | ||||
| .field.transform_field > .field_clip.invalid + .selection { | ||||
|   background-color: unset; | ||||
| } | ||||
| 
 | ||||
| .field_clip.field-error-P { | ||||
|   color: #B0B0B0; | ||||
|   background-color: unset; | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import {ColumnRec, DocModel} from 'app/client/models/DocModel'; | ||||
| import {Style} from 'app/client/models/Styles'; | ||||
| import * as modelUtil from 'app/client/models/modelUtil'; | ||||
| import {GristObjCode} from 'app/plugin/GristData'; | ||||
| 
 | ||||
| export interface RuleOwner { | ||||
|   // Field or Section can have a list of conditional styling rules. Each style is a combination of a formula and options
 | ||||
| @ -9,6 +10,8 @@ export interface RuleOwner { | ||||
|   tableId: ko.Computed<string>; | ||||
|   // If this field (or column) has a list of conditional styling rules.
 | ||||
|   hasRules: ko.Computed<boolean>; | ||||
|   // List of rules.
 | ||||
|   rulesList: ko.Computed<[GristObjCode.List, ...number[]] | null>; | ||||
|   // List of columns that are used as rules for conditional styles.
 | ||||
|   rulesCols: ko.Computed<ColumnRec[]>; | ||||
|   // List of columns ids that are used as rules for conditional styles.
 | ||||
|  | ||||
| @ -253,6 +253,7 @@ export function createViewFieldRec(this: ViewFieldRec, docModel: DocModel): void | ||||
|   }); | ||||
| 
 | ||||
|   this.tableId = ko.pureComputed(() => this.column().table().tableId()); | ||||
|   this.rulesList = ko.pureComputed(() => this._fieldOrColumn().rules()); | ||||
|   this.rulesCols = refListRecords(docModel.columns, ko.pureComputed(() => this._fieldOrColumn().rules())); | ||||
|   this.rulesColsIds = ko.pureComputed(() => this.rulesCols().map(c => c.colId())); | ||||
|   this.rulesStyles = modelUtil.fieldWithDefault( | ||||
|  | ||||
| @ -337,6 +337,8 @@ export const theme = { | ||||
| 
 | ||||
|   /* Selection */ | ||||
|   selection: new CustomProp('theme-selection', undefined, colors.selection), | ||||
|   selectionDarker: new CustomProp('theme-selection-darker', undefined, 'rgba(22,179,120,0.25)'), | ||||
|   selectionDarkest: new CustomProp('theme-selection-darkest', undefined, 'rgba(22,179,120,0.35)'), | ||||
|   selectionOpaqueFg: new CustomProp('theme-selection-opaque-fg', undefined, 'unset'), | ||||
|   selectionOpaqueBg: new CustomProp('theme-selection-opaque-bg', undefined, | ||||
|     colors.selectionOpaque), | ||||
|  | ||||
| @ -56,6 +56,8 @@ export class FormulaAssistant extends Disposable { | ||||
|   private _waiting = Observable.create(this, false); | ||||
|   /** Is this feature enabled at all */ | ||||
|   private _assistantEnabled: Computed<boolean>; | ||||
|   /** Preview column ref */ | ||||
|   private _transformColRef: string; | ||||
|   /** Preview column id */ | ||||
|   private _transformColId: string; | ||||
|   /** Method to invoke when we are closed, it saves or reverts */ | ||||
| @ -136,14 +138,20 @@ export class FormulaAssistant extends Disposable { | ||||
|       description: 'Formula Editor', | ||||
|       prepare: () => this._preparePreview(), | ||||
|       finalize: () => this._cleanupPreview(), | ||||
|       shouldIncludeInBundle: (a) => { | ||||
|         const tableId = this._options.column.table.peek().tableId.peek(); | ||||
|         const allowed = a.length === 1 | ||||
|           && a[0][0] === 'ModifyColumn' | ||||
|           && a[0][1] === tableId | ||||
|           && typeof a[0][2] === 'string' | ||||
|           && [this._transformColId, this._options.column.id.peek()].includes(a[0][2]); | ||||
|         return allowed; | ||||
|       shouldIncludeInBundle: (actions) => { | ||||
|         if (actions.length !== 1) { return false; } | ||||
| 
 | ||||
|         const actionName = actions[0][0]; | ||||
|         if (actionName === 'ModifyColumn') { | ||||
|           const tableId = this._options.column.table.peek().tableId.peek(); | ||||
|           return actions[0][1] === tableId | ||||
|             && typeof actions[0][2] === 'string' | ||||
|             && [this._transformColId, this._options.column.id.peek()].includes(actions[0][2]); | ||||
|         } else if (actionName === 'UpdateRecord') { | ||||
|           return actions[0][1] === '_grist_Tables_column' && actions[0][2] === this._transformColRef; | ||||
|         } else { | ||||
|           return false; | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
| 
 | ||||
| @ -342,14 +350,25 @@ export class FormulaAssistant extends Disposable { | ||||
|     const tableId = this._options.column.table.peek().tableId.peek(); | ||||
| 
 | ||||
|     // Add a new column to the table, and set it as the transform column.
 | ||||
|     const colInfo = await docData.sendAction(['AddColumn', tableId, 'gristHelper_Transform', { | ||||
|     const {colRef, colId} = await docData.sendAction(['AddColumn', tableId, 'gristHelper_Transform', { | ||||
|       type: this._options.column.type.peek(), | ||||
|       label: this._options.column.colId.peek(), | ||||
|       isFormula: true, | ||||
|       formula: this._options.column.formula.peek(), | ||||
|       widgetOptions: JSON.stringify(this._options.field?.widgetOptionsJson()), | ||||
|     }]); | ||||
|     this._options.field?.colRef(colInfo.colRef); // Don't save, it is only in browser.
 | ||||
|     this._transformColId = colInfo.colId; | ||||
| 
 | ||||
|     this._transformColRef = colRef; | ||||
|     this._transformColId = colId; | ||||
| 
 | ||||
|     const rules = this._options.field?.rulesList(); | ||||
|     if (rules) { | ||||
|       await docData.sendAction(['UpdateRecord', '_grist_Tables_column', colRef, { | ||||
|         rules: this._options.field?.rulesList(), | ||||
|       }]); | ||||
|     } | ||||
| 
 | ||||
|     this._options.field?.colRef(colRef); // Don't save, it is only in browser.
 | ||||
| 
 | ||||
|     // Update the transform column so that it points to the original column.
 | ||||
|     const transformColumn = this._options.field?.column.peek(); | ||||
|  | ||||
| @ -1,10 +1,6 @@ | ||||
| .record-add .field_clip { | ||||
|   background-color: var(--grist-theme-table-add-new-bg, inherit); | ||||
| } | ||||
| .transform_field { | ||||
|   color: black; | ||||
|   background-color: #FEFFE8; | ||||
| } | ||||
| 
 | ||||
| @media not print { | ||||
|   .formula_field, .formula_field_edit { | ||||
|  | ||||
| @ -132,6 +132,8 @@ export const ThemeColors = t.iface([], { | ||||
|   "card-list-form-border": "string", | ||||
|   "card-list-blocks-border": "string", | ||||
|   "selection": "string", | ||||
|   "selection-darker": "string", | ||||
|   "selection-darkest": "string", | ||||
|   "selection-opaque-fg": "string", | ||||
|   "selection-opaque-bg": "string", | ||||
|   "selection-opaque-dark-bg": "string", | ||||
|  | ||||
| @ -168,6 +168,8 @@ export interface ThemeColors { | ||||
| 
 | ||||
|   /* Selection */ | ||||
|   'selection': string; | ||||
|   'selection-darker': string; | ||||
|   'selection-darkest': string; | ||||
|   'selection-opaque-fg': string; | ||||
|   'selection-opaque-bg': string; | ||||
|   'selection-opaque-dark-bg': string; | ||||
|  | ||||
| @ -147,6 +147,8 @@ export const GristDark: ThemeColors = { | ||||
| 
 | ||||
|   /* Selection */ | ||||
|   'selection': 'rgba(22,179,120,0.15)', | ||||
|   'selection-darker': 'rgba(22,179,120,0.25)', | ||||
|   'selection-darkest': 'rgba(22,179,120,0.35)', | ||||
|   'selection-opaque-fg': 'white', | ||||
|   'selection-opaque-bg': '#2F4748', | ||||
|   'selection-opaque-dark-bg': '#253E3E', | ||||
|  | ||||
| @ -147,6 +147,8 @@ export const GristLight: ThemeColors = { | ||||
| 
 | ||||
|   /* Selection */ | ||||
|   'selection': 'rgba(22,179,120,0.15)', | ||||
|   'selection-darker': 'rgba(22,179,120,0.25)', | ||||
|   'selection-darkest': 'rgba(22,179,120,0.35)', | ||||
|   'selection-opaque-fg': 'black', | ||||
|   'selection-opaque-bg': '#DCF4EB', | ||||
|   'selection-opaque-dark-bg': '#D6EEE5', | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user