mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Better UX in full-edit mode for the formula editor
Summary: Improving UX for the formula editor - Formula editor will go into full edit mode only on formula change (not on a mouse click) - Adding column highlight and a tooltip when in full edit mode Test Plan: nbrowser tests Reviewers: cyprien Reviewed By: cyprien Differential Revision: https://phab.getgrist.com/D3194
This commit is contained in:
parent
e99cc3ae08
commit
0482c83771
@ -42,7 +42,6 @@
|
||||
}
|
||||
|
||||
.gridview_data_header {
|
||||
border-bottom: 1px solid lightgray;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
@ -52,8 +51,9 @@
|
||||
}
|
||||
|
||||
.field.column_name {
|
||||
border-bottom: 1px solid lightgray;
|
||||
line-height: var(--gridview-header-height);
|
||||
height: var(--gridview-header-height); /* Also should match height for overlay elements */
|
||||
height: calc(var(--gridview-header-height) + 1px); /* Also should match height for overlay elements */
|
||||
}
|
||||
|
||||
/* also .field.column_name, style set in viewCommon */
|
||||
@ -350,6 +350,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Column hover effect */
|
||||
|
||||
.gridview_row .field.hover-column, /* normal field in a row */
|
||||
.gridview_row .field.frozen.hover-column, /* frozen field in a row */
|
||||
.column_name.hover-column, /* column name */
|
||||
.column_name.hover-column.selected /* selected column name */ {
|
||||
/* for frozen fields can't use alpha channel */
|
||||
background-color: var(--grist-color-selection-opaque);
|
||||
}
|
||||
/* For zebra stripes, make the selection little darker */
|
||||
.record-zebra.record-even .field.hover-column {
|
||||
background-color: var(--grist-color-selection-darker-opaque);
|
||||
}
|
||||
/* When column has a hover, remove menu button. */
|
||||
.column_name.hover-column .menu_toggle {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Etc */
|
||||
|
||||
.g-column-main-menu {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
var _ = require('underscore');
|
||||
var ko = require('knockout');
|
||||
const debounce = require('lodash/debounce');
|
||||
|
||||
var gutil = require('app/common/gutil');
|
||||
var BinaryIndexedTree = require('app/common/BinaryIndexedTree');
|
||||
@ -36,6 +37,7 @@ const {RowContextMenu} = require('../ui/RowContextMenu');
|
||||
const {setPopupToCreateDom} = require('popweasel');
|
||||
const {testId} = require('app/client/ui2018/cssVars');
|
||||
const {menuToggle} = require('app/client/ui/MenuToggle');
|
||||
const {showTooltip} = require('app/client/ui/tooltips');
|
||||
|
||||
|
||||
// A threshold for interpreting a motionless click as a click rather than a drag.
|
||||
@ -187,6 +189,20 @@ function GridView(gristDoc, viewSectionModel, isPreview = false) {
|
||||
return ko.pureComputed(() => field._index() < this.numFrozen());
|
||||
}, this));
|
||||
|
||||
// Holds column index that is hovered, works only in full-edit formula mode.
|
||||
this.hoverColumn = this.autoDispose(ko.observable(-1));
|
||||
// Debounced method to change current hover column, this is needed
|
||||
// as mouse when moved from field to field will switch the hover-column
|
||||
// observable from current index to -1 and then immediately back to current index.
|
||||
// With debounced version, call to set -1 that is followed by call to set back to the field index
|
||||
// will be discarded.
|
||||
this.changeHover = debounce((index) => {
|
||||
if (this.isDisposed()) { return; }
|
||||
if (this.gristDoc.docModel.editingFormula()) {
|
||||
this.hoverColumn(index);
|
||||
}
|
||||
}, 0);
|
||||
|
||||
//--------------------------------------------------
|
||||
// Create and attach the DOM for the view.
|
||||
|
||||
@ -852,7 +868,10 @@ GridView.prototype.buildDom = function() {
|
||||
dom('div.gridview_left_border'), //these hide behind the actual headers to keep them from flashing
|
||||
// left shadow that will be visible on top of frozen columns
|
||||
dom('div.scroll_shadow_frozen', kd.show(this.frozenShadow)),
|
||||
|
||||
// When cursor leaves the GridView, remove hover immediately (without debounce).
|
||||
// This guards mouse leaving gridView from the top, as leaving from bottom or left, right, is
|
||||
// guarded on the row level.
|
||||
dom.on("mouseleave", () => !this.isDisposed() && this.hoverColumn(-1)),
|
||||
// Drag indicators
|
||||
self.colLine = dom(
|
||||
'div.col_indicator_line',
|
||||
@ -900,12 +919,30 @@ GridView.prototype.buildDom = function() {
|
||||
write: val => editIndex(val ? field._index() : -1)
|
||||
}).extend({ rateLimit: 0 });
|
||||
let filterTriggerCtl;
|
||||
const isTooltip = ko.pureComputed(() =>
|
||||
self.gristDoc.docModel.editingFormula() &&
|
||||
ko.unwrap(self.hoverColumn) === field._index());
|
||||
return dom(
|
||||
'div.column_name.field',
|
||||
kd.style('--frozen-position', () => ko.unwrap(this.frozenPositions.at(field._index()))),
|
||||
kd.toggleClass("frozen", () => ko.unwrap(this.frozenMap.at(field._index()))),
|
||||
kd.toggleClass("hover-column", isTooltip),
|
||||
dom.autoDispose(isEditingLabel),
|
||||
dom.autoDispose(isTooltip),
|
||||
dom.testId("GridView_columnLabel"),
|
||||
(el) => {
|
||||
const tooltip = new HoverColumnTooltip(el);
|
||||
return [
|
||||
dom.autoDispose(tooltip),
|
||||
dom.autoDispose(isTooltip.subscribe((show) => {
|
||||
if (show) {
|
||||
tooltip.show(`Click to insert $${field.colId.peek()}`);
|
||||
} else {
|
||||
tooltip.hide();
|
||||
}
|
||||
})),
|
||||
]
|
||||
},
|
||||
kd.style('width', field.widthPx),
|
||||
kd.style('borderRightWidth', v.borderWidthPx),
|
||||
viewCommon.makeResizable(field.width, {shouldSave: !this.gristDoc.isReadonly.get()}),
|
||||
@ -920,6 +957,8 @@ GridView.prototype.buildDom = function() {
|
||||
kf.editableLabel(self.isPreview ? field.label : field.displayLabel, isEditingLabel, renameCommands),
|
||||
dom.on('mousedown', ev => isEditingLabel() ? ev.stopPropagation() : true)
|
||||
),
|
||||
dom.on("mouseenter", () => self.changeHover(field._index())),
|
||||
dom.on("mouseleave", () => self.changeHover(-1)),
|
||||
self.isPreview ? null : menuToggle(null,
|
||||
kd.cssClass('g-column-main-menu'),
|
||||
kd.cssClass('g-column-menu-btn'),
|
||||
@ -1043,7 +1082,12 @@ GridView.prototype.buildDom = function() {
|
||||
kd.toggleClass('record-zebra', vZebraStripes),
|
||||
// even by 1-indexed rownum, so +1 (makes more sense for user-facing display stuff)
|
||||
kd.toggleClass('record-even', () => (row._index()+1) % 2 === 0 ),
|
||||
|
||||
dom.on("mouseleave", (ev) => {
|
||||
// Leave only when leaving record row.
|
||||
if (!ev.relatedTarget || !ev.relatedTarget.classList.contains("record")){
|
||||
self.changeHover(-1);
|
||||
}
|
||||
}),
|
||||
self.comparison ? kd.cssClass(() => {
|
||||
const rowType = self.extraRows.getRowType(row.id());
|
||||
return rowType && `diff-${rowType}` || '';
|
||||
@ -1078,6 +1122,10 @@ GridView.prototype.buildDom = function() {
|
||||
dom.autoDispose(isCellSelected),
|
||||
dom.autoDispose(isCellActive),
|
||||
dom.autoDispose(isSelected),
|
||||
dom.on("mouseenter", () => self.changeHover(field._index())),
|
||||
kd.toggleClass("hover-column", () =>
|
||||
self.gristDoc.docModel.editingFormula() &&
|
||||
ko.unwrap(self.hoverColumn) === (field._index())),
|
||||
kd.style('width', field.widthPx),
|
||||
//TODO: Ensure that fields in a row resize when
|
||||
//a cell in that row becomes larger
|
||||
@ -1428,10 +1476,30 @@ GridView.prototype.maybeSelectRow = function(elem, rowId) {
|
||||
}
|
||||
};
|
||||
|
||||
// End Context Menus
|
||||
|
||||
GridView.prototype.revealActiveRecord = function() {
|
||||
return kd.doScrollChildIntoView(this.scrollPane, this.cursor.rowIndex());
|
||||
}
|
||||
|
||||
// End Context Menus
|
||||
// Helper to show tooltip over column selection in the full edit mode.
|
||||
class HoverColumnTooltip {
|
||||
constructor(el) {
|
||||
this.el = el;
|
||||
}
|
||||
show(text) {
|
||||
this.hide();
|
||||
this.tooltip = showTooltip(this.el, () => dom("span", text, testId("column-formula-tooltip")))
|
||||
}
|
||||
hide() {
|
||||
if (this.tooltip ) {
|
||||
this.tooltip.close();
|
||||
this.tooltip = null;
|
||||
}
|
||||
}
|
||||
dispose() {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GridView;
|
||||
|
@ -47,6 +47,7 @@ export const colors = {
|
||||
cursor: new CustomProp('color-cursor', '#16B378'), // cursor is lightGreen
|
||||
selection: new CustomProp('color-selection', 'rgba(22,179,120,0.15)'),
|
||||
selectionOpaque: new CustomProp('color-selection-opaque', '#DCF4EB'),
|
||||
selectionDarkerOpaque: new CustomProp('color-selection-darker-opaque', '#d6eee5'),
|
||||
|
||||
inactiveCursor: new CustomProp('color-inactive-cursor', '#A2E1C9'),
|
||||
|
||||
|
@ -429,8 +429,13 @@ export function openFormulaEditor(options: {
|
||||
});
|
||||
editor.attach(refElem);
|
||||
|
||||
// Enter formula-editing mode (highlight formula icons; click on a column inserts its ID).
|
||||
field.editingFormula(true);
|
||||
// When formula is empty enter formula-editing mode (highlight formula icons; click on a column inserts its ID).
|
||||
// This function is used for primarily for switching between diffrent column behaviors, so we want to enter full
|
||||
// edit mode right away.
|
||||
// TODO: consider converting it to parameter, when this will be used in diffrent scenarios.
|
||||
if (!column.formula()) {
|
||||
field.editingFormula(true);
|
||||
}
|
||||
setupCleanup(holder, gristDoc, field, saveEdit);
|
||||
return holder;
|
||||
}
|
||||
|
@ -97,12 +97,6 @@ export class FormulaEditor extends NewBaseEditor {
|
||||
this._formulaEditor.getEditor().focus();
|
||||
}),
|
||||
dom('div.formula_editor.formula_field_edit', testId('formula-editor'),
|
||||
// We don't always enter editing mode immediately, e.g. not on double-clicking a cell.
|
||||
// In those cases, we'll switch as soon as the user types or clicks into the editor.
|
||||
dom.on('mousedown', () => {
|
||||
// but don't do it when this is a readonly mode
|
||||
options.field.editingFormula(true);
|
||||
}),
|
||||
this._formulaEditor.buildDom((aceObj: any) => {
|
||||
aceObj.setFontSize(11);
|
||||
aceObj.setHighlightActiveLine(false);
|
||||
|
Loading…
Reference in New Issue
Block a user