Skip to content

fix: Superadmin active crawl count inaccuracies #2706

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions frontend/src/features/admin/active-crawls-badge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { localized } from "@lit/localize";
import { Task } from "@lit/task";
import { html } from "lit";
import { customElement } from "lit/decorators.js";
import queryString from "query-string";

import { BtrixElement } from "@/classes/BtrixElement";
import type { APIPaginatedList } from "@/types/api";
import type { Crawl } from "@/types/crawler";

const POLL_INTERVAL_SECONDS = 30;

@customElement("btrix-active-crawls-badge")
@localized()
export class ActiveCrawlsBadge extends BtrixElement {
private readonly activeCrawlsTotalTask = new Task(this, {
task: async () => {
return await this.getActiveCrawlsTotal();
},
args: () => [] as const,
});

private readonly pollTask = new Task(this, {
task: async () => {
window.clearTimeout(this.pollTask.value);

return window.setTimeout(() => {
void this.activeCrawlsTotalTask.run();
}, POLL_INTERVAL_SECONDS * 1000);
},
args: () => [this.activeCrawlsTotalTask.value] as const,
});

disconnectedCallback(): void {
super.disconnectedCallback();

window.clearTimeout(this.pollTask.value);
}

render() {
if (this.activeCrawlsTotalTask.value) {
const { total } = this.activeCrawlsTotalTask.value;
return html`<btrix-badge variant=${total > 0 ? "primary" : "blue"}>
${this.localize.number(total)}
</btrix-badge>`;
}
}

private async getActiveCrawlsTotal() {
const query = queryString.stringify({
pageSize: 1,
});

const data = await this.api.fetch<APIPaginatedList<Crawl>>(
`/orgs/all/crawls?${query}`,
);

return data;
}
}
1 change: 1 addition & 0 deletions frontend/src/features/admin/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import "./active-crawls-badge";
import "./stats";
import "./super-admin-banner";
53 changes: 2 additions & 51 deletions frontend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import "./global";

import { provide } from "@lit/context";
import { localized, msg, str } from "@lit/localize";
import { Task } from "@lit/task";
import type {
SlDialog,
SlDrawer,
Expand All @@ -15,7 +14,6 @@ import { ifDefined } from "lit/directives/if-defined.js";
import { until } from "lit/directives/until.js";
import { when } from "lit/directives/when.js";
import isEqual from "lodash/fp/isEqual";
import queryString from "query-string";

import "./components";
import "./features";
Expand All @@ -35,9 +33,7 @@ import AuthService, {
import { BtrixElement } from "@/classes/BtrixElement";
import type { NavigateEventDetail } from "@/controllers/navigate";
import type { NotifyEventDetail } from "@/controllers/notify";
import type { APIPaginatedList } from "@/types/api";
import { type Auth } from "@/types/auth";
import type { Crawl } from "@/types/crawler";
import {
translatedLocales,
type TranslatedLocaleEnum,
Expand Down Expand Up @@ -70,8 +66,6 @@ export interface UserGuideEventMap {
"btrix-user-guide-show": CustomEvent<{ path?: string }>;
}

const POLL_INTERVAL_SECONDS = 30;

@customElement("browsertrix-app")
@localized()
export class App extends BtrixElement {
Expand Down Expand Up @@ -114,24 +108,6 @@ export class App extends BtrixElement {
@query("#userGuideDrawer")
private readonly userGuideDrawer!: SlDrawer;

private readonly activeCrawlsTotalTask = new Task(this, {
task: async () => {
return await this.getActiveCrawlsTotal();
},
args: () => [] as const,
});

private readonly pollTask = new Task(this, {
task: async ([crawls]) => {
if (!crawls) return;

return window.setTimeout(() => {
void this.activeCrawlsTotalTask.run();
}, POLL_INTERVAL_SECONDS * 1000);
},
args: () => [this.activeCrawlsTotalTask.value] as const,
});

get orgSlugInPath() {
return this.viewState.params.slug || "";
}
Expand Down Expand Up @@ -188,12 +164,6 @@ export class App extends BtrixElement {
this.startSyncBrowserTabs();
}

disconnectedCallback(): void {
super.disconnectedCallback();

window.clearTimeout(this.pollTask.value);
}

private attachUserGuideListeners() {
this.addEventListener(
"btrix-user-guide-show",
Expand Down Expand Up @@ -479,7 +449,7 @@ export class App extends BtrixElement {
}

private renderNavBar() {
const isSuperAdmin = this.userInfo?.isSuperAdmin;
const isSuperAdmin = this.authState && this.userInfo?.isSuperAdmin;

const showFullLogo =
this.viewState.route === "login" || !this.authService.authState;
Expand Down Expand Up @@ -629,14 +599,7 @@ export class App extends BtrixElement {
@click=${this.navigate.link}
>
${msg("Active Crawls")}
${when(
this.activeCrawlsTotalTask.value,
(total) => html`
<btrix-badge variant=${total > 0 ? "primary" : "blue"}>
${this.localize.number(total)}
</btrix-badge>
`,
)}
<btrix-active-crawls-badge></btrix-active-crawls-badge>
</a>
</div>
`
Expand Down Expand Up @@ -1183,16 +1146,4 @@ export class App extends BtrixElement {
private clearSelectedOrg() {
AppStateService.updateOrgSlug(null);
}

private async getActiveCrawlsTotal() {
const query = queryString.stringify({
pageSize: 1,
});

const data = await this.api.fetch<APIPaginatedList<Crawl>>(
`/orgs/all/crawls?${query}`,
);

return data.total;
}
}
Loading