fix: Sort filtered collection page URLs (#2384)
Fixes https://github.com/webrecorder/browsertrix/issues/2383 - Fixes unpredictable sort order when typing in collection page URL - Fixes page URL results flickering in and out while typing --------- Co-authored-by: Tessa Walsh <tessa@bitarchivist.net>
This commit is contained in:
parent
5b02d81991
commit
f7b9b73a68
@ -755,7 +755,7 @@ class CollectionOps:
|
||||
page_size: int = DEFAULT_PAGE_SIZE,
|
||||
page: int = 1,
|
||||
) -> Tuple[List[PageUrlCount], int]:
|
||||
"""List all URLs in collection sorted desc by snapshot count"""
|
||||
"""List all URLs in collection sorted desc by snapshot count unless prefix is specified"""
|
||||
# pylint: disable=duplicate-code, too-many-locals, too-many-branches, too-many-statements
|
||||
# Zero-index page for query
|
||||
page = page - 1
|
||||
@ -764,13 +764,15 @@ class CollectionOps:
|
||||
crawl_ids = await self.get_collection_crawl_ids(coll_id)
|
||||
|
||||
match_query: dict[str, object] = {"oid": oid, "crawl_id": {"$in": crawl_ids}}
|
||||
sort_query: dict[str, int] = {"count": -1, "_id": 1}
|
||||
|
||||
if url_prefix:
|
||||
url_prefix = urllib.parse.unquote(url_prefix)
|
||||
regex_pattern = f"^{re.escape(url_prefix)}"
|
||||
match_query["url"] = {"$regex": regex_pattern, "$options": "i"}
|
||||
sort_query = {"_id": 1}
|
||||
|
||||
aggregate = [{"$match": match_query}]
|
||||
aggregate: List[Dict[str, Union[int, object]]] = [{"$match": match_query}]
|
||||
|
||||
aggregate.extend(
|
||||
[
|
||||
@ -781,7 +783,7 @@ class CollectionOps:
|
||||
"count": {"$sum": 1},
|
||||
},
|
||||
},
|
||||
{"$sort": {"count": -1}},
|
||||
{"$sort": sort_query},
|
||||
{"$set": {"url": "$_id"}},
|
||||
{
|
||||
"$facet": {
|
||||
|
@ -357,45 +357,53 @@ export class SelectCollectionPage extends BtrixElement {
|
||||
|
||||
private renderSearchResults() {
|
||||
return this.searchResults.render({
|
||||
pending: () => html`
|
||||
<sl-menu-item slot="menu-item" disabled>
|
||||
<sl-spinner></sl-spinner>
|
||||
</sl-menu-item>
|
||||
`,
|
||||
complete: ({ items }) => {
|
||||
if (!items.length) {
|
||||
return html`
|
||||
<sl-menu-item slot="menu-item" disabled>
|
||||
${msg("No matching page found.")}
|
||||
</sl-menu-item>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
${items.map((item: Page) => {
|
||||
return html`
|
||||
<sl-menu-item
|
||||
slot="menu-item"
|
||||
@click=${async () => {
|
||||
if (this.input) {
|
||||
this.input.value = item.url;
|
||||
}
|
||||
|
||||
this.selectedPage = this.formatPage(item);
|
||||
|
||||
this.combobox?.hide();
|
||||
|
||||
this.selectedSnapshot = this.selectedPage.snapshots[0];
|
||||
}}
|
||||
>${item.url}
|
||||
</sl-menu-item>
|
||||
`;
|
||||
})}
|
||||
`;
|
||||
},
|
||||
pending: () =>
|
||||
this.renderItems(
|
||||
// Render previous value so that dropdown doesn't shift while typing
|
||||
this.searchResults.value,
|
||||
),
|
||||
complete: this.renderItems,
|
||||
});
|
||||
}
|
||||
|
||||
private readonly renderItems = (
|
||||
results: SelectCollectionPage["searchResults"]["value"],
|
||||
) => {
|
||||
if (!results) return;
|
||||
|
||||
const { items } = results;
|
||||
|
||||
if (!items.length) {
|
||||
return html`
|
||||
<sl-menu-item slot="menu-item" disabled>
|
||||
${msg("No matching page found.")}
|
||||
</sl-menu-item>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
${items.map((item: Page) => {
|
||||
return html`
|
||||
<sl-menu-item
|
||||
slot="menu-item"
|
||||
@click=${async () => {
|
||||
if (this.input) {
|
||||
this.input.value = item.url;
|
||||
}
|
||||
|
||||
this.selectedPage = this.formatPage(item);
|
||||
|
||||
this.combobox?.hide();
|
||||
|
||||
this.selectedSnapshot = this.selectedPage.snapshots[0];
|
||||
}}
|
||||
>${item.url}
|
||||
</sl-menu-item>
|
||||
`;
|
||||
})}
|
||||
`;
|
||||
};
|
||||
|
||||
private readonly onSearchInput = debounce(400)(() => {
|
||||
const value = this.input?.value;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user