web/admin: refactor table refresh to preserve selected/expanded elements correctly

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2022-05-23 20:07:56 +02:00
parent b2a42a68a4
commit 94257e0f50

View file

@ -168,25 +168,45 @@ export abstract class Table<T> extends LitElement {
return; return;
} }
this.isLoading = true; this.isLoading = true;
return this.apiEndpoint(this.page) try {
.then((r) => { this.data = await this.apiEndpoint(this.page);
this.data = r; this.page = this.data.pagination.current;
this.page = r.pagination.current; const newSelected: T[] = [];
r.results.forEach((res) => { const newExpanded: T[] = [];
const selectedIndex = this.selectedElements.indexOf(res); this.data.results.forEach((res) => {
if (selectedIndex <= -1) { const jsonRes = JSON.stringify(res);
this.selectedElements.splice(selectedIndex, 1); // So because we're dealing with complex objects here, we can't use indexOf
} // since it checks strict equality, and we also can't easily check in findIndex()
const expandedIndex = this.expandedElements.indexOf(res); // Instead we default to comparing the JSON of both objects, which is quite slow
if (expandedIndex <= -1) { // Hence we check if the objects have `pk` attributes set (as most models do)
this.expandedElements.splice(expandedIndex, 1); // and compare that instead, which will be much faster.
} let comp = (item: T) => {
}); return JSON.stringify(item) === jsonRes;
this.isLoading = false; };
}) if ("pk" in res) {
.catch(() => { comp = (item: T) => {
this.isLoading = false; return (
(item as unknown as { pk: string | number }).pk ===
(res as unknown as { pk: string | number }).pk
);
};
}
const selectedIndex = this.selectedElements.findIndex(comp);
if (selectedIndex > -1) {
newSelected.push(res);
}
const expandedIndex = this.expandedElements.findIndex(comp);
if (expandedIndex > -1) {
newExpanded.push(res);
}
}); });
this.isLoading = false;
this.selectedElements = newSelected;
this.expandedElements = newExpanded;
} catch {
this.isLoading = false;
}
} }
private renderLoading(): TemplateResult { private renderLoading(): TemplateResult {