Skip to content

Commit f8901a9

Browse files
committed
feat: Allow users to replace profile browser (#2986)
- Updates browser profile dialogs to organize settings into separate "Crawler Settings" section - Allows users to replace saved sites with new site - Fixes browser site list loading state - Consistently displays profile URLs
1 parent 4db1e9d commit f8901a9

File tree

16 files changed

+569
-240
lines changed

16 files changed

+569
-240
lines changed
Lines changed: 7 additions & 0 deletions
Loading

frontend/src/components/ui/code/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { LanguageFn } from "highlight.js";
33
import hljs from "highlight.js/lib/core";
44
import { css, html } from "lit";
55
import { customElement, property } from "lit/decorators.js";
6+
import { ifDefined } from "lit/directives/if-defined.js";
67
import { html as staticHtml, unsafeStatic } from "lit/static-html.js";
78

89
import { TailwindElement } from "@/classes/TailwindElement";
@@ -73,6 +74,9 @@ export class Code extends TailwindElement {
7374
@property({ type: Boolean })
7475
noWrap = false;
7576

77+
@property({ type: Boolean })
78+
truncate = false;
79+
7680
async connectedCallback() {
7781
const languageFn = (await langaugeFiles[this.language]).default;
7882

@@ -95,7 +99,10 @@ export class Code extends TailwindElement {
9599
class=${clsx(
96100
tw`font-monospace m-0 text-neutral-600`,
97101
this.noWrap ? tw`whitespace-nowrap` : tw`whitespace-pre-wrap`,
102+
this.truncate && tw`truncate`,
98103
)}
99-
><code>${staticHtml`${unsafeStatic(htmlStr)}`}</code></pre>`;
104+
><code title=${ifDefined(
105+
this.truncate ? this.value : undefined,
106+
)}>${staticHtml`${unsafeStatic(htmlStr)}`}</code></pre>`;
100107
}
101108
}

frontend/src/components/ui/select-crawler-proxy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export class SelectCrawlerProxy extends BtrixElement {
102102
? html`
103103
<div slot="help-text">
104104
${msg("Description:")}
105-
<span class="font-monospace"
105+
<span class="font-monospace leading-tight"
106106
>${this.selectedProxy.description || ""}</span
107107
>
108108
</div>
@@ -112,7 +112,7 @@ export class SelectCrawlerProxy extends BtrixElement {
112112
? html`
113113
<div slot="help-text">
114114
${msg("Description:")}
115-
<span class="font-monospace"
115+
<span class="font-monospace leading-tight"
116116
>${this.defaultProxy.description || ""}</span
117117
>
118118
</div>

frontend/src/components/ui/select-crawler.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { consume } from "@lit/context";
22
import { localized, msg } from "@lit/localize";
33
import { type SlSelect } from "@shoelace-style/shoelace";
4-
import { html, nothing } from "lit";
5-
import { customElement, property } from "lit/decorators.js";
4+
import { html, nothing, type PropertyValues } from "lit";
5+
import { customElement, property, state } from "lit/decorators.js";
66
import { ifDefined } from "lit/directives/if-defined.js";
77
import capitalize from "lodash/fp/capitalize";
88

@@ -51,14 +51,23 @@ export class SelectCrawler extends LiteElement {
5151
@property({ type: String })
5252
crawlerChannel?: CrawlerChannel["id"];
5353

54+
@state()
55+
public value: CrawlerChannel["id"] = "";
56+
57+
protected willUpdate(changedProperties: PropertyValues): void {
58+
if (changedProperties.has("crawlerChannel")) {
59+
this.value = this.crawlerChannel || "";
60+
}
61+
}
62+
5463
render() {
5564
const selectedCrawler = this.getSelectedChannel();
5665

5766
return html`
5867
<sl-select
5968
name="crawlerChannel"
6069
label=${msg("Crawler Release Channel")}
61-
value=${selectedCrawler?.id || ""}
70+
value=${this.value}
6271
placeholder=${msg("Latest")}
6372
size=${ifDefined(this.size)}
6473
hoist
@@ -77,7 +86,9 @@ export class SelectCrawler extends LiteElement {
7786
${msg("Version:")}
7887
${selectedCrawler
7988
? html`
80-
<span class="font-monospace">${selectedCrawler.image}</span>
89+
<span class="font-monospace leading-tight"
90+
>${selectedCrawler.image}</span
91+
>
8192
`
8293
: nothing}
8394
</div>
@@ -86,10 +97,12 @@ export class SelectCrawler extends LiteElement {
8697
}
8798

8899
private getSelectedChannel() {
89-
if (!this.crawlerChannels || !this.crawlerChannel) return null;
100+
const channelId = this.value;
90101

91-
if (this.crawlerChannel) {
92-
return this.crawlerChannels.find(({ id }) => id === this.crawlerChannel);
102+
if (!this.crawlerChannels || !channelId) return null;
103+
104+
if (channelId) {
105+
return this.crawlerChannels.find(({ id }) => id === channelId);
93106
}
94107

95108
return (
@@ -102,9 +115,10 @@ export class SelectCrawler extends LiteElement {
102115
private onChange(e: Event) {
103116
this.stopProp(e);
104117

105-
const selectedCrawler = this.crawlerChannels?.find(
106-
({ id }) => id === (e.target as SlSelect).value,
107-
);
118+
const { value } = e.target as SlSelect;
119+
120+
this.value = value as string;
121+
const selectedCrawler = this.getSelectedChannel();
108122

109123
this.dispatchEvent(
110124
new CustomEvent<SelectCrawlerChangeDetail>("on-change", {

frontend/src/components/ui/url-input.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ export class UrlInput extends SlInput {
3333
@property({ type: Boolean })
3434
hideHelpText = false;
3535

36+
// Store initial help text for when custom validity message is reset
37+
#helpText?: string;
38+
3639
constructor() {
3740
super();
3841

@@ -42,9 +45,15 @@ export class UrlInput extends SlInput {
4245
this.addEventListener("sl-change", this.onChange);
4346
}
4447

48+
connectedCallback(): void {
49+
super.connectedCallback();
50+
51+
this.#helpText = this.helpText;
52+
}
53+
4554
setCustomValidity(message: string): void {
4655
super.setCustomValidity(message);
47-
if (!this.hideHelpText) this.helpText = message;
56+
if (!this.hideHelpText) this.helpText = message || this.#helpText || "";
4857
}
4958

5059
disconnectedCallback(): void {
@@ -57,7 +66,7 @@ export class UrlInput extends SlInput {
5766
private readonly onInput = () => {
5867
if (!this.checkValidity() && validURL(this.value)) {
5968
this.setCustomValidity("");
60-
if (!this.hideHelpText) this.helpText = "";
69+
if (!this.hideHelpText) this.helpText = this.#helpText || "";
6170
}
6271
};
6372

frontend/src/features/browser-profiles/new-browser-profile-dialog.ts

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,6 @@ export class NewBrowserProfileDialog extends BtrixElement {
6363
@queryAsync("#browserProfileForm")
6464
private readonly form!: Promise<HTMLFormElement>;
6565

66-
connectedCallback(): void {
67-
super.connectedCallback();
68-
69-
if (this.org?.crawlingDefaults) {
70-
if (!this.defaultProxyId)
71-
this.defaultProxyId = this.org.crawlingDefaults.proxyId;
72-
if (!this.defaultCrawlerChannel)
73-
this.defaultCrawlerChannel = this.org.crawlingDefaults.crawlerChannel;
74-
}
75-
}
76-
7766
protected willUpdate(changedProperties: PropertyValues): void {
7867
if (changedProperties.has("defaultProxyId") && this.defaultProxyId) {
7968
this.proxyId = this.proxyId || this.defaultProxyId;
@@ -91,9 +80,14 @@ export class NewBrowserProfileDialog extends BtrixElement {
9180
}
9281

9382
render() {
83+
const channels = this.crawlerChannels;
84+
const proxyServers = this.proxyServers;
85+
const showChannels = channels && channels.length > 1;
86+
const showProxies = proxyServers?.length;
87+
9488
return html`
9589
<btrix-dialog
96-
.label=${msg("Configure New Profile")}
90+
.label=${msg("New Browser Profile")}
9791
.open=${this.open}
9892
@sl-initial-focus=${async (e: CustomEvent) => {
9993
const nameInput = (await this.form).querySelector<SlInput>(
@@ -111,39 +105,17 @@ export class NewBrowserProfileDialog extends BtrixElement {
111105
@submit=${this.onSubmit}
112106
>
113107
<btrix-url-input
114-
label=${msg("Site URL")}
108+
label=${msg("Primary Site URL")}
115109
name="profile-url"
116110
placeholder=${msg("https://example.com")}
117111
value=${ifDefined(this.defaultUrl)}
112+
help-text=${msg(
113+
"The first page of the site to load, like a login page.",
114+
)}
118115
required
119116
>
120117
</btrix-url-input>
121118
122-
${this.crawlerChannels && this.crawlerChannels.length > 1
123-
? html`<div class="mt-4">
124-
<btrix-select-crawler
125-
.crawlerChannel=${this.crawlerChannel}
126-
@on-change=${(e: SelectCrawlerChangeEvent) =>
127-
(this.crawlerChannel = e.detail.value!)}
128-
></btrix-select-crawler>
129-
</div>`
130-
: nothing}
131-
${this.proxyServers?.length
132-
? html`
133-
<div class="mt-4">
134-
<btrix-select-crawler-proxy
135-
defaultProxyId=${ifDefined(
136-
this.defaultProxyId || undefined,
137-
)}
138-
.proxyServers=${this.proxyServers}
139-
.proxyId="${this.proxyId || ""}"
140-
@btrix-change=${(e: SelectCrawlerProxyChangeEvent) =>
141-
(this.proxyId = e.detail.value)}
142-
></btrix-select-crawler-proxy>
143-
</div>
144-
`
145-
: nothing}
146-
147119
<sl-input
148120
class="mt-4"
149121
label=${msg("Profile Name")}
@@ -155,7 +127,41 @@ export class NewBrowserProfileDialog extends BtrixElement {
155127
>
156128
</sl-input>
157129
158-
<input class="invisible size-0" type="submit" />
130+
${when(
131+
showChannels || showProxies,
132+
() => html`
133+
<btrix-details class="mt-4" open>
134+
<span slot="title">${msg("Crawler Settings")}</span>
135+
136+
${showChannels
137+
? html`<div class="mt-4">
138+
<btrix-select-crawler
139+
.crawlerChannel=${this.crawlerChannel}
140+
@on-change=${(e: SelectCrawlerChangeEvent) =>
141+
(this.crawlerChannel = e.detail.value!)}
142+
></btrix-select-crawler>
143+
</div>`
144+
: nothing}
145+
${showProxies
146+
? html`
147+
<div class="mt-4">
148+
<btrix-select-crawler-proxy
149+
defaultProxyId=${ifDefined(
150+
this.defaultProxyId || undefined,
151+
)}
152+
.proxyServers=${proxyServers}
153+
.proxyId="${this.proxyId || ""}"
154+
@btrix-change=${(e: SelectCrawlerProxyChangeEvent) =>
155+
(this.proxyId = e.detail.value)}
156+
></btrix-select-crawler-proxy>
157+
</div>
158+
`
159+
: nothing}
160+
</btrix-details>
161+
`,
162+
)}
163+
164+
<input class="invisible block size-0" type="submit" />
159165
</form>
160166
<div slot="footer" class="flex justify-between">
161167
<sl-button
@@ -183,7 +189,7 @@ export class NewBrowserProfileDialog extends BtrixElement {
183189
html` <btrix-profile-browser-dialog
184190
.config=${{
185191
url,
186-
name: this.name || new URL(url).origin.slice(0, 50),
192+
name: this.name || new URL(url).hostname.slice(0, 50),
187193
crawlerChannel: this.crawlerChannel,
188194
proxyId: this.proxyId ?? undefined,
189195
}}

0 commit comments

Comments
 (0)