list: fix RecordCounter, inf scroll in search, activities
This commit is contained in:
@@ -977,7 +977,7 @@ export class accountsList extends PaginatedList {
|
|||||||
this._populateNumbers();
|
this._populateNumbers();
|
||||||
|
|
||||||
// FIXME: Remove!
|
// FIXME: Remove!
|
||||||
(window as any).s = this;
|
(window as any).acc = this;
|
||||||
|
|
||||||
let searchConfig: SearchConfiguration = {
|
let searchConfig: SearchConfiguration = {
|
||||||
filterArea: this._c.filterArea,
|
filterArea: this._c.filterArea,
|
||||||
@@ -988,10 +988,10 @@ export class accountsList extends PaginatedList {
|
|||||||
filterList: document.getElementById("accounts-filter-list"),
|
filterList: document.getElementById("accounts-filter-list"),
|
||||||
search: this._c.searchBox,
|
search: this._c.searchBox,
|
||||||
queries: queries(),
|
queries: queries(),
|
||||||
setVisibility: this.setVisibility,
|
setVisibility: null,
|
||||||
clearSearchButtonSelector: ".accounts-search-clear",
|
clearSearchButtonSelector: ".accounts-search-clear",
|
||||||
serverSearchButtonSelector: ".accounts-search-server",
|
serverSearchButtonSelector: ".accounts-search-server",
|
||||||
onSearchCallback: (_0: number, _1: boolean, _2: boolean) => {
|
onSearchCallback: (_0: boolean, _1: boolean) => {
|
||||||
this._checkCheckCount();
|
this._checkCheckCount();
|
||||||
},
|
},
|
||||||
searchServer: null,
|
searchServer: null,
|
||||||
|
|||||||
@@ -509,13 +509,13 @@ export class activityList extends PaginatedList {
|
|||||||
this.activities[act.id] = new Activity(act);
|
this.activities[act.id] = new Activity(act);
|
||||||
ordering.push(act.id);
|
ordering.push(act.id);
|
||||||
}
|
}
|
||||||
|
this._search.setOrdering(ordering, this._c.defaultSortField, this.ascending);
|
||||||
},
|
},
|
||||||
updateExistingElementsFromPage: (resp: paginatedDTO) => {
|
updateExistingElementsFromPage: (resp: paginatedDTO) => {
|
||||||
// FIXME: Implement updates to existing elements!
|
// FIXME: Implement updates to existing elements, rather than just wiping each time.
|
||||||
for (let id of Object.keys(this.activities)) {
|
for (let id of Object.keys(this.activities)) {
|
||||||
delete this.activities[id];
|
delete this.activities[id];
|
||||||
}
|
}
|
||||||
this._search.setOrdering([], this._c.defaultSortField, this.ascending);
|
|
||||||
this._c.newElementsFromPage(resp);
|
this._c.newElementsFromPage(resp);
|
||||||
},
|
},
|
||||||
defaultSortField: ACTIVITY_DEFAULT_SORT_FIELD,
|
defaultSortField: ACTIVITY_DEFAULT_SORT_FIELD,
|
||||||
@@ -529,6 +529,9 @@ export class activityList extends PaginatedList {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// FIXME: Remove!
|
||||||
|
(window as any).act = this;
|
||||||
|
|
||||||
this._container = document.getElementById("activity-card-list")
|
this._container = document.getElementById("activity-card-list")
|
||||||
document.addEventListener("activity-reload", this.reload);
|
document.addEventListener("activity-reload", this.reload);
|
||||||
|
|
||||||
@@ -543,7 +546,7 @@ export class activityList extends PaginatedList {
|
|||||||
clearSearchButtonSelector: ".activity-search-clear",
|
clearSearchButtonSelector: ".activity-search-clear",
|
||||||
serverSearchButtonSelector: ".activity-search-server",
|
serverSearchButtonSelector: ".activity-search-server",
|
||||||
queries: queries(),
|
queries: queries(),
|
||||||
setVisibility: this.setVisibility,
|
setVisibility: null,
|
||||||
filterList: document.getElementById("activity-filter-list"),
|
filterList: document.getElementById("activity-filter-list"),
|
||||||
// notFoundCallback: this._notFoundCallback,
|
// notFoundCallback: this._notFoundCallback,
|
||||||
onSearchCallback: null,
|
onSearchCallback: null,
|
||||||
|
|||||||
+40
-41
@@ -22,10 +22,10 @@ export class RecordCounter {
|
|||||||
<span class="records-shown"></span>
|
<span class="records-shown"></span>
|
||||||
<span class="records-selected"></span>
|
<span class="records-selected"></span>
|
||||||
`;
|
`;
|
||||||
this._totalRecords = document.getElementsByClassName("records-total")[0] as HTMLElement;
|
this._totalRecords = this._container.getElementsByClassName("records-total")[0] as HTMLElement;
|
||||||
this._loadedRecords = document.getElementsByClassName("records-loaded")[0] as HTMLElement;
|
this._loadedRecords = this._container.getElementsByClassName("records-loaded")[0] as HTMLElement;
|
||||||
this._shownRecords = document.getElementsByClassName("records-shown")[0] as HTMLElement;
|
this._shownRecords = this._container.getElementsByClassName("records-shown")[0] as HTMLElement;
|
||||||
this._selectedRecords = document.getElementsByClassName("records-selected")[0] as HTMLElement;
|
this._selectedRecords = this._container.getElementsByClassName("records-selected")[0] as HTMLElement;
|
||||||
this.total = 0;
|
this.total = 0;
|
||||||
this.loaded = 0;
|
this.loaded = 0;
|
||||||
this.shown = 0;
|
this.shown = 0;
|
||||||
@@ -138,7 +138,7 @@ export abstract class PaginatedList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _previousPageSize = 0;
|
protected _previousVisibleItemCount = 0;
|
||||||
|
|
||||||
// Stores a PaginatedReqDTO-implementing thing.
|
// Stores a PaginatedReqDTO-implementing thing.
|
||||||
// A standard PaginatedReqDTO will be overridden entirely,
|
// A standard PaginatedReqDTO will be overridden entirely,
|
||||||
@@ -173,9 +173,7 @@ export abstract class PaginatedList {
|
|||||||
|
|
||||||
initSearch = (searchConfig: SearchConfiguration) => {
|
initSearch = (searchConfig: SearchConfiguration) => {
|
||||||
const previousCallback = searchConfig.onSearchCallback;
|
const previousCallback = searchConfig.onSearchCallback;
|
||||||
searchConfig.onSearchCallback = (visibleCount: number, newItems: boolean, loadAll: boolean) => {
|
searchConfig.onSearchCallback = (newItems: boolean, loadAll: boolean) => {
|
||||||
this._counter.shown = visibleCount;
|
|
||||||
|
|
||||||
// if (this._search.inSearch && !this.lastPage) this._c.loadAllButton.classList.remove("unfocused");
|
// if (this._search.inSearch && !this.lastPage) this._c.loadAllButton.classList.remove("unfocused");
|
||||||
// else this._c.loadAllButton.classList.add("unfocused");
|
// else this._c.loadAllButton.classList.add("unfocused");
|
||||||
|
|
||||||
@@ -186,17 +184,17 @@ export abstract class PaginatedList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Figure out why this makes sense and make it clearer.
|
// FIXME: Figure out why this makes sense and make it clearer.
|
||||||
if ((visibleCount < this._c.itemsPerPage && this._counter.loaded < this._c.maxItemsLoadedForSearch && !this.lastPage) || loadAll) {
|
if ((this._visible.length < this._c.itemsPerPage && this._counter.loaded < this._c.maxItemsLoadedForSearch && !this.lastPage) || loadAll) {
|
||||||
if (!newItems ||
|
if (!newItems ||
|
||||||
this._previousPageSize != visibleCount ||
|
this._previousVisibleItemCount != this._visible.length ||
|
||||||
(visibleCount == 0 && !this.lastPage) ||
|
(this._visible.length == 0 && !this.lastPage) ||
|
||||||
loadAll
|
loadAll
|
||||||
) {
|
) {
|
||||||
this.loadMore(() => {}, loadAll);
|
this.loadMore(() => {}, loadAll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._previousPageSize = visibleCount;
|
this._previousVisibleItemCount = this._visible.length;
|
||||||
if (previousCallback) previousCallback(visibleCount, newItems, loadAll);
|
if (previousCallback) previousCallback(newItems, loadAll);
|
||||||
};
|
};
|
||||||
const previousServerSearch = searchConfig.searchServer;
|
const previousServerSearch = searchConfig.searchServer;
|
||||||
searchConfig.searchServer = (params: PaginatedReqDTO, newSearch: boolean) => {
|
searchConfig.searchServer = (params: PaginatedReqDTO, newSearch: boolean) => {
|
||||||
@@ -211,28 +209,28 @@ export abstract class PaginatedList {
|
|||||||
this._page = 0;
|
this._page = 0;
|
||||||
this.reload();
|
this.reload();
|
||||||
}
|
}
|
||||||
|
searchConfig.setVisibility = this.setVisibility;
|
||||||
this._search = new Search(searchConfig);
|
this._search = new Search(searchConfig);
|
||||||
this._search.generateFilterList();
|
this._search.generateFilterList();
|
||||||
this.lastPage = false;
|
this.lastPage = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sets the elements with "name"s in "elements" as visible or not.
|
// Sets the elements with "name"s in "elements" as visible or not.
|
||||||
setVisibilityNaive = (elements: string[], visible: boolean) => {
|
// setVisibilityNaive = (elements: string[], visible: boolean) => {
|
||||||
let timer = this._search.timeSearches ? performance.now() : null;
|
// let timer = this._search.timeSearches ? performance.now() : null;
|
||||||
if (visible) this._visible = elements;
|
// if (visible) this._visible = elements;
|
||||||
else this._visible = this._search.ordering.filter(v => !elements.includes(v));
|
// else this._visible = this._search.ordering.filter(v => !elements.includes(v));
|
||||||
const frag = document.createDocumentFragment()
|
// const frag = document.createDocumentFragment()
|
||||||
for (let i = 0; i < this._visible.length; i++) {
|
// for (let i = 0; i < this._visible.length; i++) {
|
||||||
frag.appendChild(this._search.items[this._visible[i]].asElement())
|
// frag.appendChild(this._search.items[this._visible[i]].asElement())
|
||||||
}
|
// }
|
||||||
this._container.replaceChildren(frag);
|
// this._container.replaceChildren(frag);
|
||||||
if (this._search.timeSearches) {
|
// if (this._search.timeSearches) {
|
||||||
const totalTime = performance.now() - timer;
|
// const totalTime = performance.now() - timer;
|
||||||
console.log(`setVisibility took ${totalTime}ms`);
|
// console.log(`setVisibility took ${totalTime}ms`);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// FIXME: On reload, load enough pages to fill required space.
|
|
||||||
// FIXME: Might have broken _counter.shown!
|
// FIXME: Might have broken _counter.shown!
|
||||||
// Sets the elements with "name"s in "elements" as visible or not.
|
// Sets the elements with "name"s in "elements" as visible or not.
|
||||||
// appendedItems==true implies "elements" is the previously rendered elements plus some new ones on the end. Knowing this means the page's infinite scroll doesn't have to be reset.
|
// appendedItems==true implies "elements" is the previously rendered elements plus some new ones on the end. Knowing this means the page's infinite scroll doesn't have to be reset.
|
||||||
@@ -240,7 +238,12 @@ export abstract class PaginatedList {
|
|||||||
let timer = this._search.timeSearches ? performance.now() : null;
|
let timer = this._search.timeSearches ? performance.now() : null;
|
||||||
if (visible) this._visible = elements;
|
if (visible) this._visible = elements;
|
||||||
else this._visible = this._search.ordering.filter(v => !elements.includes(v));
|
else this._visible = this._search.ordering.filter(v => !elements.includes(v));
|
||||||
if (this._visible.length == 0) return;
|
console.log(elements.length, visible, this._visible.length);
|
||||||
|
this._counter.shown = this._visible.length;
|
||||||
|
if (this._visible.length == 0) {
|
||||||
|
this._container.textContent = ``;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!appendedItems) {
|
if (!appendedItems) {
|
||||||
// Wipe old elements and render 1 new one, so we can take the element height.
|
// Wipe old elements and render 1 new one, so we can take the element height.
|
||||||
@@ -277,6 +280,8 @@ export abstract class PaginatedList {
|
|||||||
|
|
||||||
// Computes required scroll info, requiring one on-DOM item. Should be computed on page resize and this._visible change.
|
// Computes required scroll info, requiring one on-DOM item. Should be computed on page resize and this._visible change.
|
||||||
_computeScrollInfo = () => {
|
_computeScrollInfo = () => {
|
||||||
|
if (this._visible.length == 0) return;
|
||||||
|
|
||||||
this._scroll.screenHeight = Math.max(
|
this._scroll.screenHeight = Math.max(
|
||||||
document.documentElement.clientHeight,
|
document.documentElement.clientHeight,
|
||||||
window.innerHeight || 0
|
window.innerHeight || 0
|
||||||
@@ -340,7 +345,7 @@ export abstract class PaginatedList {
|
|||||||
|
|
||||||
this._counter.loaded = this._search.ordering.length;
|
this._counter.loaded = this._search.ordering.length;
|
||||||
|
|
||||||
this._search.onSearchBoxChange(true);
|
this._search.onSearchBoxChange(true, false, false);
|
||||||
if (this._search.inSearch) {
|
if (this._search.inSearch) {
|
||||||
// this._c.loadAllButton.classList.remove("unfocused");
|
// this._c.loadAllButton.classList.remove("unfocused");
|
||||||
} else {
|
} else {
|
||||||
@@ -400,7 +405,7 @@ export abstract class PaginatedList {
|
|||||||
if (this.lastPage) {
|
if (this.lastPage) {
|
||||||
loadAll = false;
|
loadAll = false;
|
||||||
}
|
}
|
||||||
this._search.onSearchBoxChange(true, loadAll);
|
this._search.onSearchBoxChange(true, true, loadAll);
|
||||||
} else {
|
} else {
|
||||||
// Since results come to us ordered already, we can assume "ordering"
|
// Since results come to us ordered already, we can assume "ordering"
|
||||||
// will be identical to pre-page-load but with extra elements at the end,
|
// will be identical to pre-page-load but with extra elements at the end,
|
||||||
@@ -423,15 +428,14 @@ export abstract class PaginatedList {
|
|||||||
|
|
||||||
// As reloading can disrupt long-scrolling, this function will only do it if you're at the top of the page, essentially.
|
// As reloading can disrupt long-scrolling, this function will only do it if you're at the top of the page, essentially.
|
||||||
public reloadIfNotInScroll = () => {
|
public reloadIfNotInScroll = () => {
|
||||||
if (this.maximumItemsToRender(window.scrollY) < this._scroll.initialRenderCount) {
|
if (this._visible.length == 0 || this.maximumItemsToRender(window.scrollY) < this._scroll.initialRenderCount) {
|
||||||
return this.reload();
|
return this.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_detectScroll = () => {
|
_detectScroll = () => {
|
||||||
if (!this._hasLoaded || this._scroll.scrollLoading) return;
|
if (!this._hasLoaded || this._scroll.scrollLoading || this._visible.length == 0) return;
|
||||||
if (this._visible.length == 0) return;
|
|
||||||
const scrollY = window.scrollY;
|
const scrollY = window.scrollY;
|
||||||
const scrollSpeed = scrollY - this._scroll.lastScrollY;
|
const scrollSpeed = scrollY - this._scroll.lastScrollY;
|
||||||
this._scroll.lastScrollY = scrollY;
|
this._scroll.lastScrollY = scrollY;
|
||||||
@@ -460,6 +464,7 @@ export abstract class PaginatedList {
|
|||||||
this._scroll.scrollLoading = true;
|
this._scroll.scrollLoading = true;
|
||||||
const cb = () => {
|
const cb = () => {
|
||||||
if (this._visible.length < endIdx && !this.lastPage) {
|
if (this._visible.length < endIdx && !this.lastPage) {
|
||||||
|
// FIXME: This causes scroll-to-top when in search.
|
||||||
this.loadMore(cb, false)
|
this.loadMore(cb, false)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -472,17 +477,11 @@ export abstract class PaginatedList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should be assigned to window.onscroll whenever the list is in view.
|
|
||||||
detectScroll = throttle(this._detectScroll, 200);
|
detectScroll = throttle(this._detectScroll, 200);
|
||||||
|
|
||||||
computeScrollInfo = throttle(this._computeScrollInfo, 200);
|
computeScrollInfo = throttle(this._computeScrollInfo, 200);
|
||||||
|
|
||||||
// Should be called in window resize
|
redrawScroll = this.computeScrollInfo;
|
||||||
redrawScroll = throttle(() => {
|
|
||||||
// FIXME: Make sure this is enough when rows resize, and that we don't need to re-setVisibility.
|
|
||||||
this._computeScrollInfo();
|
|
||||||
// this.setVisibility(this._visible, true, false);
|
|
||||||
}, 200);
|
|
||||||
|
|
||||||
// bindPageEvents binds window event handlers for when this list/tab containing it is visible.
|
// bindPageEvents binds window event handlers for when this list/tab containing it is visible.
|
||||||
bindPageEvents = () => {
|
bindPageEvents = () => {
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ export interface SearchConfiguration {
|
|||||||
serverSearchButtonSelector: string;
|
serverSearchButtonSelector: string;
|
||||||
search: HTMLInputElement;
|
search: HTMLInputElement;
|
||||||
queries: { [field: string]: QueryType };
|
queries: { [field: string]: QueryType };
|
||||||
setVisibility: (items: string[], visible: boolean) => void;
|
setVisibility: (items: string[], visible: boolean, appendedItems: boolean) => void;
|
||||||
onSearchCallback: (visibleCount: number, newItems: boolean, loadAll: boolean) => void;
|
onSearchCallback: (newItems: boolean, loadAll: boolean) => void;
|
||||||
searchServer: (params: PaginatedReqDTO, newSearch: boolean) => void;
|
searchServer: (params: PaginatedReqDTO, newSearch: boolean) => void;
|
||||||
clearServerSearch: () => void;
|
clearServerSearch: () => void;
|
||||||
loadMore?: () => void;
|
loadMore?: () => void;
|
||||||
@@ -505,7 +505,7 @@ export class Search {
|
|||||||
get sortField(): string { return this._sortField; }
|
get sortField(): string { return this._sortField; }
|
||||||
get ascending(): boolean { return this._ascending; }
|
get ascending(): boolean { return this._ascending; }
|
||||||
|
|
||||||
onSearchBoxChange = (newItems: boolean = false, loadAll: boolean = false) => {
|
onSearchBoxChange = (newItems: boolean = false, appendedItems: boolean = false, loadAll: boolean = false) => {
|
||||||
const query = this._c.search.value;
|
const query = this._c.search.value;
|
||||||
if (!query) {
|
if (!query) {
|
||||||
this.inSearch = false;
|
this.inSearch = false;
|
||||||
@@ -513,8 +513,8 @@ export class Search {
|
|||||||
this.inSearch = true;
|
this.inSearch = true;
|
||||||
}
|
}
|
||||||
const results = this.search(query);
|
const results = this.search(query);
|
||||||
this._c.setVisibility(results, true);
|
this._c.setVisibility(results, true, appendedItems);
|
||||||
this._c.onSearchCallback(results.length, newItems, loadAll);
|
this._c.onSearchCallback(newItems, loadAll);
|
||||||
if (this.inSearch) {
|
if (this.inSearch) {
|
||||||
if (this.inServerSearch) {
|
if (this.inServerSearch) {
|
||||||
this._serverSearchButtons.forEach((v: HTMLElement) => {
|
this._serverSearchButtons.forEach((v: HTMLElement) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user