Skip to content

Commit 44f76c2

Browse files
committed
wip
1 parent 65a40c4 commit 44f76c2

File tree

9 files changed

+107
-32
lines changed

9 files changed

+107
-32
lines changed

backend/btrixcloud/colls.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,11 @@ async def get_collection_out(
341341
result = await self.get_collection_raw(coll_id, public_or_unlisted_only)
342342

343343
if resources:
344-
result["resources"], crawl_ids, pages_optimized = (
345-
await self.get_collection_crawl_resources(coll_id)
346-
)
344+
(
345+
result["resources"],
346+
crawl_ids,
347+
pages_optimized,
348+
) = await self.get_collection_crawl_resources(coll_id)
347349

348350
initial_pages, _ = await self.page_ops.list_pages(
349351
crawl_ids=crawl_ids,
@@ -965,9 +967,11 @@ async def get_collection_all(org: Organization = Depends(org_viewer_dep)):
965967
try:
966968
all_collections, _ = await colls.list_collections(org, page_size=10_000)
967969
for collection in all_collections:
968-
results[collection.name], _, _ = (
969-
await colls.get_collection_crawl_resources(collection.id)
970-
)
970+
(
971+
results[collection.name],
972+
_,
973+
_,
974+
) = await colls.get_collection_crawl_resources(collection.id)
971975
except Exception as exc:
972976
# pylint: disable=raise-missing-from
973977
raise HTTPException(

backend/btrixcloud/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,7 @@ class PageUrlCount(BaseModel):
13761376
"""Model for counting pages by URL"""
13771377

13781378
url: AnyHttpUrl
1379+
title: Optional[str] = None
13791380
count: int = 0
13801381
snapshots: List[PageIdTimestamp] = []
13811382

frontend/src/components/ui/combobox.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { consume } from "@lit/context";
12
import type { SlMenu, SlMenuItem, SlPopup } from "@shoelace-style/shoelace";
2-
import { css, html, LitElement, type PropertyValues } from "lit";
3+
import { css, html, type PropertyValues } from "lit";
34
import {
45
customElement,
56
property,
@@ -8,6 +9,8 @@ import {
89
state,
910
} from "lit/decorators.js";
1011

12+
import { TailwindElement } from "@/classes/TailwindElement";
13+
import { popupBoundary } from "@/context/popup-boundary";
1114
import { dropdown } from "@/utils/css";
1215

1316
/**
@@ -20,7 +23,7 @@ import { dropdown } from "@/utils/css";
2023
* @event request-close
2124
*/
2225
@customElement("btrix-combobox")
23-
export class Combobox extends LitElement {
26+
export class Combobox extends TailwindElement {
2427
static styles = [
2528
dropdown,
2629
css`
@@ -34,6 +37,13 @@ export class Combobox extends LitElement {
3437
@property({ type: Boolean })
3538
open = false;
3639

40+
@property({ type: Boolean })
41+
loading = false;
42+
43+
@consume({ context: popupBoundary })
44+
@state()
45+
autoSizeBoundary?: Element | Element[] | undefined;
46+
3747
@state()
3848
isActive = true;
3949

@@ -69,22 +79,25 @@ export class Combobox extends LitElement {
6979
}
7080

7181
render() {
82+
console.log(this.autoSizeBoundary);
7283
return html`
7384
<sl-popup
7485
placement="bottom-start"
7586
shift
7687
strategy="fixed"
88+
autoSize="both"
89+
.autoSizeBoundary=${this.autoSizeBoundary}
7790
?active=${this.isActive}
7891
@keydown=${this.onKeydown}
7992
@keyup=${this.onKeyup}
8093
@focusout=${this.onFocusout}
8194
>
82-
<div slot="anchor">
95+
<div slot="anchor" class="relative z-20">
8396
<slot></slot>
8497
</div>
8598
<div
8699
id="dropdown"
87-
class="dropdown hidden"
100+
class="dropdown z-10 -mt-2 hidden"
88101
@animationend=${(e: AnimationEvent) => {
89102
const el = e.target as HTMLDivElement;
90103
if (e.animationName === "dropdownShow") {
@@ -97,7 +110,10 @@ export class Combobox extends LitElement {
97110
}
98111
}}
99112
>
100-
<sl-menu role="listbox">
113+
<sl-menu role="listbox" class="border-t-0 pt-4">
114+
<!-- <div class="fixed inset-0 bg-neutral-50 opacity-25">
115+
<sl-spinner></sl-spinner>
116+
</div> -->
101117
<slot name="menu-item"></slot>
102118
</sl-menu>
103119
</div>

frontend/src/components/ui/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ import("./tag-input");
3939
import("./tag");
4040
import("./time-input");
4141
import("./user-language-select");
42+
import("./menu-item-without-focus");
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/** A version of <sl-menu-item> that doesn't steal focus on mouseover */
2+
3+
import { SlMenuItem } from "@shoelace-style/shoelace";
4+
import { customElement } from "lit/decorators.js";
5+
6+
@customElement("btrix-menu-item")
7+
// @ts-expect-error this shouldn't be allowed, but idk of an easier way without
8+
// forking the whole component
9+
export class BtrixMenuItem extends SlMenuItem {
10+
private readonly handleMouseOver = (event: MouseEvent) => {
11+
// NOT doing this.focus();
12+
event.stopPropagation();
13+
};
14+
15+
connectedCallback() {
16+
super.connectedCallback();
17+
}
18+
19+
disconnectedCallback() {
20+
super.disconnectedCallback();
21+
}
22+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { createContext } from "@lit/context";
2+
3+
/**
4+
* Boundary for custom <sl-popup> instances to use, e.g. when inside a dialog
5+
*/
6+
export const popupBoundary = createContext<Element | Element[] | undefined>(
7+
"popup-boundary",
8+
);

frontend/src/features/collections/collection-edit-dialog.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { provide } from "@lit/context";
12
import { localized, msg, str } from "@lit/localize";
23
import { Task, TaskStatus } from "@lit/task";
34
import { type SlRequestCloseEvent } from "@shoelace-style/shoelace";
@@ -22,6 +23,7 @@ import { type SelectCollectionPage } from "./select-collection-page";
2223
import { BtrixElement } from "@/classes/BtrixElement";
2324
import type { Dialog } from "@/components/ui/dialog";
2425
import { type TabGroupPanel } from "@/components/ui/tab-group/tab-panel";
26+
import { popupBoundary } from "@/context/popup-boundary";
2527
import {
2628
type Collection,
2729
type CollectionThumbnailSource,
@@ -118,6 +120,9 @@ export class CollectionEdit extends BtrixElement {
118120
@query("btrix-collection-snapshot-preview")
119121
public readonly thumbnailPreview?: CollectionSnapshotPreview | null;
120122

123+
@provide({ context: popupBoundary })
124+
private popupBoundary: Element | Element[] | undefined;
125+
121126
protected willUpdate(changedProperties: PropertyValues<this>): void {
122127
if (changedProperties.has("collectionId") && this.collectionId) {
123128
void this.fetchCollection(this.collectionId);
@@ -135,6 +140,7 @@ export class CollectionEdit extends BtrixElement {
135140
null;
136141
this.selectedSnapshot = this.collection?.thumbnailSource ?? null;
137142
}
143+
this.popupBoundary = this.dialog;
138144
}
139145

140146
readonly checkChanged = checkChanged.bind(this);

frontend/src/features/collections/select-collection-page.ts

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import type { APIPaginationQuery } from "@/types/api";
2222
import type { Collection } from "@/types/collection";
2323
import type { UnderlyingFunction } from "@/types/utils";
2424
import { tw } from "@/utils/tailwind";
25+
import { timeoutCache } from "@/utils/timeoutCache";
26+
import { cached } from "@/utils/weakCache";
2527

2628
type Snapshot = {
2729
pageId: string;
@@ -31,6 +33,7 @@ type Snapshot = {
3133

3234
type Page = {
3335
url: string;
36+
title?: string;
3437
count: number;
3538
snapshots: Snapshot[];
3639
};
@@ -179,17 +182,20 @@ export class SelectCollectionPage extends BtrixElement {
179182
}
180183

181184
private readonly searchResults = new Task(this, {
182-
task: async ([searchValue], { signal }) => {
183-
const pageUrls = await this.getPageUrls(
184-
{
185-
id: this.collectionId!,
186-
urlPrefix: searchValue,
187-
},
188-
signal,
189-
);
185+
task: cached(
186+
async ([searchValue], { signal }) => {
187+
const pageUrls = await this.getPageUrls(
188+
{
189+
id: this.collectionId!,
190+
urlPrefix: searchValue,
191+
},
192+
signal,
193+
);
190194

191-
return pageUrls;
192-
},
195+
return pageUrls;
196+
},
197+
{ cacheConstructor: timeoutCache(300) },
198+
),
193199
args: () => [this.searchQuery] as const,
194200
});
195201

@@ -365,19 +371,21 @@ export class SelectCollectionPage extends BtrixElement {
365371
this.renderItems(
366372
// Render previous value so that dropdown doesn't shift while typing
367373
this.searchResults.value,
374+
true,
368375
),
369376
complete: this.renderItems,
370377
});
371378
}
372379

373380
private readonly renderItems = (
374381
results: SelectCollectionPage["searchResults"]["value"],
382+
loading = false,
375383
) => {
376384
if (!results) return;
377385

378386
const { items } = results;
379387

380-
if (!items.length) {
388+
if (!loading && !items.length) {
381389
return html`
382390
<sl-menu-item slot="menu-item" disabled>
383391
${msg("No matching page found.")}
@@ -388,7 +396,7 @@ export class SelectCollectionPage extends BtrixElement {
388396
return html`
389397
${items.map((item: Page) => {
390398
return html`
391-
<sl-menu-item
399+
<btrix-menu-item
392400
slot="menu-item"
393401
@click=${async () => {
394402
if (this.input) {
@@ -401,8 +409,18 @@ export class SelectCollectionPage extends BtrixElement {
401409
402410
this.selectedSnapshot = this.selectedPage.snapshots[0];
403411
}}
404-
>${item.url}
405-
</sl-menu-item>
412+
>${item.title
413+
? html`<div class="text-sm font-semibold">${item.title}</div>
414+
<div class="text-xs leading-4 text-blue-600">
415+
${item.url}
416+
</div>`
417+
: html`<div class="text-sm font-semibold opacity-50">
418+
${msg("No page title")}
419+
</div>
420+
<div class="text-xs leading-4 text-blue-600">
421+
${item.url}
422+
</div>`}
423+
</btrix-menu-item>
406424
`;
407425
})}
408426
`;

frontend/src/utils/css.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ export const animatePulse = css`
102102
export const dropdown = css`
103103
.dropdown {
104104
contain: content;
105-
transform-origin: top left;
106105
box-shadow: var(--sl-shadow-medium);
107106
}
108107
@@ -111,34 +110,34 @@ export const dropdown = css`
111110
}
112111
113112
.animateShow {
114-
animation: dropdownShow 100ms ease forwards;
113+
animation: dropdownShow 150ms cubic-bezier(0, 0, 0.2, 1) forwards;
115114
}
116115
117116
.animateHide {
118-
animation: dropdownHide 100ms ease forwards;
117+
animation: dropdownHide 150ms cubic-bezier(0.4, 0, 1, 1) forwards;
119118
}
120119
121120
@keyframes dropdownShow {
122121
from {
123122
opacity: 0;
124-
transform: scale(0.9);
123+
transform: translateY(-8px);
125124
}
126125
127126
to {
128127
opacity: 1;
129-
transform: scale(1);
128+
transform: translateY(0);
130129
}
131130
}
132131
133132
@keyframes dropdownHide {
134133
from {
135134
opacity: 1;
136-
transform: scale(1);
135+
transform: translateY(0);
137136
}
138137
139138
to {
140139
opacity: 0;
141-
transform: scale(0.9);
140+
transform: translateY(-8px);
142141
}
143142
}
144143
`;

0 commit comments

Comments
 (0)