From b6fe3e34f5cd70cd5ba666d72b23423a6a2c8663 Mon Sep 17 00:00:00 2001 From: Tsanie Lily Date: Sun, 7 Apr 2024 08:39:44 +0800 Subject: [PATCH] issue: customer communication contacts grid height. change: replace schedule date control. change: date validation from 1753-01-01 to 9999-12-31. --- lib/app/communications/customer.js | 8 ++++---- lib/app/communications/style.scss | 1 + lib/element/schedule.js | 10 ++++++++-- lib/element/style.scss | 6 ++++++ lib/ui/date.js | 4 ++++ lib/ui/dropdown.d.ts | 4 +++- lib/ui/dropdown.js | 12 ++++++++---- lib/ui/grid/column.js | 30 +++++++++++++++++++++++++++--- lib/ui/grid/grid.js | 7 +++++-- 9 files changed, 66 insertions(+), 16 deletions(-) diff --git a/lib/app/communications/customer.js b/lib/app/communications/customer.js index 1963dd9..7650055 100644 --- a/lib/app/communications/customer.js +++ b/lib/app/communications/customer.js @@ -790,9 +790,9 @@ export default class CustomerCommunication { div.style.display = 'none'; } div.className = 'contacts-record'; - div.style.maxHeight = '200px'; + // div.style.maxHeight = '200px'; div.style.width = '675px'; - div.style.overflow = 'auto'; + // div.style.overflow = 'auto'; }), createElement('div', div => { div.style.fontWeight = 'bold'; @@ -800,9 +800,9 @@ export default class CustomerCommunication { }), createElement('div', div => { div.className = 'contacts-wo'; - div.style.maxHeight = '200px'; + // div.style.maxHeight = '200px'; div.style.width = '675px'; - div.style.overflow = 'auto'; + // div.style.overflow = 'auto'; }) ) }); diff --git a/lib/app/communications/style.scss b/lib/app/communications/style.scss index 318b475..4f975a4 100644 --- a/lib/app/communications/style.scss +++ b/lib/app/communications/style.scss @@ -16,6 +16,7 @@ >.ui-grid { overflow-x: visible; + max-height: 200px; } } } diff --git a/lib/element/schedule.js b/lib/element/schedule.js index 18520f6..7a8bf73 100644 --- a/lib/element/schedule.js +++ b/lib/element/schedule.js @@ -206,10 +206,16 @@ export default class ScheduleItem { createElement('legend', legend => legend.innerText = 'Duration'), createElement('div', 'schedule-item-line schedule-item-line-duration', createElement('span', span => span.innerText = 'Start date'), - createElement('input', i => { i.type = 'date', i.className = 'ui-input schedule-id-duration-start', i.maxLength = 10 }), + validation( + createElement('input', i => { i.type = 'date', i.className = 'ui-input schedule-id-duration-start', i.maxLength = 10, i.required = true, i.min = '1753-01-01', i.max = '9999-12-31' }), + /^[1-9][0-9]{3}-(1[0-2]|0[1-9])-(3[0-1]|[1-2][0-9]|0[1-9])$/ + ), createElement('div', 'schedule-item-placeholder'), createElement('span', span => span.innerText = 'End date'), - createElement('input', i => { i.type = 'date', i.className = 'ui-input schedule-id-duration-end', i.maxLength = 10 }) + validation( + createElement('input', i => { i.type = 'date', i.className = 'ui-input schedule-id-duration-end', i.maxLength = 10, i.required = true, i.min = '1753-01-01', i.max = '9999-12-31' }), + /^[1-9][0-9]{3}-(1[0-2]|0[1-9])-(3[0-1]|[1-2][0-9]|0[1-9])$/ + ) ), createElement('div', 'schedule-item-line', createCheckbox({ className: 'schedule-id-enabled', checked: true, label: 'Enabled' }) diff --git a/lib/element/style.scss b/lib/element/style.scss index f7a7b35..5c9c758 100644 --- a/lib/element/style.scss +++ b/lib/element/style.scss @@ -18,6 +18,12 @@ .ui-input { line-height: 20px; height: 20px; + text-indent: 0; + + &.validation-error, + &:invalid { + color: #0000004d; + } } .schedule-item-monthly { diff --git a/lib/ui/date.js b/lib/ui/date.js index e3ca45d..81d249a 100644 --- a/lib/ui/date.js +++ b/lib/ui/date.js @@ -22,9 +22,13 @@ export function createDateInput(min, max, element) { date.type = 'date'; if (min != null) { date.min = min; + } else { + date.min = '1753-01-01'; } if (max != null) { date.max = max; + } else { + date.max = '9999-12-31'; } return date; } diff --git a/lib/ui/dropdown.d.ts b/lib/ui/dropdown.d.ts index b69dbcc..927c1f4 100644 --- a/lib/ui/dropdown.d.ts +++ b/lib/ui/dropdown.d.ts @@ -117,8 +117,10 @@ export class Dropdown { * 选中某个条目 * @param selected 选中的值 * @param silence 是否静默选中,即不触发 {@linkcode onSelected} 事件 + * @param ignoreCase 是否不区分大小写 + * @returns 是否选中 */ - select(selected: string, silence?: boolean): void; + select(selected: string, silence?: boolean, ignoreCase?: boolean): boolean | undefined; /** * 选中条目列表 * @param selectedlist 选中的值的列表 diff --git a/lib/ui/dropdown.js b/lib/ui/dropdown.js index 78df616..9799ef0 100644 --- a/lib/ui/dropdown.js +++ b/lib/ui/dropdown.js @@ -281,18 +281,21 @@ export class Dropdown { get selectedList() { return this._var.selectedList || [] } - select(selected, silence) { + select(selected, silence, ignoreCase) { if (typeof selected !== 'string') { selected = String(selected); } + if (ignoreCase) { + selected = selected.toLowerCase(); + } if (this._var.lastSelected === selected) { - return false; + return; } this._var.lastSelected = selected; const valuekey = this._var.options.valueKey; const textkey = this._var.options.textKey; const htmlkey = this._var.options.htmlKey; - let item = this.source.find(it => String(it[valuekey]) === selected); + let item = this.source.find(it => (ignoreCase ? String(it[valuekey]).toLowerCase() : String(it[valuekey])) === selected); if (this._var.options.input) { if (item == null) { item = { [valuekey]: selected }; @@ -322,7 +325,7 @@ export class Dropdown { } if (expanded) { for (let li of this._var.container.querySelectorAll('li[data-value]')) { - if (li.dataset.value === selected) { + if ((ignoreCase ? li.dataset.value.toLowerCase() : li.dataset.value) === selected) { li.classList.add('selected'); break; } @@ -338,6 +341,7 @@ export class Dropdown { if (!silence && typeof this.onSelected === 'function') { this.onSelected(item); } + return true; } selectlist(selectedlist, silence) { diff --git a/lib/ui/grid/column.js b/lib/ui/grid/column.js index cb0385f..46467b5 100644 --- a/lib/ui/grid/column.js +++ b/lib/ui/grid/column.js @@ -445,8 +445,9 @@ export class GridDropdownColumn extends GridColumn { * @param {any} val * @param {GridItemWrapper} wrapper * @param {GridColumnDefinition} col + * @param {Grid} grid */ - static setValue(element, val, wrapper, col) { + static setValue(element, val, wrapper, col, grid) { if (element.tagName !== 'DIV') { let source = this._getSource(wrapper, col); if (source instanceof Promise) { @@ -460,19 +461,42 @@ export class GridDropdownColumn extends GridColumn { if (drop == null) { return; } + const ignoreCase = col.dropRestrictCase !== true; if (drop.source == null || drop.source.length === 0) { let source = this._getSource(wrapper, col); if (source instanceof Promise) { source.then(s => { drop.source = s; - drop.select(val, true); + drop.select(val, true, ignoreCase); }) return; } else if (source != null) { drop.source = source; } } - drop.select(val, true); + if (typeof val === 'string' && val !== '') { + const lVal = String(val).toLowerCase(); + const item = drop.source.find(s => { + let v = s[col.dropOptions?.valueKey ?? 'value']; + if (ignoreCase) { + return String(v).toLowerCase() === lVal; + } + return v === val; + }); + if (item == null) { + let text; + if (col.text == null && typeof col.filter === 'function') { + text = col.filter(wrapper.values, false, grid._var.refs.body); + } else { + text = val; + } + drop.source.push({ + [col.dropOptions?.textKey ?? 'text']: text, + [col.dropOptions?.valueKey ?? 'value']: val + }); + } + } + drop.select(val, true, ignoreCase); } /** diff --git a/lib/ui/grid/grid.js b/lib/ui/grid/grid.js index d7e4902..63b725f 100644 --- a/lib/ui/grid/grid.js +++ b/lib/ui/grid/grid.js @@ -258,6 +258,7 @@ let r = lang; * @property {boolean} [filterAsValue=false] - 列头过滤强制使用 `Value` 字段 * @property {GridItemSortCallback} [sortFilter] - 自定义列排序函数 * @property {DropdownOptions} [dropOptions] - 列为下拉列表类型时以该值设置下拉框的参数 + * @property {boolean} [dropRestrictCase=false] - 下拉列表是否区分大小写 * @property {(GridSourceItem[] | Promise | GridDropdownSourceCallback)} [source] - 列为下拉列表类型时以该值设置下拉列表数据源,支持返回异步对象,也支持调用函数返回 * @property {boolean} [sourceCache=false] - 下拉列表数据源是否缓存结果(即行数据未发生变化时仅从source属性获取一次值) * @property {("fa-light" | "fa-regular" | "fa-solid")} [iconType=fa-light] - 列为图标类型时以该值设置图标样式 @@ -1924,7 +1925,8 @@ export class Grid { } const it = this._var.currentSource[index]; // clear dropdown source cache - delete it.source; + // FIXME: 清除缓存会导致选中状态下动态数据源下拉列表显示为空 + // delete it.source; it.values = item; if (this.sortIndex >= 0) { this.sortColumn(); @@ -4127,7 +4129,8 @@ export class Grid { return; } const vals = this._var.currentSource[this._var.startIndex + index]; - delete vals.source; + // FIXME: 清除缓存会导致选中状态下动态数据源下拉列表显示为空 + // delete vals.source; const item = vals.values; if (item == null) { return;