Fix data table worker (#5921)

This commit is contained in:
Bram Kragten 2020-05-19 13:59:16 +02:00 committed by GitHub
parent bbc16b6bc8
commit d9bb40f934
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 52 deletions

View File

@ -21,7 +21,8 @@ import { nextRender } from "../../common/util/render-status";
import "../ha-checkbox"; import "../ha-checkbox";
import type { HaCheckbox } from "../ha-checkbox"; import type { HaCheckbox } from "../ha-checkbox";
import "../ha-icon"; import "../ha-icon";
import { filterSortData } from "./sort-filter"; import { filterData, sortData } from "./sort-filter";
import memoizeOne from "memoize-one";
declare global { declare global {
// for fire event // for fire event
@ -72,6 +73,10 @@ export interface DataTableRowData {
selectable?: boolean; selectable?: boolean;
} }
export interface SortableColumnContainer {
[key: string]: DataTableSortColumnData;
}
@customElement("ha-data-table") @customElement("ha-data-table")
export class HaDataTable extends LitElement { export class HaDataTable extends LitElement {
@property({ type: Object }) public columns: DataTableColumnContainer = {}; @property({ type: Object }) public columns: DataTableColumnContainer = {};
@ -109,9 +114,7 @@ export class HaDataTable extends LitElement {
private _checkedRows: string[] = []; private _checkedRows: string[] = [];
private _sortColumns: { private _sortColumns: SortableColumnContainer = {};
[key: string]: DataTableSortColumnData;
} = {};
private curRequest = 0; private curRequest = 0;
@ -179,7 +182,7 @@ export class HaDataTable extends LitElement {
properties.has("_sortColumn") || properties.has("_sortColumn") ||
properties.has("_sortDirection") properties.has("_sortDirection")
) { ) {
this._filterData(); this._sortFilterData();
} }
} }
@ -369,20 +372,30 @@ export class HaDataTable extends LitElement {
`; `;
} }
private async _filterData() { private async _sortFilterData() {
const startTime = new Date().getTime(); const startTime = new Date().getTime();
this.curRequest++; this.curRequest++;
const curRequest = this.curRequest; const curRequest = this.curRequest;
const filterProm = filterSortData( let filteredData = this.data;
if (this._filter) {
filteredData = await this._memFilterData(
this.data, this.data,
this._sortColumns, this._sortColumns,
this._filter, this.filter
);
}
const prom = this._sortColumn
? sortData(
filteredData,
this._sortColumns,
this._sortDirection, this._sortDirection,
this._sortColumn this._sortColumn
); )
: filteredData;
const [data] = await Promise.all([filterProm, nextRender]); const [data] = await Promise.all([prom, nextRender]);
const curTime = new Date().getTime(); const curTime = new Date().getTime();
const elapsed = curTime - startTime; const elapsed = curTime - startTime;
@ -396,6 +409,16 @@ export class HaDataTable extends LitElement {
this._filteredData = data; this._filteredData = data;
} }
private _memFilterData = memoizeOne(
async (
data: DataTableRowData[],
columns: SortableColumnContainer,
filter: string
): Promise<DataTableRowData[]> => {
return filterData(data, columns, filter);
}
);
private _handleHeaderClick(ev: Event) { private _handleHeaderClick(ev: Event) {
const columnId = ((ev.target as HTMLElement).closest( const columnId = ((ev.target as HTMLElement).closest(
".mdc-data-table__header-cell" ".mdc-data-table__header-cell"

View File

@ -1,26 +1,34 @@
import { wrap } from "comlink"; import { wrap } from "comlink";
type FilterSortDataType = typeof import("./sort_filter_worker").api["filterSortData"]; type FilterDataType = typeof import("./sort_filter_worker").api["filterData"];
type filterSortDataParamTypes = Parameters<FilterSortDataType>; type FilterDataParamTypes = Parameters<FilterDataType>;
type SortDataType = typeof import("./sort_filter_worker").api["sortData"];
type SortDataParamTypes = Parameters<SortDataType>;
let worker: any | undefined; let worker: any | undefined;
export const filterSortData = async ( export const filterData = async (
data: filterSortDataParamTypes[0], data: FilterDataParamTypes[0],
columns: filterSortDataParamTypes[1], columns: FilterDataParamTypes[1],
filter: filterSortDataParamTypes[2], filter: FilterDataParamTypes[2]
direction: filterSortDataParamTypes[3], ): Promise<ReturnType<FilterDataType>> => {
sortColumn: filterSortDataParamTypes[4]
): Promise<ReturnType<FilterSortDataType>> => {
if (!worker) { if (!worker) {
worker = wrap(new Worker("./sort_filter_worker", { type: "module" })); worker = wrap(new Worker("./sort_filter_worker", { type: "module" }));
} }
return await worker.filterSortData( return await worker.filterData(data, columns, filter);
data, };
columns,
filter, export const sortData = async (
direction, data: SortDataParamTypes[0],
sortColumn columns: SortDataParamTypes[1],
); direction: SortDataParamTypes[2],
sortColumn: SortDataParamTypes[3]
): Promise<ReturnType<SortDataType>> => {
if (!worker) {
worker = wrap(new Worker("./sort_filter_worker", { type: "module" }));
}
return await worker.sortData(data, columns, direction, sortColumn);
}; };

View File

@ -5,33 +5,16 @@ import type {
DataTableSortColumnData, DataTableSortColumnData,
DataTableRowData, DataTableRowData,
SortingDirection, SortingDirection,
HaDataTable, SortableColumnContainer,
} from "./ha-data-table"; } from "./ha-data-table";
type SortableColumnContainer = HaDataTable["_sortColumns"];
const filterSortData = (
data: DataTableRowData[],
columns: SortableColumnContainer,
filter: string,
direction: SortingDirection,
sortColumn?: string
) => {
const filteredData = filter ? filterData(data, columns, filter) : data;
if (!sortColumn) {
return filteredData;
}
return sortData(filteredData, columns, direction, sortColumn);
};
const filterData = ( const filterData = (
data: DataTableRowData[], data: DataTableRowData[],
columns: SortableColumnContainer, columns: SortableColumnContainer,
filter: string filter: string
) => ) => {
data.filter((row) => { filter = filter.toUpperCase();
return data.filter((row) => {
return Object.entries(columns).some((columnEntry) => { return Object.entries(columns).some((columnEntry) => {
const [key, column] = columnEntry; const [key, column] = columnEntry;
if (column.filterable) { if (column.filterable) {
@ -46,6 +29,7 @@ const filterData = (
return false; return false;
}); });
}); });
};
const sortData = ( const sortData = (
data: DataTableRowData[], data: DataTableRowData[],
@ -85,7 +69,8 @@ const sortData = (
// Export for types // Export for types
export const api = { export const api = {
filterSortData, filterData,
sortData,
}; };
expose(api); expose(api);