Change update logic in ha-data-table (#21874)

* Change update logic in ha-data-table

* use time of last request
This commit is contained in:
Bram Kragten 2024-09-04 10:49:32 +02:00 committed by GitHub
parent 7aa7019386
commit 76fc0c7ab1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -25,7 +25,6 @@ import { fireEvent } from "../../common/dom/fire_event";
import { stringCompare } from "../../common/string/compare"; import { stringCompare } from "../../common/string/compare";
import { debounce } from "../../common/util/debounce"; import { debounce } from "../../common/util/debounce";
import { groupBy } from "../../common/util/group-by"; import { groupBy } from "../../common/util/group-by";
import { nextRender } from "../../common/util/render-status";
import { haStyleScrollbar } from "../../resources/styles"; import { haStyleScrollbar } from "../../resources/styles";
import { loadVirtualizer } from "../../resources/virtualizer"; import { loadVirtualizer } from "../../resources/virtualizer";
import { HomeAssistant } from "../../types"; import { HomeAssistant } from "../../types";
@ -35,6 +34,7 @@ import "../ha-svg-icon";
import "../search-input"; import "../search-input";
import { filterData, sortData } from "./sort-filter"; import { filterData, sortData } from "./sort-filter";
import { LocalizeFunc } from "../../common/translations/localize"; import { LocalizeFunc } from "../../common/translations/localize";
import { nextRender } from "../../common/util/render-status";
export interface RowClickedEvent { export interface RowClickedEvent {
id: string; id: string;
@ -169,8 +169,6 @@ export class HaDataTable extends LitElement {
@query("slot[name='header']") private _header!: HTMLSlotElement; @query("slot[name='header']") private _header!: HTMLSlotElement;
@state() private _items: DataTableRowData[] = [];
@state() private _collapsedGroups: string[] = []; @state() private _collapsedGroups: string[] = [];
private _checkableRowsCount?: number; private _checkableRowsCount?: number;
@ -179,7 +177,9 @@ export class HaDataTable extends LitElement {
private _sortColumns: SortableColumnContainer = {}; private _sortColumns: SortableColumnContainer = {};
private curRequest = 0; private _curRequest = 0;
private _lastUpdate = 0;
// @ts-ignore // @ts-ignore
@restoreScroll(".scroller") private _savedScrollPos?: number; @restoreScroll(".scroller") private _savedScrollPos?: number;
@ -206,9 +206,9 @@ export class HaDataTable extends LitElement {
public connectedCallback() { public connectedCallback() {
super.connectedCallback(); super.connectedCallback();
if (this._items.length) { if (this._filteredData.length) {
// Force update of location of rows // Force update of location of rows
this._items = [...this._items]; this._filteredData = [...this._filteredData];
} }
} }
@ -291,16 +291,13 @@ export class HaDataTable extends LitElement {
properties.has("columns") || properties.has("columns") ||
properties.has("_filter") || properties.has("_filter") ||
properties.has("sortColumn") || properties.has("sortColumn") ||
properties.has("sortDirection") || properties.has("sortDirection")
properties.has("groupColumn") ||
properties.has("groupOrder") ||
properties.has("_collapsedGroups")
) { ) {
this._sortFilterData(); this._sortFilterData();
} }
if (properties.has("selectable") || properties.has("hiddenColumns")) { if (properties.has("selectable") || properties.has("hiddenColumns")) {
this._items = [...this._items]; this._filteredData = [...this._filteredData];
} }
} }
@ -467,7 +464,15 @@ export class HaDataTable extends LitElement {
scroller scroller
class="mdc-data-table__content scroller ha-scrollbar" class="mdc-data-table__content scroller ha-scrollbar"
@scroll=${this._saveScrollPos} @scroll=${this._saveScrollPos}
.items=${this._items} .items=${this._groupData(
this._filteredData,
localize,
this.appendRow,
this.hasFab,
this.groupColumn,
this.groupOrder,
this._collapsedGroups
)}
.keyFunction=${this._keyFunction} .keyFunction=${this._keyFunction}
.renderItem=${renderRow} .renderItem=${renderRow}
></lit-virtualizer> ></lit-virtualizer>
@ -602,8 +607,13 @@ export class HaDataTable extends LitElement {
private async _sortFilterData() { private async _sortFilterData() {
const startTime = new Date().getTime(); const startTime = new Date().getTime();
this.curRequest++; const timeBetweenUpdate = startTime - this._lastUpdate;
const curRequest = this.curRequest; const timeBetweenRequest = startTime - this._curRequest;
this._curRequest = startTime;
const forceUpdate =
!this._lastUpdate ||
(timeBetweenUpdate > 500 && timeBetweenRequest < 500);
let filteredData = this.data; let filteredData = this.data;
if (this._filter) { if (this._filter) {
@ -614,6 +624,10 @@ export class HaDataTable extends LitElement {
); );
} }
if (!forceUpdate && this._curRequest !== startTime) {
return;
}
const prom = this.sortColumn const prom = this.sortColumn
? sortData( ? sortData(
filteredData, filteredData,
@ -634,17 +648,30 @@ export class HaDataTable extends LitElement {
setTimeout(resolve, 100 - elapsed); setTimeout(resolve, 100 - elapsed);
}); });
} }
if (this.curRequest !== curRequest) {
if (!forceUpdate && this._curRequest !== startTime) {
return; return;
} }
const localize = this.localizeFunc || this.hass.localize; this._lastUpdate = startTime;
this._filteredData = data;
}
if (this.appendRow || this.hasFab || this.groupColumn) { private _groupData = memoizeOne(
(
data: DataTableRowData[],
localize: LocalizeFunc,
appendRow,
hasFab: boolean,
groupColumn: string | undefined,
groupOrder: string[] | undefined,
collapsedGroups: string[]
) => {
if (appendRow || hasFab || groupColumn) {
let items = [...data]; let items = [...data];
if (this.groupColumn) { if (groupColumn) {
const grouped = groupBy(items, (item) => item[this.groupColumn!]); const grouped = groupBy(items, (item) => item[groupColumn]);
if (grouped.undefined) { if (grouped.undefined) {
// make sure ungrouped items are at the bottom // make sure ungrouped items are at the bottom
grouped[UNDEFINED_GROUP_KEY] = grouped.undefined; grouped[UNDEFINED_GROUP_KEY] = grouped.undefined;
@ -654,8 +681,8 @@ export class HaDataTable extends LitElement {
[key: string]: DataTableRowData[]; [key: string]: DataTableRowData[];
} = Object.keys(grouped) } = Object.keys(grouped)
.sort((a, b) => { .sort((a, b) => {
const orderA = this.groupOrder?.indexOf(a) ?? -1; const orderA = groupOrder?.indexOf(a) ?? -1;
const orderB = this.groupOrder?.indexOf(b) ?? -1; const orderB = groupOrder?.indexOf(b) ?? -1;
if (orderA !== orderB) { if (orderA !== orderB) {
if (orderA === -1) { if (orderA === -1) {
return 1; return 1;
@ -687,7 +714,7 @@ export class HaDataTable extends LitElement {
> >
<ha-icon-button <ha-icon-button
.path=${mdiChevronUp} .path=${mdiChevronUp}
class=${this._collapsedGroups.includes(groupName) class=${collapsedGroups.includes(groupName)
? "collapsed" ? "collapsed"
: ""} : ""}
> >
@ -697,27 +724,26 @@ export class HaDataTable extends LitElement {
: groupName || ""} : groupName || ""}
</div>`, </div>`,
}); });
if (!this._collapsedGroups.includes(groupName)) { if (!collapsedGroups.includes(groupName)) {
groupedItems.push(...rows); groupedItems.push(...rows);
} }
}); });
items = groupedItems; items = groupedItems;
} }
if (this.appendRow) { if (appendRow) {
items.push({ append: true, content: this.appendRow }); items.push({ append: true, content: appendRow });
} }
if (this.hasFab) { if (hasFab) {
items.push({ empty: true }); items.push({ empty: true });
} }
this._items = items; return items;
} else {
this._items = data;
} }
this._filteredData = data; return data;
} }
);
private _memFilterData = memoizeOne( private _memFilterData = memoizeOne(
( (
@ -802,8 +828,8 @@ export class HaDataTable extends LitElement {
private _checkedRowsChanged() { private _checkedRowsChanged() {
// force scroller to update, change it's items // force scroller to update, change it's items
if (this._items.length) { if (this._filteredData.length) {
this._items = [...this._items]; this._filteredData = [...this._filteredData];
} }
fireEvent(this, "selection-changed", { fireEvent(this, "selection-changed", {
value: this._checkedRows, value: this._checkedRows,