gristlabs_grist-core/app/client/widgets/DateTextBox.js
George Gevoian 86062a8c28 (core) New Grist Forms styling and field options
Summary:
 - New styling for forms.
 - New field options for various field types (spinner, checkbox, radio buttons, alignment, sort).
 - Improved alignment of form fields in columns.
 - Support for additional select input keyboard shortcuts (Enter and Backspace).
 - Prevent submitting form on Enter if an input has focus.
 - Fix for changing form field type causing the field to disappear.

Test Plan: Browser tests.

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D4223
2024-04-11 08:17:42 -07:00

127 lines
4.1 KiB
JavaScript

var _ = require('underscore');
var ko = require('knockout');
var dom = require('../lib/dom');
var dispose = require('../lib/dispose');
var kd = require('../lib/koDom');
var kf = require('../lib/koForm');
var AbstractWidget = require('./AbstractWidget');
const {FormFieldRulesConfig} = require('app/client/components/Forms/FormConfig');
const {fromKoSave} = require('app/client/lib/fromKoSave');
const {alignmentSelect, cssButtonSelect} = require('app/client/ui2018/buttonSelect');
const {cssLabel, cssRow} = require('app/client/ui/RightPanelStyles');
const {cssTextInput} = require("app/client/ui2018/editableLabel");
const {dom: gdom, styled, fromKo} = require('grainjs');
const {select} = require('app/client/ui2018/menus');
const {dateFormatOptions} = require('app/common/parseDate');
/**
* DateTextBox - The most basic widget for displaying simple date information.
*/
function DateTextBox(field) {
AbstractWidget.call(this, field);
this.alignment = this.options.prop('alignment');
// These properties are only used in configuration.
this.dateFormat = this.field.config.options.prop('dateFormat');
this.isCustomDateFormat = this.field.config.options.prop('isCustomDateFormat');
this.mixedDateFormat = ko.pureComputed(() => this.dateFormat() === null || this.isCustomDateFormat() === null);
// Helper to set 'dateFormat' and 'isCustomDateFormat' from the set of default date format strings.
this.standardDateFormat = this.autoDispose(ko.computed({
owner: this,
read: function() { return this.mixedDateFormat() ? null : this.isCustomDateFormat() ? 'Custom' : this.dateFormat(); },
write: function(val) {
if (val === 'Custom') { this.isCustomDateFormat.setAndSave(true); }
else {
this.field.config.options.update({isCustomDateFormat: false, dateFormat: val});
this.field.config.options.save();
}
}
}));
// An observable that always returns `UTC`, eases DateTimeEditor inheritance.
this.timezone = ko.observable('UTC');
}
dispose.makeDisposable(DateTextBox);
_.extend(DateTextBox.prototype, AbstractWidget.prototype);
DateTextBox.prototype.buildDateConfigDom = function() {
const disabled = this.field.config.options.disabled('dateFormat');
return dom('div',
cssLabel("Date Format"),
cssRow(dom(select(
fromKo(this.standardDateFormat),
[...dateFormatOptions, "Custom"],
{ disabled, defaultLabel: "Mixed format" },
), dom.testId("Widget_dateFormat"))),
kd.maybe(() => !this.mixedDateFormat() && this.isCustomDateFormat(), () => {
return cssRow(dom(
textbox(this.dateFormat, { disabled }),
dom.testId("Widget_dateCustomFormat")));
})
);
};
DateTextBox.prototype.buildConfigDom = function() {
return dom('div',
this.buildDateConfigDom(),
cssRow(
alignmentSelect(
fromKoSave(this.field.config.options.prop('alignment')),
cssButtonSelect.cls('-disabled', this.field.config.options.disabled('alignment')),
),
)
);
};
DateTextBox.prototype.buildTransformConfigDom = function() {
return this.buildDateConfigDom();
};
DateTextBox.prototype.buildFormConfigDom = function() {
return [
gdom.create(FormFieldRulesConfig, this.field),
];
};
DateTextBox.prototype.buildDom = function(row) {
let value = row[this.field.colId()];
return dom('div.field_clip',
kd.style('text-align', this.alignment),
kd.text(() => row._isAddRow() || this.isDisposed() ? '' : this.valueFormatter().format(value()))
);
};
// clean up old koform styles
const cssClean = styled('div', `
flex: 1;
margin: 0px;
`)
// override focus - to look like modern ui
const cssFocus = styled('div', `
&:focus {
outline: none;
box-shadow: 0 0 3px 2px var(--grist-color-cursor);
border: 1px solid transparent;
}
`)
// helper method to create old style textbox that looks like a new one
function textbox(value, options) {
const textDom = kf.text(value, options ?? {});
const tzInput = textDom.querySelector('input');
dom(tzInput,
kd.cssClass(cssTextInput.className),
kd.cssClass(cssFocus.className)
);
dom(textDom,
kd.cssClass(cssClean.className)
);
return textDom;
}
module.exports = DateTextBox;