mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Improving experience when editing group-by column.
Summary: Improving experience when editing group-by column: - Disable column rename - Allow changing most widget properties: - Color/Background - Number format - Date/DateTime format (but not the timezone) - All toggle options (for toggle column) - Remove Edit button on Choice Edit - Changing the underlying column should reset all those options back to the original column. Test Plan: nbrowser Reviewers: alexmojaki Reviewed By: alexmojaki Subscribers: alexmojaki Differential Revision: https://phab.getgrist.com/D3216
This commit is contained in:
@@ -918,7 +918,12 @@ GridView.prototype.buildDom = function() {
|
||||
kd.style('borderLeftWidth', v.borderWidthPx),
|
||||
kd.foreach(v.viewFields(), field => {
|
||||
var isEditingLabel = ko.pureComputed({
|
||||
read: () => this.gristDoc.isReadonlyKo() || self.isPreview ? false : editIndex() === field._index(),
|
||||
read: () => {
|
||||
const goodIndex = () => editIndex() === field._index();
|
||||
const isReadonly = () => this.gristDoc.isReadonlyKo() || self.isPreview;
|
||||
const isSummary = () => Boolean(field.column().disableEditData());
|
||||
return goodIndex() && !isReadonly() && !isSummary();
|
||||
},
|
||||
write: val => editIndex(val ? field._index() : -1)
|
||||
}).extend({ rateLimit: 0 });
|
||||
let filterTriggerCtl;
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface ACSelectItem extends ACItem {
|
||||
export function buildACSelect(
|
||||
owner: IDisposableOwner,
|
||||
options: {
|
||||
disabled?: Observable<boolean>,
|
||||
acIndex: ACIndex<ACSelectItem>,
|
||||
valueObs: Observable<string>,
|
||||
save: (value: string, item: ACSelectItem|undefined) => Promise<void>|void
|
||||
@@ -55,6 +56,9 @@ export function buildACSelect(
|
||||
|
||||
const onMouseDown = (ev: MouseEvent) => {
|
||||
ev.preventDefault(); // Don't let it affect focus, since we focus/blur manually.
|
||||
if (options.disabled?.get()) {
|
||||
return;
|
||||
}
|
||||
if (!isOpen()) { textInput.focus(); }
|
||||
openOrCommit();
|
||||
};
|
||||
@@ -73,6 +77,7 @@ export function buildACSelect(
|
||||
dom.prop('value', valueObs),
|
||||
dom.on('focus', (ev, elem) => elem.select()),
|
||||
dom.on('blur', commitOrRevert),
|
||||
dom.prop("disabled", (use) => options.disabled ? use(options.disabled) : false),
|
||||
dom.onKeyDown({
|
||||
Escape: revert,
|
||||
Enter: openOrCommit,
|
||||
|
||||
@@ -58,7 +58,8 @@ export function buildNameConfig(owner: MultiHolder, origColumn: ColumnRec, curso
|
||||
cssColTieConnectors(),
|
||||
cssToggleButton(icon('FieldReference'),
|
||||
cssToggleButton.cls('-selected', (use) => !use(untieColId)),
|
||||
dom.on('click', () => untieColId.saveOnly(!untieColId.peek())),
|
||||
dom.on('click', () => !origColumn.disableModify.peek() && untieColId.saveOnly(!untieColId.peek())),
|
||||
cssToggleButton.cls("-disabled", origColumn.disableModify),
|
||||
testId('field-derive-id')
|
||||
),
|
||||
)
|
||||
@@ -391,6 +392,10 @@ const cssToggleButton = styled(cssIconButton, `
|
||||
&-selected:hover {
|
||||
--icon-color: ${colors.darkGrey};
|
||||
}
|
||||
&-disabled, &-disabled:hover {
|
||||
--icon-color: ${colors.light};
|
||||
background-color: var(--grist-color-medium-grey-opaque);
|
||||
}
|
||||
`);
|
||||
|
||||
const cssColLabelBlock = styled('div', `
|
||||
|
||||
@@ -91,7 +91,8 @@ export class ChoiceListEntry extends Disposable {
|
||||
constructor(
|
||||
private _values: Observable<string[]>,
|
||||
private _choiceOptionsByName: Observable<ChoiceOptionsByName>,
|
||||
private _onSave: (values: string[], choiceOptions: ChoiceOptionsByName, renames: Record<string, string>) => void
|
||||
private _onSave: (values: string[], choiceOptions: ChoiceOptionsByName, renames: Record<string, string>) => void,
|
||||
private _disabled: Observable<boolean>
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -177,12 +178,15 @@ export class ChoiceListEntry extends Disposable {
|
||||
)
|
||||
),
|
||||
dom.on('click', () => this._startEditing()),
|
||||
cssListBoxInactive.cls("-disabled", this._disabled),
|
||||
testId('choice-list-entry')
|
||||
),
|
||||
cssButtonRow(
|
||||
primaryButton('Edit',
|
||||
dom.on('click', () => this._startEditing()),
|
||||
testId('choice-list-entry-edit')
|
||||
dom.maybe(use => !use(this._disabled), () =>
|
||||
cssButtonRow(
|
||||
primaryButton('Edit',
|
||||
dom.on('click', () => this._startEditing()),
|
||||
testId('choice-list-entry-edit')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -191,7 +195,9 @@ export class ChoiceListEntry extends Disposable {
|
||||
}
|
||||
|
||||
private _startEditing(): void {
|
||||
this._isEditing.set(true);
|
||||
if (!this._disabled.get()) {
|
||||
this._isEditing.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
private _save(): void {
|
||||
@@ -369,6 +375,9 @@ const cssListBoxInactive = styled(cssListBox, `
|
||||
&:hover {
|
||||
border: 1px solid ${colors.hover};
|
||||
}
|
||||
&-disabled {
|
||||
cursor: default;
|
||||
}
|
||||
`);
|
||||
|
||||
const cssListRow = styled('div', `
|
||||
|
||||
@@ -5,7 +5,7 @@ import {KoSaveableObservable} from 'app/client/models/modelUtil';
|
||||
import {cssLabel, cssRow} from 'app/client/ui/RightPanel';
|
||||
import {testId} from 'app/client/ui2018/cssVars';
|
||||
import {NTextBox} from 'app/client/widgets/NTextBox';
|
||||
import {Computed, dom, styled} from 'grainjs';
|
||||
import {Computed, dom, fromKo, styled} from 'grainjs';
|
||||
import {choiceToken, DEFAULT_FILL_COLOR, DEFAULT_TEXT_COLOR} from 'app/client/widgets/ChoiceToken';
|
||||
|
||||
export interface IChoiceOptions {
|
||||
@@ -73,7 +73,8 @@ export class ChoiceTextBox extends NTextBox {
|
||||
ChoiceListEntry,
|
||||
this._choiceValues,
|
||||
this._choiceOptionsByName,
|
||||
this.save.bind(this)
|
||||
this.save.bind(this),
|
||||
fromKo(this.field.column().disableEditData)
|
||||
)
|
||||
)
|
||||
];
|
||||
|
||||
@@ -66,7 +66,10 @@ DateTimeTextBox.prototype.buildConfigDom = function(isTransformConfig) {
|
||||
var self = this;
|
||||
return dom('div',
|
||||
cssLabel("Timezone"),
|
||||
cssRow(gdom.create(buildTZAutocomplete, moment, fromKo(this._timezone), this._setTimezone)),
|
||||
cssRow(
|
||||
gdom.create(buildTZAutocomplete, moment, fromKo(this._timezone), this._setTimezone,
|
||||
{ disabled : fromKo(this.field.column().disableEditData)}),
|
||||
),
|
||||
self.buildDateConfigDom(),
|
||||
cssLabel("Time Format"),
|
||||
cssRow(dom(select(fromKo(self.standardTimeFormat), self.timeFormatOptions), dom.testId("Widget_timeFormat"))),
|
||||
|
||||
@@ -47,7 +47,8 @@ export function buildTZAutocomplete(
|
||||
owner: IDisposableOwner,
|
||||
moment: MomentTimezone,
|
||||
valueObs: Observable<string>,
|
||||
save: (value: string) => Promise<void>|void
|
||||
save: (value: string) => Promise<void>|void,
|
||||
options?: { disabled?: Observable<boolean> }
|
||||
) {
|
||||
// Set a large maxResults, since it's sometimes nice to see all supported timezones (there are
|
||||
// fewer than 1000 in practice).
|
||||
@@ -69,7 +70,7 @@ export function buildTZAutocomplete(
|
||||
}
|
||||
};
|
||||
return buildACSelect(owner,
|
||||
{acIndex, valueObs, save: saveTZ},
|
||||
{...options, acIndex, valueObs, save: saveTZ},
|
||||
testId("tz-autocomplete")
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user