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
1 changed files with 38 additions and 18 deletions

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()
// Instead we default to comparing the JSON of both objects, which is quite slow
// Hence we check if the objects have `pk` attributes set (as most models do)
// and compare that instead, which will be much faster.
let comp = (item: T) => {
return JSON.stringify(item) === jsonRes;
};
if ("pk" in res) {
comp = (item: T) => {
return (
(item as unknown as { pk: string | number }).pk ===
(res as unknown as { pk: string | number }).pk
);
};
} }
const expandedIndex = this.expandedElements.indexOf(res);
if (expandedIndex <= -1) { const selectedIndex = this.selectedElements.findIndex(comp);
this.expandedElements.splice(expandedIndex, 1); if (selectedIndex > -1) {
newSelected.push(res);
}
const expandedIndex = this.expandedElements.findIndex(comp);
if (expandedIndex > -1) {
newExpanded.push(res);
} }
}); });
this.isLoading = false; this.isLoading = false;
}) this.selectedElements = newSelected;
.catch(() => { this.expandedElements = newExpanded;
} catch {
this.isLoading = false; this.isLoading = false;
}); }
} }
private renderLoading(): TemplateResult { private renderLoading(): TemplateResult {