From 8dafc1c5f4e8222b4be30e88a82876da09490f79 Mon Sep 17 00:00:00 2001 From: Tsanie Lily Date: Fri, 5 May 2023 15:35:58 +0800 Subject: [PATCH] sync --- lib/app/communications/customer.js | 25 +++--- lib/app/communications/style.scss | 5 +- lib/ui/grid/column.js | 21 ++++-- lib/ui/grid/grid.html | 2 +- lib/ui/grid/grid.js | 117 +++++++++++++---------------- 5 files changed, 88 insertions(+), 82 deletions(-) diff --git a/lib/app/communications/customer.js b/lib/app/communications/customer.js index 5ec58ed..0f5f586 100644 --- a/lib/app/communications/customer.js +++ b/lib/app/communications/customer.js @@ -255,6 +255,7 @@ class CustomerCommunication { this.#followers.replaceChildren(); if (followers?.length > 0) { this.#container.querySelector('.follower-bar').style.display = ''; + setTooltip(this.#buttonFollower, r('editFollower', 'Edit Followers')); this.#container.querySelector('.follower-bar>.bar-list').appendChild(this.#buttonFollower); for (let f of followers) { if (f.OptOut) { @@ -297,6 +298,7 @@ class CustomerCommunication { } } else { this.#container.querySelector('.follower-bar').style.display = 'none'; + setTooltip(this.#buttonFollower, r('addFollowers', 'Add Followers')); this.#container.querySelector('.button-edit-contacts').insertAdjacentElement('beforebegin', this.#buttonFollower) } this.#message.scrollTop = this.#message.scrollHeight @@ -491,7 +493,7 @@ class CustomerCommunication { })); button.addEventListener('click', () => { const add = new Contact({ - company: !nullOrEmpty(this.#data.companyName), + company: !nullOrEmpty(this.#option.companyName), onSave: item => { const exists = this.#gridContact.source.some(s => s.Name === item.Name && s.MobilePhone === item.MobilePhone); if (exists) { @@ -535,19 +537,20 @@ class CustomerCommunication { }), createElement('div', null, createElement('div', div => { - if (nullOrEmpty(this.#data.companyName)) { + if (nullOrEmpty(this.#option.companyName)) { div.style.display = 'none'; } div.style.fontWeight = 'bold'; div.innerText = r('contactFromRecord', 'Contacts from Customer Record'); }), createElement('div', div => { - if (nullOrEmpty(this.#data.companyName)) { + if (nullOrEmpty(this.#option.companyName)) { div.style.display = 'none'; } div.className = 'contacts-record'; - div.style.maxHeight = '400px'; - div.style.width = '660px'; + div.style.maxHeight = '200px'; + div.style.width = '675px'; + div.style.overflow = 'auto'; }), createElement('div', div => { div.style.fontWeight = 'bold'; @@ -556,7 +559,8 @@ class CustomerCommunication { createElement('div', div => { div.className = 'contacts-wo'; div.style.maxHeight = '200px'; - div.style.width = '660px'; + div.style.width = '675px'; + div.style.overflow = 'auto'; }) ) ); @@ -564,14 +568,15 @@ class CustomerCommunication { const selectedCol = This => { return { key: 'selected', - type: Grid.ColumnTypes.Checkbox, + type: TooltipCheckboxColumn, width: 50, enabled: item => !item.OptOut && !item.OptOut_BC, onchanged: function () { if (typeof option.onChanged === 'function') { option.onChanged([...This.#gridContact.source, ...This.#gridWo.source]); } - } + }, + tooltip: item => item.OptOut ? r('optedOut', 'Opted Out') : r('optedIn', 'Opted In') } }; const iconCol = { @@ -606,7 +611,7 @@ class CustomerCommunication { onclick: function () { const edit = new Contact({ contact: this, - company: !nullOrEmpty(This.#data.companyName), + company: !nullOrEmpty(This.#option.companyName), onSave: (item, _op) => { const exists = This.#gridContact.source.some(s => s !== this && s.Name === item.Name && s.MobilePhone === item.MobilePhone) || @@ -871,7 +876,7 @@ class CustomerCommunication { createElement('div', div => { div.className = 'followers-record'; div.style.maxHeight = '400px'; - div.style.width = '660px'; + div.style.width = '675px'; div.style.overflow = 'auto'; }) ) diff --git a/lib/app/communications/style.scss b/lib/app/communications/style.scss index 0aef017..46adaea 100644 --- a/lib/app/communications/style.scss +++ b/lib/app/communications/style.scss @@ -196,11 +196,14 @@ > textarea { padding: 10px 10px 0; - border: none; + border: 1px solid var(--title-bg-color); + border-radius: 5px; height: 70px; resize: none; font-size: var(--font-smaller-size); font-family: var(--font-family); + margin: 3px 5px; + background: #f0f0f0; @include outline(); } diff --git a/lib/ui/grid/column.js b/lib/ui/grid/column.js index 690157d..2275c34 100644 --- a/lib/ui/grid/column.js +++ b/lib/ui/grid/column.js @@ -1,9 +1,9 @@ import { global } from "../../utility"; -import { nullOrEmpty } from "../../utility/strings"; +// import { nullOrEmpty } from "../../utility/strings"; import { createElement } from "../../functions"; import { createIcon } from "../icon"; import { createCheckbox } from "../checkbox"; -import { setTooltip } from "../tooltip"; +// import { setTooltip } from "../tooltip"; import Dropdown from "../dropdown"; class GridColumn { @@ -20,6 +20,13 @@ class GridColumn { element.style.setProperty(css[0], css[1]); } } + + static setEnabled(element, enabled) { + const tooltip = element.querySelector('.ui-tooltip-wrapper'); + if (tooltip != null) { + tooltip.style.display = enabled === false ? 'none' : ''; + } + } } class GridInputColumn extends GridColumn { @@ -54,6 +61,7 @@ class GridInputColumn extends GridColumn { static getValue(e) { return e.target.value } static setEnabled(element, enabled) { + super.setEnabled(element , enabled); element.disabled = enabled === false; } } @@ -162,6 +170,7 @@ class GridDropdownColumn extends GridColumn { } static setEnabled(element, enabled) { + super.setEnabled(element , enabled); const drop = this.#getDrop(element); if (drop == null) { return; @@ -185,6 +194,7 @@ class GridCheckboxColumn extends GridColumn { static getValue(e) { return e.target.checked } static setEnabled(element, enabled) { + super.setEnabled(element , enabled); element.querySelector('input').disabled = enabled === false; } } @@ -211,22 +221,19 @@ class GridIconColumn extends GridColumn { const icon = createIcon(type, val); // const layer = element.children[0]; element.replaceChildren(icon); - !nullOrEmpty(col.tooltip) && setTooltip(element, col.tooltip, false, grid.element); + // !nullOrEmpty(col.tooltip) && setTooltip(element, col.tooltip, false, grid.element); element.dataset.type = type; element.dataset.icon = val; } } static setEnabled(element, enabled) { + super.setEnabled(element , enabled); if (enabled === false) { element.classList.add('disabled'); } else { element.classList.remove('disabled'); } - const tooltip = element.querySelector('.ui-tooltip-wrapper'); - if (tooltip != null) { - tooltip.style.display = enabled === false ? 'none' : ''; - } } } diff --git a/lib/ui/grid/grid.html b/lib/ui/grid/grid.html index 887af0f..89dea87 100644 --- a/lib/ui/grid/grid.html +++ b/lib/ui/grid/grid.html @@ -225,7 +225,7 @@ enabled: 'enabled' }, { key: 'c2c', caption: '多行编辑', type: Grid.ColumnTypes.Text, enabled: 'enabled' }, - { key: 'c3', caption: 'column 3', width: 90 }, + { key: 'c3', caption: 'column 3', width: 90, align: 'right' }, { key: 'c4', caption: 'Note', type: Grid.ColumnTypes.Input }, { key: 'c5', diff --git a/lib/ui/grid/grid.js b/lib/ui/grid/grid.js index 9ff5468..10fae81 100644 --- a/lib/ui/grid/grid.js +++ b/lib/ui/grid/grid.js @@ -1,9 +1,11 @@ import '../css/grid.scss'; import { global, isPositive, isMobile, throttle, truncate } from "../../utility"; import { r } from "../../utility/lgres"; +import { nullOrEmpty } from "../../utility/strings"; import { createElement } from "../../functions"; import { createIcon } from "../icon"; import { createCheckbox } from "../checkbox"; +import { setTooltip } from "../tooltip"; import { GridColumn, GridInputColumn, GridTextColumn, GridDropdownColumn, GridCheckboxColumn, GridIconColumn } from "./column"; const ColumnChangedType = { @@ -223,7 +225,7 @@ class Grid { this.#parent = container; const grid = createElement('div', 'ui-grid'); grid.setAttribute('tabindex', 0); - const onKeydown = e => { + grid.addEventListener('keydown', e => { let index = this.selectedIndex; let flag = false; if (e.key === 'ArrowUp') { @@ -249,8 +251,7 @@ class Grid { } e.stopPropagation(); } - }; - grid.addEventListener('keydown', e => throttle(onKeydown, 800, this, e)); + }); container.replaceChildren(grid); const sizer = createElement('span', 'ui-grid-sizer'); grid.appendChild(sizer); @@ -296,7 +297,7 @@ class Grid { let height = this.height; if (height === 0) { - height = this.#containerHeight ??= this.containerHeight; + height = this.#containerHeight; } else if (isNaN(height) || height < 0) { height = this.#el.offsetHeight - top; } @@ -308,21 +309,17 @@ class Grid { this.#bodyClientWidth = body.clientWidth; } - get containerHeight() { + reload() { let length = this.#currentSource.length; if (this.extraRows > 0) { length += this.extraRows; } - return length * (this.rowHeight + 1); - } - - reload() { - this.#containerHeight = this.containerHeight; + this.#containerHeight = length * (this.rowHeight + 1); this.#refs.body.scrollTop = 0; this.#refs.body.scrollLeft = 0; this.#refs.bodyContent.style.top = '0px'; this.#refs.bodyContainer.style.height = `${this.#containerHeight}px`; - // this.#adjustRows(this.#refs.bodyContent); + this.#adjustRows(this.#refs.bodyContent); this.refresh(); } @@ -330,8 +327,9 @@ class Grid { if (this.#refs.bodyContent == null) { throw new Error('body has not been created.'); } + const rows = this.#refs.bodyContent.children; const widths = {}; - this.#fillRows(widths); + this.#fillRows(rows, this.columns, widths); if (this.#needResize && widths.flag) { this.#needResize = false; this.columns.forEach((col, i) => { @@ -586,45 +584,24 @@ class Grid { return body; } - #fillRows(widths) { + #adjustRows() { let count = this.#rowCount; if (isNaN(count) || count < 0 || !this.virtual) { count = this.#currentSource.length; } - const content = this.#refs.bodyContent; - // content.replaceChildren(); const cols = this.columns; - const vtable = this.#vtable; - const vnew = []; - const startIndex = this.#startIndex; - // reuse - for (let i = 0; i < count; i++) { - const index = startIndex + i; - const e = vtable.findIndex(v => v.index === index); - if (e >= 0) { - vnew[i] = vtable.splice(e, 1)[0]; - } - } - // move or create - for (let i = 0; i < count; i++) { - if (vnew[i] != null) { - continue; - } - const index = startIndex + i; - const e = vtable.splice(0, 1); - let vdom; - if (e.length > 0) { - vdom = { - ...e[0], - index, - mode: 'move' - }; - vdom.el.remove(); - } else { + const content = this.#refs.bodyContent; + const exists = content.children.length; + count -= exists; + if (count > 0) { + for (let i = 0; i < count; i += 1) { const row = createElement('tr', 'ui-grid-row'); + // row.addEventListener('mousedown', e => this.#onRowClicked(e, exists + i)); + // row.addEventListener('dblclick', e => this.#onRowDblClicked(e)); cols.forEach((col, j) => { const cell = createElement('td'); if (col.visible !== false) { + cell.dataset.row = String(exists + i); cell.dataset.col = String(j); const style = this.#get(col.key, 'style'); if (style != null) { @@ -638,7 +615,7 @@ class Grid { } } if (Grid.ColumnTypes.isCheckbox(col.type)) { - cell.appendChild(GridCheckboxColumn.createEdit(e => this.#onRowChanged(e, index, col, e.target.checked))); + cell.appendChild(GridCheckboxColumn.createEdit(e => this.#onRowChanged(e, exists + i, col, e.target.checked, cell))); // this.#colTypes[col.key] = GridCheckboxColumn; } else { let type = this.#colTypes[col.key]; @@ -659,30 +636,29 @@ class Grid { row.appendChild(cell); }); row.appendChild(createElement('td')); - vdom = { - index, - mode: 'create', - el: row - }; + content.appendChild(row); + } + } else if (count < 0) { + for (let i = -1; i >= count; i -= 1) { + // content.removeChild(content.children[exists + i]); + content.children[exists + i].remove(); } - vnew[i] = vdom; } - this.#vtable = vnew; + } + #fillRows(rows, cols, widths) { + const startIndex = this.#startIndex; const selectedIndexes = this.#selectedIndexes; - vnew.filter(vdom => vdom.mode != null).forEach(vdom => { - const row = vdom.el; - const index = vdom.index; - const vals = this.#currentSource[index]; + [...rows].forEach((row, i) => { + const vals = this.#currentSource[startIndex + i]; if (vals == null) { return; } if (!isPositive(row.children.length)) { return; } - // row.dataset.row = String(index); const item = vals.values; - const selected = selectedIndexes.indexOf(index) >= 0; + const selected = selectedIndexes.indexOf(startIndex + i) >= 0; if (selected) { row.classList.add('selected'); } else if (row.classList.contains('selected')) { @@ -713,7 +689,6 @@ class Grid { val ??= ''; // fill const cell = row.children[j]; - cell.dataset.row = String(index); if (typeof col.bgFilter === 'function') { const bgColor = col.bgFilter(item); cell.style.backgroundColor = bgColor ?? ''; @@ -724,10 +699,10 @@ class Grid { if (!isCheckbox && selectChanged && typeof type.createEdit === 'function') { if (vals.__editing?.[col.key] && type.editing) { val = type.getValue({ target: cell.children[0] }); - this.#onRowChanged(null, index, col, val, true); + this.#onRowChanged(null, startIndex + i, col, val, cell, true); } element = selected ? - type.createEdit(e => this.#onRowChanged(e, index, col, type.getValue(e)), col, this.#refs.bodyContent, vals) : + type.createEdit(e => this.#onRowChanged(e, startIndex + i, col, type.getValue(e), cell), col, this.#refs.bodyContent, vals) : type.create(col); cell.replaceChildren(element); } else { @@ -745,6 +720,15 @@ class Grid { } } type.setValue(element, val, item, col, this); + let tip = col.tooltip; + if (typeof tip === 'function') { + tip = tip.call(col, item); + } + if (nullOrEmpty(tip)) { + element.querySelector('.ui-tooltip-wrapper')?.remove(); + } else { + setTooltip(element, tip, false, this.element); + } if (typeof type.setEnabled === 'function') { type.setEnabled(element, enabled); } @@ -781,8 +765,6 @@ class Grid { delete vals.__editing; } }); - - content.replaceChildren(...vnew.map(vdom => vdom.el)); } #changeColumnWidth(index, width) { @@ -1532,11 +1514,11 @@ class Grid { } } - #onRowChanged(_e, index, col, value, blur) { + #onRowChanged(_e, index, col, value, cell, blur) { if (this.#currentSource == null) { return; } - const row = this.#currentSource[index]; + const row = this.#currentSource[this.#startIndex + index]; const item = row.values; if (item == null) { return; @@ -1549,6 +1531,15 @@ class Grid { } if (enabled !== false) { item[col.key] = value; + let tip = col.tooltip; + if (typeof tip === 'function') { + tip = tip.call(col, item); + } + if (nullOrEmpty(tip)) { + cell.querySelector('.ui-tooltip-wrapper')?.remove(); + } else { + setTooltip(cell.children[0], tip, false, this.element); + } row.__changed = true; if (blur) { if (typeof col.oneditend === 'function') {