From 69b5bd98ba41f3610eb67ac2d885d0b65f4cde95 Mon Sep 17 00:00:00 2001 From: sua yoo Date: Thu, 13 Nov 2025 11:48:50 -0800 Subject: [PATCH 01/15] update form --- .../new-browser-profile-dialog.ts | 11 --- .../browser-profiles/start-browser-dialog.ts | 73 +++++++++++++++++-- frontend/src/pages/org/index.ts | 9 ++- 3 files changed, 74 insertions(+), 19 deletions(-) diff --git a/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts b/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts index d6769933be..4f756521e3 100644 --- a/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts +++ b/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts @@ -63,17 +63,6 @@ export class NewBrowserProfileDialog extends BtrixElement { @queryAsync("#browserProfileForm") private readonly form!: Promise; - connectedCallback(): void { - super.connectedCallback(); - - if (this.org?.crawlingDefaults) { - if (!this.defaultProxyId) - this.defaultProxyId = this.org.crawlingDefaults.proxyId; - if (!this.defaultCrawlerChannel) - this.defaultCrawlerChannel = this.org.crawlingDefaults.crawlerChannel; - } - } - protected willUpdate(changedProperties: PropertyValues): void { if (changedProperties.has("defaultProxyId") && this.defaultProxyId) { this.proxyId = this.proxyId || this.defaultProxyId; diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 2e57714c69..46008a4542 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -1,9 +1,14 @@ import { consume } from "@lit/context"; import { localized, msg } from "@lit/localize"; -import type { SlButton } from "@shoelace-style/shoelace"; +import type { + SlButton, + SlChangeEvent, + SlCheckbox, +} from "@shoelace-style/shoelace"; import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js"; import { html } from "lit"; -import { customElement, property, query } from "lit/decorators.js"; +import { customElement, property, query, state } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; import { when } from "lit/directives/when.js"; import { BtrixElement } from "@/classes/BtrixElement"; @@ -13,6 +18,10 @@ import { orgCrawlerChannelsContext, type OrgCrawlerChannelsContext, } from "@/context/org-crawler-channels"; +import { + orgProxiesContext, + type OrgProxiesContext, +} from "@/context/org-proxies"; import type { Profile } from "@/types/crawler"; type StartBrowserEventDetail = { @@ -30,6 +39,9 @@ export type BtrixStartBrowserEvent = CustomEvent; @customElement("btrix-start-browser-dialog") @localized() export class StartBrowserDialog extends BtrixElement { + @consume({ context: orgProxiesContext, subscribe: true }) + private readonly orgProxies?: OrgProxiesContext; + @consume({ context: orgCrawlerChannelsContext, subscribe: true }) private readonly orgCrawlerChannels?: OrgCrawlerChannelsContext; @@ -42,6 +54,9 @@ export class StartBrowserDialog extends BtrixElement { @property({ type: Boolean }) open = false; + @state() + resetProfile = false; + @query("btrix-dialog") private readonly dialog?: Dialog | null; @@ -87,7 +102,7 @@ export class StartBrowserDialog extends BtrixElement { if (!form.checkValidity()) return; const values = serialize(form); - const url = values["starting-url"] as string; + const url = values["startingUrl"] as string; const crawlerChannel = values["crawlerChannel"] as string | undefined; this.dispatchEvent( @@ -98,23 +113,50 @@ export class StartBrowserDialog extends BtrixElement { }} > ${when( - this.orgCrawlerChannels && this.orgCrawlerChannels.length > 1, - () => html` + this.orgCrawlerChannels && + this.orgCrawlerChannels.length > 1 && + this.profile, + (profile) => html`
`, )} + + + (this.resetProfile = (e.target as SlCheckbox).checked)} + > + ${msg("Reset configured sites")} + ${when( + this.resetProfile, + () => html` +
+ + ${msg( + "All previously configured site data and browsing activity will be removed.", + )} +
+ `, + )} +
+ + ${when(this.resetProfile && this.profile, this.renderProxy)}
void this.dialog?.hide()} @@ -131,4 +173,21 @@ export class StartBrowserDialog extends BtrixElement {
`; } + + private readonly renderProxy = (profile: Profile) => { + if (!this.orgProxies?.servers.length) return; + + return html` + + + `; + }; } diff --git a/frontend/src/pages/org/index.ts b/frontend/src/pages/org/index.ts index 7ecb624afd..261855e125 100644 --- a/frontend/src/pages/org/index.ts +++ b/frontend/src/pages/org/index.ts @@ -492,7 +492,14 @@ export class Org extends BtrixElement { ? html` (this.openDialogName = undefined)} > From b4b8d15b9c309aa9f57358fdd38152fa701b7ec3 Mon Sep 17 00:00:00 2001 From: sua yoo Date: Thu, 13 Nov 2025 12:38:38 -0800 Subject: [PATCH 02/15] wip replace --- .../src/components/ui/select-crawler-proxy.ts | 4 +- frontend/src/components/ui/select-crawler.ts | 4 +- .../profile-browser-dialog.ts | 9 +- .../browser-profiles/start-browser-dialog.ts | 87 +++++++++++-------- .../src/pages/org/browser-profiles/profile.ts | 85 ++++++++++++------ 5 files changed, 116 insertions(+), 73 deletions(-) diff --git a/frontend/src/components/ui/select-crawler-proxy.ts b/frontend/src/components/ui/select-crawler-proxy.ts index 12362a179b..abe19b5a76 100644 --- a/frontend/src/components/ui/select-crawler-proxy.ts +++ b/frontend/src/components/ui/select-crawler-proxy.ts @@ -102,7 +102,7 @@ export class SelectCrawlerProxy extends BtrixElement { ? html`
${msg("Description:")} - ${this.selectedProxy.description || ""}
@@ -112,7 +112,7 @@ export class SelectCrawlerProxy extends BtrixElement { ? html`
${msg("Description:")} - ${this.defaultProxy.description || ""}
diff --git a/frontend/src/components/ui/select-crawler.ts b/frontend/src/components/ui/select-crawler.ts index 2328080dea..c36316a440 100644 --- a/frontend/src/components/ui/select-crawler.ts +++ b/frontend/src/components/ui/select-crawler.ts @@ -77,7 +77,9 @@ export class SelectCrawler extends LiteElement { ${msg("Version:")} ${selectedCrawler ? html` - ${selectedCrawler.image} + ${selectedCrawler.image} ` : nothing} diff --git a/frontend/src/features/browser-profiles/profile-browser-dialog.ts b/frontend/src/features/browser-profiles/profile-browser-dialog.ts index 36b94e96b9..26032a580d 100644 --- a/frontend/src/features/browser-profiles/profile-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/profile-browser-dialog.ts @@ -54,7 +54,7 @@ export class ProfileBrowserDialog extends BtrixElement { #savedBrowserId?: string; private readonly browserIdTask = new Task(this, { - task: async ([open, config, profile], { signal }) => { + task: async ([open, config], { signal }) => { if (!open || !config) return null; const browserId = this.browserIdTask.value; @@ -63,14 +63,11 @@ export class ProfileBrowserDialog extends BtrixElement { void this.deleteBrowser(browserId, signal); } - const { browserid } = await this.createBrowser( - { profileId: profile?.id, ...config }, - signal, - ); + const { browserid } = await this.createBrowser(config, signal); return browserid; }, - args: () => [this.open, this.config, this.profile] as const, + args: () => [this.open, this.config] as const, }); disconnectedCallback(): void { diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 46008a4542..16b946df1c 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -27,6 +27,8 @@ import type { Profile } from "@/types/crawler"; type StartBrowserEventDetail = { url?: string; crawlerChannel?: Profile["crawlerChannel"]; + proxyId?: Profile["proxyId"]; + replaceBrowser: boolean; }; export type BtrixStartBrowserEvent = CustomEvent; @@ -51,11 +53,14 @@ export class StartBrowserDialog extends BtrixElement { @property({ type: String }) startUrl?: string; + @property({ type: Boolean }) + replaceable = false; + @property({ type: Boolean }) open = false; @state() - resetProfile = false; + replaceBrowser = false; @query("btrix-dialog") private readonly dialog?: Dialog | null; @@ -90,7 +95,7 @@ export class StartBrowserDialog extends BtrixElement { } } - void this.dialog?.hide(); + this.replaceBrowser = false; }} >
("btrix-start-browser", { - detail: { url, crawlerChannel }, + detail: { + url, + crawlerChannel, + replaceBrowser: this.replaceBrowser, + }, }), ); }} @@ -133,30 +142,8 @@ export class StartBrowserDialog extends BtrixElement { `, )} - - - (this.resetProfile = (e.target as SlCheckbox).checked)} - > - ${msg("Reset configured sites")} - ${when( - this.resetProfile, - () => html` -
- - ${msg( - "All previously configured site data and browsing activity will be removed.", - )} -
- `, - )} -
- - ${when(this.resetProfile && this.profile, this.renderProxy)} + ${when(this.replaceable, this.renderReplaceControl)} + ${when(this.replaceBrowser && this.profile, this.renderProxy)}
void this.dialog?.hide()} @@ -174,20 +161,46 @@ export class StartBrowserDialog extends BtrixElement { `; } + private readonly renderReplaceControl = () => { + return html` + (this.replaceBrowser = (e.target as SlCheckbox).checked)} + > + ${msg("Reset configured sites")} + ${when( + this.replaceBrowser, + () => html` +
+ + ${msg( + "All previously configured site data and browsing activity will be removed.", + )} +
+ `, + )} +
`; + }; + private readonly renderProxy = (profile: Profile) => { if (!this.orgProxies?.servers.length) return; return html` - - +
+ + +
`; }; } diff --git a/frontend/src/pages/org/browser-profiles/profile.ts b/frontend/src/pages/org/browser-profiles/profile.ts index 9fb6ae2c53..de3f71b750 100644 --- a/frontend/src/pages/org/browser-profiles/profile.ts +++ b/frontend/src/pages/org/browser-profiles/profile.ts @@ -15,6 +15,7 @@ import type { import { parsePage, type PageChangeEvent } from "@/components/ui/pagination"; import { ClipboardController } from "@/controllers/clipboard"; import { CrawlStatus } from "@/features/archived-items/crawl-status"; +import type { ProfileBrowserDialog } from "@/features/browser-profiles/profile-browser-dialog"; import type { BtrixStartBrowserEvent } from "@/features/browser-profiles/start-browser-dialog"; import { badges, @@ -29,7 +30,11 @@ import { panel, panelBody } from "@/layouts/panel"; import { OrgTab, WorkflowTab } from "@/routes"; import { noData, stringFor } from "@/strings/ui"; import type { APIPaginatedList, APIPaginationQuery } from "@/types/api"; -import type { Profile, Workflow } from "@/types/crawler"; +import { + CrawlerChannelImage, + type Profile, + type Workflow, +} from "@/types/crawler"; import type { CrawlState } from "@/types/crawlState"; import { SortDirection } from "@/types/utils"; import { isApiError } from "@/utils/api"; @@ -76,10 +81,12 @@ export class BrowserProfilesProfilePage extends BtrixElement { | "duplicate"; @state() - private browserLoadUrl?: string; - - @state() - private browserLoadCrawlerChannel?: Profile["crawlerChannel"]; + private browserLoadParams: { + url?: string; + crawlerChannel?: Profile["crawlerChannel"]; + proxyId?: Profile["proxyId"]; + replaceBrowser?: boolean; + } = {}; /** * Render updated fields before refreshing data from API @@ -139,24 +146,43 @@ export class BrowserProfilesProfilePage extends BtrixElement { } satisfies Parameters[0]; const duplicating = this.openDialog === "duplicate"; + const browserLoadUrl = this.browserLoadParams.url; + const browserLoadCrawlerChannel = + this.browserLoadParams.crawlerChannel || CrawlerChannelImage.Default; + + // Custom config will take precedence over profile data + let config: ProfileBrowserDialog["config"] = undefined; + + if (browserLoadUrl) { + config = { + url: browserLoadUrl, + profileId: this.profileId, + crawlerChannel: browserLoadCrawlerChannel, + }; + + if (duplicating) { + config = { + ...config, + name: `${this.profile?.name || browserLoadUrl} ${msg("Copy")}`, + crawlerChannel: this.profile?.crawlerChannel, + proxyId: this.profile?.proxyId, + }; + } else if (this.browserLoadParams.replaceBrowser) { + config = { + ...config, + // Don't specify profile ID if replacing browser instance + profileId: undefined, + // Allow specifying new proxy + proxyId: this.browserLoadParams.proxyId, + }; + } + } return html`${page(header, this.renderPage)} { + private readonly openBrowser = async ( + opts: BrowserProfilesProfilePage["browserLoadParams"], + ) => { let { url } = opts; if (!url) { url = await this.getFirstBrowserUrl(); } - this.browserLoadUrl = url; - this.browserLoadCrawlerChannel = opts.crawlerChannel; + + this.browserLoadParams = { + ...opts, + url, + }; this.openDialog = "browser"; }; @@ -780,13 +809,15 @@ export class BrowserProfilesProfilePage extends BtrixElement { } private readonly closeBrowser = () => { - this.browserLoadUrl = undefined; - this.browserLoadCrawlerChannel = undefined; + this.browserLoadParams = {}; this.openDialog = undefined; }; private async duplicateProfile() { - this.browserLoadUrl = await this.getFirstBrowserUrl(); + this.browserLoadParams = { + ...this.browserLoadParams, + url: await this.getFirstBrowserUrl(), + }; this.openDialog = "duplicate"; } From 10d85c274abc35c5ad5c8bc44720a3a4ff8e74fa Mon Sep 17 00:00:00 2001 From: sua yoo Date: Mon, 17 Nov 2025 15:11:46 -0800 Subject: [PATCH 03/15] update dialogs --- .../new-browser-profile-dialog.ts | 68 +++++---- .../browser-profiles/start-browser-dialog.ts | 134 ++++++++++-------- frontend/src/layouts/page.ts | 2 +- .../src/pages/org/browser-profiles/profile.ts | 14 +- 4 files changed, 115 insertions(+), 103 deletions(-) diff --git a/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts b/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts index 4f756521e3..e711b95a32 100644 --- a/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts +++ b/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts @@ -80,9 +80,14 @@ export class NewBrowserProfileDialog extends BtrixElement { } render() { + const channels = this.crawlerChannels; + const proxyServers = this.proxyServers; + const showChannels = channels && channels.length > 1; + const showProxies = proxyServers?.length; + return html` { const nameInput = (await this.form).querySelector( @@ -108,31 +113,6 @@ export class NewBrowserProfileDialog extends BtrixElement { > - ${this.crawlerChannels && this.crawlerChannels.length > 1 - ? html`
- - (this.crawlerChannel = e.detail.value!)} - > -
` - : nothing} - ${this.proxyServers?.length - ? html` -
- - (this.proxyId = e.detail.value)} - > -
- ` - : nothing} - - + ${when( + showChannels || showProxies, + () => html` + + ${msg("Crawler Settings")} + + ${showChannels + ? html`
+ + (this.crawlerChannel = e.detail.value!)} + > +
` + : nothing} + ${showProxies + ? html` +
+ + (this.proxyId = e.detail.value)} + > +
+ ` + : nothing} +
+ `, + )} + +
1 && profile; + const showProxies = + this.replaceBrowser && proxies && proxyServers?.length && profile; + return html` { await this.updateComplete; @@ -123,27 +132,69 @@ export class StartBrowserDialog extends BtrixElement { > + > + + + + (this.replaceBrowser = (e.target as SlCheckbox).checked)} + > + ${msg("Replace configured sites")} + ${when( + this.replaceBrowser, + () => html` +
+ + ${msg( + "All previously configured site data and browsing activity will be removed.", + )} +
+ `, + )} +
${when( - this.orgCrawlerChannels && - this.orgCrawlerChannels.length > 1 && - this.profile, - (profile) => html` -
- - -
+ this.open && (showChannels || showProxies), + () => html` + + ${msg("Crawler Settings")} + + ${showChannels + ? html`
+ + +
` + : nothing} + ${showProxies + ? html`
+ + +
` + : nothing} +
`, )} - ${when(this.replaceable, this.renderReplaceControl)} - ${when(this.replaceBrowser && this.profile, this.renderProxy)}
void this.dialog?.hide()} @@ -160,47 +211,4 @@ export class StartBrowserDialog extends BtrixElement {
`; } - - private readonly renderReplaceControl = () => { - return html` - (this.replaceBrowser = (e.target as SlCheckbox).checked)} - > - ${msg("Reset configured sites")} - ${when( - this.replaceBrowser, - () => html` -
- - ${msg( - "All previously configured site data and browsing activity will be removed.", - )} -
- `, - )} -
`; - }; - - private readonly renderProxy = (profile: Profile) => { - if (!this.orgProxies?.servers.length) return; - - return html` -
- - -
- `; - }; } diff --git a/frontend/src/layouts/page.ts b/frontend/src/layouts/page.ts index a84710480c..b028a2c7b1 100644 --- a/frontend/src/layouts/page.ts +++ b/frontend/src/layouts/page.ts @@ -42,7 +42,7 @@ export function page( class="mx-auto box-border flex min-h-full w-full max-w-screen-desktop flex-1 flex-col gap-3 lg:px-10 lg:pb-10" > ${header.breadcrumbs ? html` ${pageNav(header.breadcrumbs)} ` : nothing} - ${header.title ? pageHeader(header) : nothing} + ${pageHeader(header)} ${header.title ? html`
${render()}
` : render()} diff --git a/frontend/src/pages/org/browser-profiles/profile.ts b/frontend/src/pages/org/browser-profiles/profile.ts index de3f71b750..7f97c287cf 100644 --- a/frontend/src/pages/org/browser-profiles/profile.ts +++ b/frontend/src/pages/org/browser-profiles/profile.ts @@ -242,7 +242,7 @@ export class BrowserProfilesProfilePage extends BtrixElement { )} > - ${msg("Configure Profile")} + ${msg("Configure Sites")} - (this.openDialog = "start-browser")} - ?disabled=${archivingDisabled} - > - ` - : undefined, body: html`${this.renderOrigins()} ${when( isCrawler, @@ -325,6 +315,7 @@ export class BrowserProfilesProfilePage extends BtrixElement { size="small" class="mt-3" @click=${() => (this.openDialog = "start-browser-add-site")} + ?disabled=${archivingDisabled} > ${msg("Add Site")}
Date: Tue, 18 Nov 2025 09:51:46 -0800 Subject: [PATCH 04/15] update labels --- frontend/src/components/ui/code/index.ts | 9 +- .../profile-browser-dialog.ts | 34 ++++++-- .../browser-profiles/profile-browser.ts | 84 ++++++++++++------- .../browser-profiles/start-browser-dialog.ts | 2 +- frontend/src/layouts/emptyMessage.ts | 9 ++ .../src/pages/org/browser-profiles/profile.ts | 2 +- frontend/src/theme.stylesheet.css | 8 +- 7 files changed, 105 insertions(+), 43 deletions(-) diff --git a/frontend/src/components/ui/code/index.ts b/frontend/src/components/ui/code/index.ts index 9af0351ac5..24f13919ea 100644 --- a/frontend/src/components/ui/code/index.ts +++ b/frontend/src/components/ui/code/index.ts @@ -3,6 +3,7 @@ import type { LanguageFn } from "highlight.js"; import hljs from "highlight.js/lib/core"; import { css, html } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; import { html as staticHtml, unsafeStatic } from "lit/static-html.js"; import { TailwindElement } from "@/classes/TailwindElement"; @@ -73,6 +74,9 @@ export class Code extends TailwindElement { @property({ type: Boolean }) noWrap = false; + @property({ type: Boolean }) + truncate = false; + async connectedCallback() { const languageFn = (await langaugeFiles[this.language]).default; @@ -95,7 +99,10 @@ export class Code extends TailwindElement { class=${clsx( tw`font-monospace m-0 text-neutral-600`, this.noWrap ? tw`whitespace-nowrap` : tw`whitespace-pre-wrap`, + this.truncate && tw`truncate`, )} - >${staticHtml`${unsafeStatic(htmlStr)}`}`; + >${staticHtml`${unsafeStatic(htmlStr)}`}`; } } diff --git a/frontend/src/features/browser-profiles/profile-browser-dialog.ts b/frontend/src/features/browser-profiles/profile-browser-dialog.ts index 26032a580d..bcf17b08d9 100644 --- a/frontend/src/features/browser-profiles/profile-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/profile-browser-dialog.ts @@ -148,7 +148,7 @@ export class ProfileBrowserDialog extends BtrixElement { @sl-after-hide=${() => this.closeBrowser()} >
-
+
-
-

- ${[this.config?.name || this.profile?.name, this.config?.url] - .filter((v) => v) - .join(" — ")} -

+
+
+

+ ${this.config?.name || this.profile?.name} +

+ ${when( + this.config?.url, + (url) => html` + + + `, + )} +
${when( (this.profile || this.config) && { ...this.profile, @@ -181,7 +197,7 @@ export class ProfileBrowserDialog extends BtrixElement { )}
-
+
void this.profileBrowser?.enterFullscreen()} > - + - this.browserTask.status === TaskStatus.PENDING - ? emptyMessage({ - message: msg( - "Sites will be shown here once the browser is done loading.", - ), - }) - : emptyMessage({ - message: msg("No sites configured yet."), - }), + html`
+ ${typeof this.browserTask.value !== "number" && + this.browserTask.value?.id + ? emptyMessage({ + icon: { name: "slash-circle", label: msg("None") }, + message: msg("No sites configured yet."), + }) + : emptyMessage({ + icon: { + name: "hourglass-split", + label: msg("Waiting"), + }, + message: msg( + "Sites will be shown here once the browser is done loading.", + ), + })} +
`, )}
@@ -469,7 +479,7 @@ export class ProfileBrowser extends BtrixElement { private renderSidebarButton() { return html` - +
-

${msg("Saved Sites")}

+

${msg("Configured Sites")}

${msg("New Sites")}

(iframeSrc ? this.navigateBrowser({ url }) : {})} - > -
${url}
- ${iframeSrc - ? html`` - : ""} + return html`
  • +
    void this.navigateBrowser({ url }) + : undefined} + > + ${iframeSrc + ? html` + + ` + : ""} + + +
  • `; } diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index f3ce32802b..8730a57819 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -143,7 +143,7 @@ export class StartBrowserDialog extends BtrixElement { @sl-change=${(e: SlChangeEvent) => (this.replaceBrowser = (e.target as SlCheckbox).checked)} > - ${msg("Replace configured sites")} + ${msg("Replace previously configured sites")} ${when( this.replaceBrowser, () => html` diff --git a/frontend/src/layouts/emptyMessage.ts b/frontend/src/layouts/emptyMessage.ts index 06f33a6756..ca3370531a 100644 --- a/frontend/src/layouts/emptyMessage.ts +++ b/frontend/src/layouts/emptyMessage.ts @@ -7,15 +7,24 @@ export function emptyMessage({ message, detail, actions, + icon, classNames, }: { message: TemplateResult | string; detail?: TemplateResult | string; actions?: TemplateResult; + icon?: { name: string; label: string }; classNames?: typeof tw | string; }) { return html`
    + ${icon + ? html`` + : nothing}

    void this.openBrowser({ url: origin })} > - + Date: Tue, 18 Nov 2025 10:37:17 -0800 Subject: [PATCH 05/15] update options --- .../browser-profiles/start-browser-dialog.ts | 75 ++++++++++++++++--- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 8730a57819..2d48b1f382 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -4,10 +4,17 @@ import type { SlButton, SlChangeEvent, SlCheckbox, + SlSelect, } from "@shoelace-style/shoelace"; import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js"; import { html, nothing } from "lit"; -import { customElement, property, query, state } from "lit/decorators.js"; +import { + customElement, + property, + query, + queryAsync, + state, +} from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; import { when } from "lit/directives/when.js"; @@ -34,6 +41,8 @@ type StartBrowserEventDetail = { export type BtrixStartBrowserEvent = CustomEvent; +const URL_FORM_FIELD_NAME = "startingUrl"; + /** * Start browser with specified profile and additional configuration. * @@ -57,6 +66,9 @@ export class StartBrowserDialog extends BtrixElement { @property({ type: Boolean }) open = false; + @state() + addSite = false; + @state() replaceBrowser = false; @@ -69,6 +81,9 @@ export class StartBrowserDialog extends BtrixElement { @query("btrix-details") private readonly details?: Details | null; + @queryAsync(`[name=${URL_FORM_FIELD_NAME}]`) + private readonly urlInput?: UrlInput | SlSelect | null; + @query("#submit-button") private readonly submitButton?: SlButton | null; @@ -82,7 +97,9 @@ export class StartBrowserDialog extends BtrixElement { this.replaceBrowser && proxies && proxyServers?.length && profile; return html` { await this.updateComplete; @@ -116,7 +133,7 @@ export class StartBrowserDialog extends BtrixElement { if (!form.checkValidity()) return; const values = serialize(form); - const url = values["startingUrl"] as string; + const url = values[URL_FORM_FIELD_NAME] as string; const crawlerChannel = values["crawlerChannel"] as string | undefined; this.dispatchEvent( @@ -130,20 +147,14 @@ export class StartBrowserDialog extends BtrixElement { ); }} > - - + ${when(this.profile, this.renderUrl)} (this.replaceBrowser = (e.target as SlCheckbox).checked)} > - ${msg("Replace previously configured sites")} + ${msg("Replace saved sites")} ${when( this.replaceBrowser, () => html` @@ -153,7 +164,7 @@ export class StartBrowserDialog extends BtrixElement { name="exclamation-triangle" > ${msg( - "All previously configured site data and browsing activity will be removed.", + "Data and browsing activity of all previously configured sites will be removed.", )}

    `, @@ -211,4 +222,44 @@ export class StartBrowserDialog extends BtrixElement {
    `; } + + private readonly renderUrl = (profile: Profile) => { + const urlInput = html` + `; + + if (this.startUrl && profile.origins.length > 1) { + return html` { + const { value } = e.target as SlSelect; + this.addSite = !value; + + await this.updateComplete; + (await this.urlInput)?.focus(); + }} + > + ${msg("Configured Sites")} + ${profile.origins.map( + (url) => html` ${url} `, + )} + + ${msg("Add New Site")} + + + ${when( + this.addSite, + () => html`
    ${urlInput}
    `, + )} `; + } + + return urlInput; + }; } From 9490a6b92810d107012e18f6cd266dbf40dd635a Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 10:40:26 -0800 Subject: [PATCH 06/15] update label --- .../src/features/browser-profiles/start-browser-dialog.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 2d48b1f382..998e1ab473 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -224,10 +224,12 @@ export class StartBrowserDialog extends BtrixElement { } private readonly renderUrl = (profile: Profile) => { + const startUrl = this.startUrl; + const showNew = this.addSite || !startUrl; const urlInput = html` `; From 4d8f43e128551dc3daf0fb607a0977e9e8928146 Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 10:49:32 -0800 Subject: [PATCH 07/15] update menu label --- frontend/src/features/browser-profiles/profile-browser.ts | 2 +- frontend/src/features/browser-profiles/start-browser-dialog.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/features/browser-profiles/profile-browser.ts b/frontend/src/features/browser-profiles/profile-browser.ts index 0a32c1aae6..0d40ec5ef7 100644 --- a/frontend/src/features/browser-profiles/profile-browser.ts +++ b/frontend/src/features/browser-profiles/profile-browser.ts @@ -496,7 +496,7 @@ export class ProfileBrowser extends BtrixElement { class="flex min-h-10 justify-between border-b p-1 leading-tight text-neutral-700" >
    -

    ${msg("Configured Sites")}

    +

    ${msg("Saved Sites")}

    - ${msg("Configured Sites")} + ${msg("Saved Sites")} ${profile.origins.map( (url) => html` ${url} `, )} From 0a3fe206d54763ba075879f184a7022c377c0a72 Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 13:30:09 -0800 Subject: [PATCH 08/15] fix crawler --- frontend/src/components/ui/select-crawler.ts | 30 ++++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/ui/select-crawler.ts b/frontend/src/components/ui/select-crawler.ts index c36316a440..b30d3de05b 100644 --- a/frontend/src/components/ui/select-crawler.ts +++ b/frontend/src/components/ui/select-crawler.ts @@ -1,8 +1,8 @@ import { consume } from "@lit/context"; import { localized, msg } from "@lit/localize"; import { type SlSelect } from "@shoelace-style/shoelace"; -import { html, nothing } from "lit"; -import { customElement, property } from "lit/decorators.js"; +import { html, nothing, type PropertyValues } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; import capitalize from "lodash/fp/capitalize"; @@ -51,6 +51,15 @@ export class SelectCrawler extends LiteElement { @property({ type: String }) crawlerChannel?: CrawlerChannel["id"]; + @state() + public value: CrawlerChannel["id"] = ""; + + protected willUpdate(changedProperties: PropertyValues): void { + if (changedProperties.has("crawlerChannel")) { + this.value = this.crawlerChannel || ""; + } + } + render() { const selectedCrawler = this.getSelectedChannel(); @@ -58,7 +67,7 @@ export class SelectCrawler extends LiteElement { id === this.crawlerChannel); + if (!this.crawlerChannels || !channelId) return null; + + if (channelId) { + return this.crawlerChannels.find(({ id }) => id === channelId); } return ( @@ -104,9 +115,10 @@ export class SelectCrawler extends LiteElement { private onChange(e: Event) { this.stopProp(e); - const selectedCrawler = this.crawlerChannels?.find( - ({ id }) => id === (e.target as SlSelect).value, - ); + const { value } = e.target as SlSelect; + + this.value = value as string; + const selectedCrawler = this.getSelectedChannel(); this.dispatchEvent( new CustomEvent("on-change", { From 63b0c921205ff99e5ab8bd47a8d461de44f631fe Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 15:11:50 -0800 Subject: [PATCH 09/15] update actions --- frontend/src/assets/icons/window-gear.svg | 7 + .../new-browser-profile-dialog.ts | 7 +- .../profile-browser-dialog.ts | 10 +- .../browser-profiles/profile-browser.ts | 126 +++++++++--------- .../browser-profiles/start-browser-dialog.ts | 114 +++++++++------- frontend/src/layouts/panel.ts | 2 +- .../src/pages/org/browser-profiles-list.ts | 2 +- .../src/pages/org/browser-profiles/profile.ts | 45 ++++--- 8 files changed, 177 insertions(+), 136 deletions(-) create mode 100644 frontend/src/assets/icons/window-gear.svg diff --git a/frontend/src/assets/icons/window-gear.svg b/frontend/src/assets/icons/window-gear.svg new file mode 100644 index 0000000000..edd6e8093b --- /dev/null +++ b/frontend/src/assets/icons/window-gear.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts b/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts index e711b95a32..d5c1e1f86a 100644 --- a/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts +++ b/frontend/src/features/browser-profiles/new-browser-profile-dialog.ts @@ -105,10 +105,13 @@ export class NewBrowserProfileDialog extends BtrixElement { @submit=${this.onSubmit} > @@ -186,7 +189,7 @@ export class NewBrowserProfileDialog extends BtrixElement { html`
    -
    +

    html` - +

    @@ -490,17 +518,19 @@ export class ProfileBrowser extends BtrixElement { `; } - private renderOrigins(origins: string[]) { + private renderOriginsList( + { heading, popoverContent }: { heading: string; popoverContent: string }, + origins?: string[], + ) { + if (!origins?.length) return; + return html`
    -

    ${msg("Saved Sites")}

    - ${heading} + -
    -

    ${msg("New Sites")}

    - -
    -
    -
      - ${origins.map((url) => this.renderOriginItem(url))} -
    - `; - } - private renderOriginItem(url: string) { const iframeSrc = !isPolling(this.browserTask.value) && this.browserTask.value?.url; diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 3ff723eead..9dd399a05d 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -7,7 +7,7 @@ import type { SlSelect, } from "@shoelace-style/shoelace"; import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js"; -import { html, nothing } from "lit"; +import { html, nothing, type PropertyValues } from "lit"; import { customElement, property, @@ -41,6 +41,7 @@ type StartBrowserEventDetail = { export type BtrixStartBrowserEvent = CustomEvent; +const PRIMARY_SITE_FIELD_NAME = "primarySite"; const URL_FORM_FIELD_NAME = "startingUrl"; /** @@ -61,13 +62,13 @@ export class StartBrowserDialog extends BtrixElement { profile?: Profile; @property({ type: String }) - startUrl?: string; + initialUrl?: string; @property({ type: Boolean }) open = false; @state() - addSite = false; + loadUrl?: string; @state() replaceBrowser = false; @@ -81,12 +82,27 @@ export class StartBrowserDialog extends BtrixElement { @query("btrix-details") private readonly details?: Details | null; + @queryAsync(`[name=${PRIMARY_SITE_FIELD_NAME}]`) + private readonly primarySiteInput?: SlSelect | null; + @queryAsync(`[name=${URL_FORM_FIELD_NAME}]`) - private readonly urlInput?: UrlInput | SlSelect | null; + private readonly urlInput?: UrlInput | null; @query("#submit-button") private readonly submitButton?: SlButton | null; + protected willUpdate(changedProperties: PropertyValues): void { + if (changedProperties.has("initialUrl")) { + this.loadUrl = this.initialUrl; + } + } + + protected firstUpdated(): void { + if (this.loadUrl === undefined) { + this.loadUrl = this.initialUrl; + } + } + render() { const profile = this.profile; const channels = this.orgCrawlerChannels; @@ -97,14 +113,12 @@ export class StartBrowserDialog extends BtrixElement { this.replaceBrowser && proxies && proxyServers?.length && profile; return html` { await this.updateComplete; - if (this.startUrl) { + if (this.initialUrl) { this.submitButton?.focus(); } else { this.dialog?.querySelector("btrix-url-input")?.focus(); @@ -154,7 +168,7 @@ export class StartBrowserDialog extends BtrixElement { @sl-change=${(e: SlChangeEvent) => (this.replaceBrowser = (e.target as SlCheckbox).checked)} > - ${msg("Replace saved sites")} + ${msg("Reset previous configuration on save")} ${when( this.replaceBrowser, () => html` @@ -164,7 +178,7 @@ export class StartBrowserDialog extends BtrixElement { name="exclamation-triangle" > ${msg( - "Data and browsing activity of all previously configured sites will be removed.", + "Data and browsing activity of all previously saved sites will be removed upon saving this browser profile session.", )}
    `, @@ -224,44 +238,52 @@ export class StartBrowserDialog extends BtrixElement { } private readonly renderUrl = (profile: Profile) => { - const startUrl = this.startUrl; - const showNew = this.addSite || !startUrl; - const urlInput = html` - `; - - if (this.startUrl && profile.origins.length > 1) { - return html` { + this.loadUrl = (e.target as SlSelect).value as string; + + await this.updateComplete; + (await this.urlInput)?.focus(); + }} + > + ${msg("Saved Sites")} + ${profile.origins.map( + (url) => html` ${url} `, + )} + + ${msg("New Site")} + + +
    + { - const { value } = e.target as SlSelect; - this.addSite = !value; - - await this.updateComplete; - (await this.urlInput)?.focus(); + const value = (e.target as UrlInput).value; + const origin = new URL(value).origin; + + const savedSite = profile.origins.find( + (url) => new URL(url).origin === origin, + ); + + if (savedSite) { + const primarySiteInput = await this.primarySiteInput; + if (primarySiteInput) { + primarySiteInput.value = savedSite; + } + } }} - > - ${msg("Saved Sites")} - ${profile.origins.map( - (url) => html` ${url} `, + help-text=${msg( + "The first page of the site to load, like a login page.", )} - - ${msg("Add New Site")} - - - ${when( - this.addSite, - () => html`
    ${urlInput}
    `, - )} `; - } - - return urlInput; + > +
    +
    `; }; } diff --git a/frontend/src/layouts/panel.ts b/frontend/src/layouts/panel.ts index e295647d1f..1622d24a18 100644 --- a/frontend/src/layouts/panel.ts +++ b/frontend/src/layouts/panel.ts @@ -14,7 +14,7 @@ export function panelHeader({ actions?: TemplateResult; }) { return html` -
    +
    ${typeof heading === "string" ? pageHeading({ content: heading }) : pageHeading(heading)} diff --git a/frontend/src/pages/org/browser-profiles-list.ts b/frontend/src/pages/org/browser-profiles-list.ts index 856ef74dc7..f5da641665 100644 --- a/frontend/src/pages/org/browser-profiles-list.ts +++ b/frontend/src/pages/org/browser-profiles-list.ts @@ -47,7 +47,7 @@ const sortableFields: Record< defaultDirection: "desc", }, url: { - label: msg("Starting URL"), + label: msg("Primary Site"), defaultDirection: "asc", }, modified: { diff --git a/frontend/src/pages/org/browser-profiles/profile.ts b/frontend/src/pages/org/browser-profiles/profile.ts index fe310d01a1..ad18b4fc56 100644 --- a/frontend/src/pages/org/browser-profiles/profile.ts +++ b/frontend/src/pages/org/browser-profiles/profile.ts @@ -241,8 +241,12 @@ export class BrowserProfilesProfilePage extends BtrixElement { () => (this.openDialog = "start-browser"), )} > - - ${msg("Configure Sites")} + + ${msg("Load Profile")} (this.openDialog = "start-browser-add-site")} + ?disabled=${archivingDisabled} + > + + ${msg("Load New URL")} + ` + : undefined, body: html`${this.renderOrigins()} - ${when( - isCrawler, - () => html` - (this.openDialog = "start-browser-add-site")} - ?disabled=${archivingDisabled} - > - - ${msg("Add Site")} - `, - )} ${when( this.profileTask.value, (profile) => html` void this.openBrowser({ url: origin })} > - - + + Date: Tue, 18 Nov 2025 15:14:39 -0800 Subject: [PATCH 10/15] update label --- frontend/src/features/browser-profiles/start-browser-dialog.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 9dd399a05d..654a5e2166 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -261,7 +261,7 @@ export class StartBrowserDialog extends BtrixElement {
    { From 3d5c524432a9914954af41278eb367c6fca02c29 Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 15:19:44 -0800 Subject: [PATCH 11/15] reset input if site is not in list --- .../browser-profiles/start-browser-dialog.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 654a5e2166..6b490882b5 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -268,15 +268,14 @@ export class StartBrowserDialog extends BtrixElement { const value = (e.target as UrlInput).value; const origin = new URL(value).origin; - const savedSite = profile.origins.find( - (url) => new URL(url).origin === origin, - ); - - if (savedSite) { - const primarySiteInput = await this.primarySiteInput; - if (primarySiteInput) { - primarySiteInput.value = savedSite; - } + const primarySiteInput = await this.primarySiteInput; + + if (primarySiteInput) { + const savedSite = profile.origins.find( + (url) => new URL(url).origin === origin, + ); + + primarySiteInput.value = savedSite || ""; } }} help-text=${msg( From 15b664ad06d175a9d80966ba80d14275d2fbff2c Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 15:35:05 -0800 Subject: [PATCH 12/15] fix reset --- frontend/src/components/ui/url-input.ts | 13 +++++- .../browser-profiles/start-browser-dialog.ts | 43 ++++++++++--------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/ui/url-input.ts b/frontend/src/components/ui/url-input.ts index 3a1dd916ac..62ddf1c01e 100644 --- a/frontend/src/components/ui/url-input.ts +++ b/frontend/src/components/ui/url-input.ts @@ -33,6 +33,9 @@ export class UrlInput extends SlInput { @property({ type: Boolean }) hideHelpText = false; + // Store initial help text for when custom validity message is reset + #helpText?: string; + constructor() { super(); @@ -42,9 +45,15 @@ export class UrlInput extends SlInput { this.addEventListener("sl-change", this.onChange); } + connectedCallback(): void { + super.connectedCallback(); + + this.#helpText = this.helpText; + } + setCustomValidity(message: string): void { super.setCustomValidity(message); - if (!this.hideHelpText) this.helpText = message; + if (!this.hideHelpText) this.helpText = message || this.#helpText || ""; } disconnectedCallback(): void { @@ -57,7 +66,7 @@ export class UrlInput extends SlInput { private readonly onInput = () => { if (!this.checkValidity() && validURL(this.value)) { this.setCustomValidity(""); - if (!this.hideHelpText) this.helpText = ""; + if (!this.hideHelpText) this.helpText = this.#helpText || ""; } }; diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 6b490882b5..66b6abced3 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -8,13 +8,7 @@ import type { } from "@shoelace-style/shoelace"; import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js"; import { html, nothing, type PropertyValues } from "lit"; -import { - customElement, - property, - query, - queryAsync, - state, -} from "lit/decorators.js"; +import { customElement, property, query, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; import { when } from "lit/directives/when.js"; @@ -82,10 +76,10 @@ export class StartBrowserDialog extends BtrixElement { @query("btrix-details") private readonly details?: Details | null; - @queryAsync(`[name=${PRIMARY_SITE_FIELD_NAME}]`) + @query(`[name=${PRIMARY_SITE_FIELD_NAME}]`) private readonly primarySiteInput?: SlSelect | null; - @queryAsync(`[name=${URL_FORM_FIELD_NAME}]`) + @query(`[name=${URL_FORM_FIELD_NAME}]`) private readonly urlInput?: UrlInput | null; @query("#submit-button") @@ -127,18 +121,18 @@ export class StartBrowserDialog extends BtrixElement { @sl-after-hide=${async () => { if (this.form) { this.form.reset(); - - const input = this.form.querySelector("btrix-url-input"); - if (input) { - input.value = ""; - input.setCustomValidity(""); - } } this.replaceBrowser = false; }} >
    { + if (this.urlInput) { + this.urlInput.value = ""; + this.urlInput.setCustomValidity(""); + } + }} @submit=${async (e: SubmitEvent) => { e.preventDefault(); @@ -247,7 +241,10 @@ export class StartBrowserDialog extends BtrixElement { this.loadUrl = (e.target as SlSelect).value as string; await this.updateComplete; - (await this.urlInput)?.focus(); + + if (this.open) { + this.urlInput?.focus(); + } }} > ${msg("Saved Sites")} @@ -264,18 +261,22 @@ export class StartBrowserDialog extends BtrixElement { label=${msg("URL to Load")} .value=${this.loadUrl || ""} required - @sl-change=${async (e: SlChangeEvent) => { + @sl-change=${(e: SlChangeEvent) => { const value = (e.target as UrlInput).value; - const origin = new URL(value).origin; + let origin = ""; - const primarySiteInput = await this.primarySiteInput; + try { + origin = new URL(value).origin; + } catch { + // Not a valid URL + } - if (primarySiteInput) { + if (origin && this.primarySiteInput) { const savedSite = profile.origins.find( (url) => new URL(url).origin === origin, ); - primarySiteInput.value = savedSite || ""; + this.primarySiteInput.value = savedSite || ""; } }} help-text=${msg( From ddb3c59b47faa31516d476ff388a0cd4157f739e Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 16:27:19 -0800 Subject: [PATCH 13/15] revert unused icon --- frontend/src/pages/org/browser-profiles/profile.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/src/pages/org/browser-profiles/profile.ts b/frontend/src/pages/org/browser-profiles/profile.ts index ad18b4fc56..098900c5a9 100644 --- a/frontend/src/pages/org/browser-profiles/profile.ts +++ b/frontend/src/pages/org/browser-profiles/profile.ts @@ -602,10 +602,6 @@ export class BrowserProfilesProfilePage extends BtrixElement { ` : panelBody({ content: emptyMessage({ - icon: { - name: "file-code-fill", - label: "Workflow", - }, message: msg( "This profile is not in use by any crawl workflows.", ), From cc6c4df06f317874001a614b9ad7419e76334f3c Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 17:44:01 -0800 Subject: [PATCH 14/15] fix proxy selection --- .../src/features/browser-profiles/start-browser-dialog.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index 66b6abced3..8000adc9af 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -15,6 +15,7 @@ import { when } from "lit/directives/when.js"; import { BtrixElement } from "@/classes/BtrixElement"; import type { Details } from "@/components/ui/details"; import type { Dialog } from "@/components/ui/dialog"; +import type { SelectCrawlerProxy } from "@/components/ui/select-crawler-proxy"; import type { UrlInput } from "@/components/ui/url-input"; import { orgCrawlerChannelsContext, @@ -82,6 +83,9 @@ export class StartBrowserDialog extends BtrixElement { @query(`[name=${URL_FORM_FIELD_NAME}]`) private readonly urlInput?: UrlInput | null; + @query("btrix-select-crawler-proxy") + private readonly selectCrawlerProxy?: SelectCrawlerProxy | null; + @query("#submit-button") private readonly submitButton?: SlButton | null; @@ -143,12 +147,14 @@ export class StartBrowserDialog extends BtrixElement { const values = serialize(form); const url = values[URL_FORM_FIELD_NAME] as string; const crawlerChannel = values["crawlerChannel"] as string | undefined; + const proxyId = this.selectCrawlerProxy?.value; this.dispatchEvent( new CustomEvent("btrix-start-browser", { detail: { url, crawlerChannel, + proxyId: this.replaceBrowser ? proxyId : undefined, replaceBrowser: this.replaceBrowser, }, }), From 5ea39b24b657a37e5616bfdcc5e580fd9bd81d76 Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 18 Nov 2025 17:59:19 -0800 Subject: [PATCH 15/15] confirm before exiting --- .../profile-browser-dialog.ts | 66 +++++++++++++++---- .../browser-profiles/profile-browser.ts | 2 +- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/frontend/src/features/browser-profiles/profile-browser-dialog.ts b/frontend/src/features/browser-profiles/profile-browser-dialog.ts index b73d7b11a4..036c2343f8 100644 --- a/frontend/src/features/browser-profiles/profile-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/profile-browser-dialog.ts @@ -1,7 +1,7 @@ import { localized, msg } from "@lit/localize"; import { Task, TaskStatus } from "@lit/task"; import clsx from "clsx"; -import { html, nothing } from "lit"; +import { html, nothing, type PropertyValues } from "lit"; import { customElement, property, query, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; import { when } from "lit/directives/when.js"; @@ -45,6 +45,9 @@ export class ProfileBrowserDialog extends BtrixElement { @state() private isBrowserLoaded = false; + @state() + private showConfirmation = false; + @query("btrix-dialog") private readonly dialog?: Dialog | null; @@ -70,6 +73,17 @@ export class ProfileBrowserDialog extends BtrixElement { args: () => [this.open, this.config] as const, }); + protected willUpdate(changedProperties: PropertyValues): void { + if (changedProperties.has("open")) { + if (!this.open) { + this.showConfirmation = false; + this.isBrowserLoaded = false; + this.#savedBrowserId = undefined; + this.browserIdTask.abort(); + } + } + } + disconnectedCallback(): void { const browserId = this.browserIdTask.value; @@ -218,14 +232,31 @@ export class ProfileBrowserDialog extends BtrixElement {
    - ${when( - isCrawler, - () => html` - -
    +
    + ${when( + isCrawler, + () => html` + + void this.dialog?.hide() + : () => (this.showConfirmation = true)} + > + ${this.showConfirmation ? msg("Yes, Exit") : msg("Exit")} + + + + ${creatingNew ? msg("Create Profile") : msg("Save Profile")} -
    - - `, - )} + + `, + () => html` + void this.dialog?.hide()} + > + ${msg("Exit")} + + `, + )} +
    diff --git a/frontend/src/features/browser-profiles/profile-browser.ts b/frontend/src/features/browser-profiles/profile-browser.ts index 38de3ab7fc..61023782e8 100644 --- a/frontend/src/features/browser-profiles/profile-browser.ts +++ b/frontend/src/features/browser-profiles/profile-browser.ts @@ -331,7 +331,7 @@ export class ProfileBrowser extends BtrixElement { initial: browserLoading, pending: browserLoading, error: () => html` -
    +

    ${msg(