Configurable Max Scale for frontend (#1557)
Allow maximum scale option to be fully configurable via `max_crawl_scale`. Already configurable on the backend, and now exposed to the frontend via API `/api/settings` `maxCrawlScale` value. The workflow editor and workflow details are updated to allow selecting the scale up to the maxCrawlScale setting (which defaults to 3 if not set).
This commit is contained in:
parent
8462c08206
commit
08f6847194
@ -67,6 +67,7 @@ def main():
|
|||||||
os.environ.get("DEFAULT_PAGE_LOAD_TIME_SECONDS", 120)
|
os.environ.get("DEFAULT_PAGE_LOAD_TIME_SECONDS", 120)
|
||||||
),
|
),
|
||||||
"maxPagesPerCrawl": int(os.environ.get("MAX_PAGES_PER_CRAWL", 0)),
|
"maxPagesPerCrawl": int(os.environ.get("MAX_PAGES_PER_CRAWL", 0)),
|
||||||
|
"maxScale": int(os.environ.get("MAX_CRAWL_SCALE", 3)),
|
||||||
}
|
}
|
||||||
|
|
||||||
invites = init_invites(mdb, email)
|
invites = init_invites(mdb, email)
|
||||||
|
@ -14,5 +14,6 @@ def test_settings():
|
|||||||
"jwtTokenLifetime": 86400,
|
"jwtTokenLifetime": 86400,
|
||||||
"defaultBehaviorTimeSeconds": 300,
|
"defaultBehaviorTimeSeconds": 300,
|
||||||
"maxPagesPerCrawl": 4,
|
"maxPagesPerCrawl": 4,
|
||||||
|
"maxScale": 3,
|
||||||
"defaultPageLoadTimeSeconds": 120,
|
"defaultPageLoadTimeSeconds": 120,
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import "./assets/fonts/Inter/inter.css";
|
|||||||
import "./assets/fonts/Recursive/recursive.css";
|
import "./assets/fonts/Recursive/recursive.css";
|
||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
import { theme } from "@/theme";
|
import { theme } from "@/theme";
|
||||||
|
import { DEFAULT_MAX_SCALE } from "./utils/crawler";
|
||||||
|
|
||||||
// Make theme CSS available in document
|
// Make theme CSS available in document
|
||||||
document.adoptedStyleSheets = [theme];
|
document.adoptedStyleSheets = [theme];
|
||||||
@ -79,6 +80,8 @@ export class App extends LiteElement {
|
|||||||
@state()
|
@state()
|
||||||
private isRegistrationEnabled?: boolean;
|
private isRegistrationEnabled?: boolean;
|
||||||
|
|
||||||
|
private maxScale = DEFAULT_MAX_SCALE;
|
||||||
|
|
||||||
async connectedCallback() {
|
async connectedCallback() {
|
||||||
let authState: AuthState = null;
|
let authState: AuthState = null;
|
||||||
try {
|
try {
|
||||||
@ -136,6 +139,7 @@ export class App extends LiteElement {
|
|||||||
|
|
||||||
if (settings) {
|
if (settings) {
|
||||||
this.isRegistrationEnabled = settings.registrationEnabled;
|
this.isRegistrationEnabled = settings.registrationEnabled;
|
||||||
|
this.maxScale = settings.maxScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isAppSettingsLoaded = true;
|
this.isAppSettingsLoaded = true;
|
||||||
@ -173,13 +177,19 @@ export class App extends LiteElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAppSettings(): Promise<{ registrationEnabled: boolean } | void> {
|
async getAppSettings(): Promise<{
|
||||||
|
registrationEnabled: boolean;
|
||||||
|
maxScale: number;
|
||||||
|
} | void> {
|
||||||
const resp = await fetch("/api/settings", {
|
const resp = await fetch("/api/settings", {
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const body = (await resp.json()) as { registrationEnabled: boolean };
|
const body = (await resp.json()) as {
|
||||||
|
registrationEnabled: boolean;
|
||||||
|
maxScale: number;
|
||||||
|
};
|
||||||
|
|
||||||
return body;
|
return body;
|
||||||
} else {
|
} else {
|
||||||
@ -600,6 +610,7 @@ export class App extends LiteElement {
|
|||||||
.userInfo=${this.appState.userInfo ?? undefined}
|
.userInfo=${this.appState.userInfo ?? undefined}
|
||||||
.viewStateData=${this.viewState.data}
|
.viewStateData=${this.viewState.data}
|
||||||
.params=${this.viewState.params}
|
.params=${this.viewState.params}
|
||||||
|
.maxScale=${this.maxScale}
|
||||||
slug=${slug}
|
slug=${slug}
|
||||||
orgPath=${orgPath.split(slug)[1]}
|
orgPath=${orgPath.split(slug)[1]}
|
||||||
orgTab=${orgTab as OrgTab}
|
orgTab=${orgTab as OrgTab}
|
||||||
|
@ -11,6 +11,7 @@ import type { OrgData } from "@/utils/orgs";
|
|||||||
import { isAdmin, isCrawler } from "@/utils/orgs";
|
import { isAdmin, isCrawler } from "@/utils/orgs";
|
||||||
import LiteElement, { html } from "@/utils/LiteElement";
|
import LiteElement, { html } from "@/utils/LiteElement";
|
||||||
import { needLogin } from "@/utils/auth";
|
import { needLogin } from "@/utils/auth";
|
||||||
|
import { DEFAULT_MAX_SCALE } from "@/utils/crawler";
|
||||||
import "./workflow-detail";
|
import "./workflow-detail";
|
||||||
import "./workflows-list";
|
import "./workflows-list";
|
||||||
import "./workflows-new";
|
import "./workflows-new";
|
||||||
@ -104,6 +105,9 @@ export class Org extends LiteElement {
|
|||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
orgTab: OrgTab = defaultTab;
|
orgTab: OrgTab = defaultTab;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
maxScale: number = DEFAULT_MAX_SCALE;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private orgStorageQuotaReached = false;
|
private orgStorageQuotaReached = false;
|
||||||
|
|
||||||
@ -572,6 +576,7 @@ export class Org extends LiteElement {
|
|||||||
openDialogName=${this.viewStateData?.dialog}
|
openDialogName=${this.viewStateData?.dialog}
|
||||||
?isEditing=${isEditing}
|
?isEditing=${isEditing}
|
||||||
?isCrawler=${this.isCrawler}
|
?isCrawler=${this.isCrawler}
|
||||||
|
.maxScale=${this.maxScale}
|
||||||
></btrix-workflow-detail>
|
></btrix-workflow-detail>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,11 @@ import type {
|
|||||||
} from "./types";
|
} from "./types";
|
||||||
import { humanizeSchedule } from "@/utils/cron";
|
import { humanizeSchedule } from "@/utils/cron";
|
||||||
import type { APIPaginatedList } from "@/types/api";
|
import type { APIPaginatedList } from "@/types/api";
|
||||||
import { inactiveCrawlStates, isActive } from "@/utils/crawler";
|
import {
|
||||||
|
DEFAULT_MAX_SCALE,
|
||||||
|
inactiveCrawlStates,
|
||||||
|
isActive,
|
||||||
|
} from "@/utils/crawler";
|
||||||
import type { SlSelect } from "@shoelace-style/shoelace";
|
import type { SlSelect } from "@shoelace-style/shoelace";
|
||||||
import type { PageChangeEvent } from "@/components/ui/pagination";
|
import type { PageChangeEvent } from "@/components/ui/pagination";
|
||||||
import { ExclusionEditor } from "@/features/crawl-workflows/exclusion-editor";
|
import { ExclusionEditor } from "@/features/crawl-workflows/exclusion-editor";
|
||||||
@ -70,6 +74,9 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
initialActivePanel?: Tab;
|
initialActivePanel?: Tab;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
maxScale = DEFAULT_MAX_SCALE;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private workflow?: Workflow;
|
private workflow?: Workflow;
|
||||||
|
|
||||||
@ -1261,20 +1268,13 @@ export class WorkflowDetail extends LiteElement {
|
|||||||
private renderEditScale() {
|
private renderEditScale() {
|
||||||
if (!this.workflow) return;
|
if (!this.workflow) return;
|
||||||
|
|
||||||
const scaleOptions = [
|
const scaleOptions = [];
|
||||||
{
|
for (let value = 1; value <= this.maxScale; value++) {
|
||||||
value: 1,
|
scaleOptions.push({
|
||||||
label: "1×",
|
value,
|
||||||
},
|
label: `${value}×`,
|
||||||
{
|
});
|
||||||
value: 2,
|
}
|
||||||
label: "2×",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 3,
|
|
||||||
label: "3×",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div>
|
<div>
|
||||||
|
@ -17,6 +17,8 @@ import {
|
|||||||
customElement,
|
customElement,
|
||||||
} from "lit/decorators.js";
|
} from "lit/decorators.js";
|
||||||
import { when } from "lit/directives/when.js";
|
import { when } from "lit/directives/when.js";
|
||||||
|
import { map } from "lit/directives/map.js";
|
||||||
|
import { range } from "lit/directives/range.js";
|
||||||
import { msg, localized, str } from "@lit/localize";
|
import { msg, localized, str } from "@lit/localize";
|
||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
import { choose } from "lit/directives/choose.js";
|
import { choose } from "lit/directives/choose.js";
|
||||||
@ -37,6 +39,7 @@ import {
|
|||||||
getNextDate,
|
getNextDate,
|
||||||
} from "@/utils/cron";
|
} from "@/utils/cron";
|
||||||
import { maxLengthValidator } from "@/utils/form";
|
import { maxLengthValidator } from "@/utils/form";
|
||||||
|
import { DEFAULT_MAX_SCALE } from "@/utils/crawler";
|
||||||
import type { Tab } from "@/components/ui/tab-list";
|
import type { Tab } from "@/components/ui/tab-list";
|
||||||
import type {
|
import type {
|
||||||
ExclusionRemoveEvent,
|
ExclusionRemoveEvent,
|
||||||
@ -298,6 +301,8 @@ export class CrawlConfigEditor extends LiteElement {
|
|||||||
@state()
|
@state()
|
||||||
private serverError?: TemplateResult | string;
|
private serverError?: TemplateResult | string;
|
||||||
|
|
||||||
|
private maxScale = DEFAULT_MAX_SCALE;
|
||||||
|
|
||||||
// For fuzzy search:
|
// For fuzzy search:
|
||||||
private readonly fuse = new Fuse<string>([], {
|
private readonly fuse = new Fuse<string>([], {
|
||||||
shouldSort: false,
|
shouldSort: false,
|
||||||
@ -1542,9 +1547,13 @@ https://archiveweb.page/images/${"logo.svg"}`}
|
|||||||
scale: +(e.target as SlCheckbox).value,
|
scale: +(e.target as SlCheckbox).value,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<sl-radio-button value="1" size="small">1×</sl-radio-button>
|
${map(
|
||||||
<sl-radio-button value="2" size="small">2×</sl-radio-button>
|
range(this.maxScale),
|
||||||
<sl-radio-button value="3" size="small">3×</sl-radio-button>
|
(i: number) =>
|
||||||
|
html` <sl-radio-button value="${i + 1}" size="small"
|
||||||
|
>${i + 1}×</sl-radio-button
|
||||||
|
>`,
|
||||||
|
)}
|
||||||
</sl-radio-group>
|
</sl-radio-group>
|
||||||
`)}
|
`)}
|
||||||
${this.renderHelpTextCol(
|
${this.renderHelpTextCol(
|
||||||
@ -2562,6 +2571,9 @@ https://archiveweb.page/images/${"logo.svg"}`}
|
|||||||
if (data.maxPagesPerCrawl > 0) {
|
if (data.maxPagesPerCrawl > 0) {
|
||||||
orgDefaults.maxPagesPerCrawl = data.maxPagesPerCrawl;
|
orgDefaults.maxPagesPerCrawl = data.maxPagesPerCrawl;
|
||||||
}
|
}
|
||||||
|
if (data.maxScale) {
|
||||||
|
this.maxScale = data.maxScale;
|
||||||
|
}
|
||||||
this.orgDefaults = orgDefaults;
|
this.orgDefaults = orgDefaults;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.debug(e);
|
console.debug(e);
|
||||||
|
@ -27,6 +27,8 @@ export const inactiveCrawlStates: CrawlState[] = [
|
|||||||
"failed",
|
"failed",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const DEFAULT_MAX_SCALE = 3;
|
||||||
|
|
||||||
export function isActive(state: CrawlState | null) {
|
export function isActive(state: CrawlState | null) {
|
||||||
return state && activeCrawlStates.includes(state);
|
return state && activeCrawlStates.includes(state);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user