Skip to content

Commit

Permalink
fix: Crawler proxy selection fixes (#2280)
Browse files Browse the repository at this point in the history
- Hides proxy form control if there are no proxy servers available
- Fixes org default proxy value not being saved
  • Loading branch information
SuaYoo authored Jan 9, 2025
1 parent d6189ee commit 1260aec
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 107 deletions.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"@formatjs/intl-durationformat": "^0.6.4",
"@formatjs/intl-localematcher": "^0.5.9",
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
"@lit/context": "^1.1.3",
"@lit/localize": "^0.12.1",
"@lit/task": "^1.0.0",
"@novnc/novnc": "^1.4.0-beta",
Expand Down
115 changes: 40 additions & 75 deletions frontend/src/components/ui/select-crawler-proxy.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { localized, msg } from "@lit/localize";
import { type SlSelect } from "@shoelace-style/shoelace";
import type { SlSelect } from "@shoelace-style/shoelace";
import { html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";

import type { ProxiesAPIResponse, Proxy } from "@/pages/org/types";
import LiteElement from "@/utils/LiteElement";
import { BtrixElement } from "@/classes/BtrixElement";
import type { Proxy } from "@/pages/org/types";

type SelectCrawlerProxyChangeDetail = {
value: string | null;
Expand All @@ -26,30 +27,40 @@ export type SelectCrawlerProxyUpdateEvent =
* Usage example:
* ```ts
* <btrix-select-crawler-proxy
* orgId=${orgId}
* on-change=${({value}) => selectedcrawlerProxy = value}
* .proxyServers=${proxyServers}
* btrix-change=${({value}) => selectedcrawlerProxy = value}
* ></btrix-select-crawler-proxy>
* ```
*
* @event on-change
* @fires btrix-change
*/
@customElement("btrix-select-crawler-proxy")
@localized()
export class SelectCrawlerProxy extends LiteElement {
export class SelectCrawlerProxy extends BtrixElement {
@property({ type: String })
defaultProxyId: string | null = null;

@property({ type: Array })
proxyServers: Proxy[] = [];

@property({ type: String })
proxyId: string | null = null;

@property({ type: String })
size?: SlSelect["size"];

@state()
private selectedProxy?: Proxy;

@state()
private defaultProxy?: Proxy;

@state()
private allProxies?: Proxy[];
public get value() {
return this.selectedProxy?.id || "";
}

protected firstUpdated() {
void this.fetchOrgProxies();
void this.initProxies();
}
// credit: https://dev.to/jorik/country-code-to-flag-emoji-a21
private countryCodeToFlagEmoji(countryCode: String): String {
Expand All @@ -61,10 +72,6 @@ export class SelectCrawlerProxy extends LiteElement {
}

render() {
/*if (this.crawlerProxys && this.crawlerProxys.length < 2) {
return html``;
}*/

return html`
<sl-select
name="proxyId"
Expand All @@ -75,15 +82,12 @@ export class SelectCrawlerProxy extends LiteElement {
: msg("No Proxy")}
hoist
clearable
size=${ifDefined(this.size)}
@sl-change=${this.onChange}
@sl-focus=${() => {
// Refetch to keep list up to date
void this.fetchOrgProxies();
}}
@sl-hide=${this.stopProp}
@sl-after-hide=${this.stopProp}
>
${this.allProxies?.map(
${this.proxyServers.map(
(server) =>
html` <sl-option value=${server.id}>
${server.country_code
Expand Down Expand Up @@ -121,7 +125,7 @@ export class SelectCrawlerProxy extends LiteElement {
private onChange(e: Event) {
this.stopProp(e);

this.selectedProxy = this.allProxies?.find(
this.selectedProxy = this.proxyServers.find(
({ id }) => id === (e.target as SlSelect).value,
);

Expand All @@ -130,71 +134,32 @@ export class SelectCrawlerProxy extends LiteElement {
}

this.dispatchEvent(
new CustomEvent<SelectCrawlerProxyChangeDetail>("on-change", {
new CustomEvent<SelectCrawlerProxyChangeDetail>("btrix-change", {
detail: {
value: this.selectedProxy ? this.selectedProxy.id : null,
},
}),
);
}

/**
* Fetch crawler proxies and update internal state
*/
private async fetchOrgProxies(): Promise<void> {
try {
const data = await this.getOrgProxies();
const defaultProxyId = data.default_proxy_id;

this.allProxies = data.servers;

if (!this.defaultProxy) {
this.defaultProxy = this.allProxies.find(
({ id }) => id === defaultProxyId,
);
}

if (this.proxyId && !this.selectedProxy?.id) {
this.selectedProxy = this.allProxies.find(
({ id }) => id === this.proxyId,
);
}

if (!this.selectedProxy) {
this.proxyId = null;
this.dispatchEvent(
new CustomEvent("on-change", {
detail: {
value: null,
},
}),
);
this.selectedProxy = this.allProxies.find(
({ id }) => id === this.proxyId,
);
}

this.dispatchEvent(
new CustomEvent<SelectCrawlerProxyUpdateDetail>("on-update", {
detail: {
show: this.allProxies.length > 1,
},
}),
private async initProxies(): Promise<void> {
const defaultProxyId = this.defaultProxyId;

if (!this.defaultProxy) {
this.defaultProxy = this.proxyServers.find(
({ id }) => id === defaultProxyId,
);
} catch (e) {
this.notify({
message: msg("Sorry, couldn't retrieve proxies at this time."),
variant: "danger",
icon: "exclamation-octagon",
id: "proxy-retrieve-status",
});
}
}

private async getOrgProxies(): Promise<ProxiesAPIResponse> {
return this.apiFetch<ProxiesAPIResponse>(
`/orgs/${this.orgId}/crawlconfigs/crawler-proxies`,
);
if (this.proxyId && !this.selectedProxy) {
this.selectedProxy = this.proxyServers.find(
({ id }) => id === this.proxyId,
);
}

if (!this.selectedProxy) {
this.proxyId = null;
}
}

/**
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/context/org.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createContext } from "@lit/context";

import type { ProxiesAPIResponse } from "@/types/crawler";

export type ProxiesContext = ProxiesAPIResponse | null;

export const proxiesContext = createContext<ProxiesContext>("proxies");
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { consume } from "@lit/context";
import { localized, msg, str } from "@lit/localize";
import { type SlInput } from "@shoelace-style/shoelace";
import { nothing } from "lit";
import {
customElement,
property,
query,
queryAsync,
state,
} from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import queryString from "query-string";

import type { Dialog } from "@/components/ui/dialog";
import { type SelectCrawlerChangeEvent } from "@/components/ui/select-crawler";
import { type SelectCrawlerProxyChangeEvent } from "@/components/ui/select-crawler-proxy";
import { proxiesContext, type ProxiesContext } from "@/context/org";
import LiteElement, { html } from "@/utils/LiteElement";

@localized()
@customElement("btrix-new-browser-profile-dialog")
export class NewBrowserProfileDialog extends LiteElement {
@consume({ context: proxiesContext, subscribe: true })
private readonly proxies?: ProxiesContext;

@property({ type: Boolean })
open = false;

Expand Down Expand Up @@ -83,14 +90,22 @@ export class NewBrowserProfileDialog extends LiteElement {
(this.crawlerChannel = e.detail.value!)}
></btrix-select-crawler>
</div>
<div class="mt-4">
<btrix-select-crawler-proxy
orgId=${this.orgId}
.proxyId="${this.proxyId || ""}"
@on-change=${(e: SelectCrawlerProxyChangeEvent) =>
(this.proxyId = e.detail.value!)}
></btrix-select-crawler-proxy>
</div>
${this.proxies?.servers.length
? html`
<div class="mt-4">
<btrix-select-crawler-proxy
defaultProxyId=${ifDefined(
this.proxies.default_proxy_id ?? undefined,
)}
.proxyServers=${this.proxies.servers}
.proxyId="${this.proxyId || ""}"
@btrix-change=${(e: SelectCrawlerProxyChangeEvent) =>
(this.proxyId = e.detail.value)}
></btrix-select-crawler-proxy>
</div>
`
: nothing}
<input class="invisible size-0" type="submit" />
</form>
<div slot="footer" class="flex justify-between">
Expand Down
34 changes: 23 additions & 11 deletions frontend/src/features/crawl-workflows/workflow-editor.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { consume } from "@lit/context";
import { localized, msg, str } from "@lit/localize";
import type {
SlChangeEvent,
Expand Down Expand Up @@ -43,6 +44,7 @@ import type { SelectCrawlerProxyChangeEvent } from "@/components/ui/select-crawl
import type { Tab } from "@/components/ui/tab-list";
import type { TagInputEvent, TagsChangeEvent } from "@/components/ui/tag-input";
import type { TimeInputChangeEvent } from "@/components/ui/time-input";
import { proxiesContext, type ProxiesContext } from "@/context/org";
import { type SelectBrowserProfileChangeEvent } from "@/features/browser-profiles/select-browser-profile";
import type { CollectionsChangeEvent } from "@/features/collections/collections-add";
import type { QueueExclusionTable } from "@/features/crawl-workflows/queue-exclusion-table";
Expand Down Expand Up @@ -188,6 +190,9 @@ type CrawlConfigResponse = {
@localized()
@customElement("btrix-workflow-editor")
export class WorkflowEditor extends BtrixElement {
@consume({ context: proxiesContext, subscribe: true })
private readonly proxies?: ProxiesContext;

@property({ type: String })
configId?: string;

Expand Down Expand Up @@ -1329,17 +1334,24 @@ https://archiveweb.page/images/${"logo.svg"}`}
></btrix-select-browser-profile>
`)}
${this.renderHelpTextCol(infoTextStrings["browserProfile"])}
${inputCol(html`
<btrix-select-crawler-proxy
orgId=${this.orgId}
.proxyId="${this.formState.proxyId || ""}"
@on-change=${(e: SelectCrawlerProxyChangeEvent) =>
this.updateFormState({
proxyId: e.detail.value,
})}
></btrix-select-crawler-proxy>
`)}
${this.renderHelpTextCol(infoTextStrings["proxyId"])}
${this.proxies?.servers.length
? [
inputCol(html`
<btrix-select-crawler-proxy
defaultProxyId=${ifDefined(
this.proxies.default_proxy_id ?? undefined,
)}
.proxyServers=${this.proxies.servers}
.proxyId="${this.formState.proxyId || ""}"
@btrix-change=${(e: SelectCrawlerProxyChangeEvent) =>
this.updateFormState({
proxyId: e.detail.value,
})}
></btrix-select-crawler-proxy>
`),
this.renderHelpTextCol(infoTextStrings["proxyId"]),
]
: nothing}
${inputCol(html`
<sl-radio-group
name="scale"
Expand Down
Loading

0 comments on commit 1260aec

Please sign in to comment.