Allow users to configure offset when viewing crawl queued URLs (#1581)

This commit is contained in:
sua yoo 2024-05-15 14:42:00 -07:00 committed by GitHub
parent 1a668fe82f
commit 0479489bd8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 108 additions and 32 deletions

View File

@ -14,6 +14,7 @@ import("./desc-list");
import("./details"); import("./details");
import("./dialog"); import("./dialog");
import("./file-list"); import("./file-list");
import("./inline-input");
import("./input"); import("./input");
import("./language-select"); import("./language-select");
import("./locale-picker"); import("./locale-picker");

View File

@ -0,0 +1,25 @@
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
import inputStyles from "@shoelace-style/shoelace/dist/components/input/input.styles.js";
import { css } from "lit";
import { customElement } from "lit/decorators.js";
/**
* Input to use inline with text.
*/
@customElement("btrix-inline-input")
export class InlineInput extends SlInput {
static styles = [
inputStyles,
css`
:host {
--sl-input-height-small: var(--sl-font-size-x-large);
--sl-input-color: var(--sl-color-neutral-500);
}
.input--small .input__control {
text-align: center;
padding: 0 0.5ch;
}
`,
] as typeof SlInput.styles;
}

View File

@ -33,17 +33,12 @@ export class Pagination extends LitElement {
static styles = [ static styles = [
srOnly, srOnly,
css` css`
:host {
--sl-input-height-small: var(--sl-font-size-x-large);
--sl-input-color: var(--sl-color-neutral-500);
}
ul { ul {
align-items: center; align-items: center;
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
color: var(--sl-input-color); color: var(--sl-color-neutral-500);
} }
ul.compact { ul.compact {
@ -64,11 +59,6 @@ export class Pagination extends LitElement {
cursor: pointer; cursor: pointer;
} }
sl-input::part(input) {
text-align: center;
padding: 0 0.5ch;
}
.currentPage { .currentPage {
display: flex; display: flex;
align-items: center; align-items: center;
@ -211,7 +201,7 @@ export class Pagination extends LitElement {
return html` return html`
<div class="pageInput"> <div class="pageInput">
<div class="totalPages" role="none">${this.pages}</div> <div class="totalPages" role="none">${this.pages}</div>
<sl-input <btrix-inline-input
class="input" class="input"
inputmode="numeric" inputmode="numeric"
size="small" size="small"
@ -256,7 +246,7 @@ export class Pagination extends LitElement {
// Select text on focus for easy typing // Select text on focus for easy typing
(e.target as SlInput).select(); (e.target as SlInput).select();
}} }}
></sl-input> ></btrix-inline-input>
</div> </div>
`; `;
} }

View File

@ -32,6 +32,7 @@ export class Observable extends LitElement {
disconnectedCallback(): void { disconnectedCallback(): void {
this.observer?.disconnect(); this.observer?.disconnect();
super.disconnectedCallback();
} }
firstUpdated() { firstUpdated() {

View File

@ -1,4 +1,9 @@
import { localized, msg, str } from "@lit/localize"; import { localized, msg, str } from "@lit/localize";
import type {
SlChangeEvent,
SlInput,
SlInputEvent,
} from "@shoelace-style/shoelace";
import type { PropertyValues } from "lit"; import type { PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { when } from "lit/directives/when.js"; import { when } from "lit/directives/when.js";
@ -60,6 +65,9 @@ export class CrawlQueue extends LiteElement {
@state() @state()
private isLoading = false; private isLoading = false;
@state()
private pageOffset = 0;
@state() @state()
private pageSize = 50; private pageSize = 50;
@ -82,7 +90,10 @@ export class CrawlQueue extends LiteElement {
changedProperties.has("orgId") || changedProperties.has("orgId") ||
changedProperties.has("crawlId") || changedProperties.has("crawlId") ||
changedProperties.has("pageSize") || changedProperties.has("pageSize") ||
changedProperties.has("regex") changedProperties.has("regex") ||
(changedProperties.has("pageOffset") &&
// Prevents double-fetch when offset is programmatically changed according to queue total
!changedProperties.has("queue"))
) { ) {
void this.fetchOnUpdate(); void this.fetchOnUpdate();
} }
@ -90,13 +101,66 @@ export class CrawlQueue extends LiteElement {
render() { render() {
return html` return html`
<btrix-section-heading style="--margin: var(--sl-spacing-small)" <btrix-section-heading style="--margin: var(--sl-spacing-small)">
>${msg("Queued URLs")} ${this.renderBadge()}</btrix-section-heading ${this.renderOffsetControl()} ${this.renderBadge()}
> </btrix-section-heading>
${this.renderContent()} ${this.renderContent()}
`; `;
} }
private renderOffsetControl() {
if (!this.queue) {
return msg("Queued URLs");
}
if (this.pageOffset === 0 && this.queue.total <= this.pageSize) {
return msg(
str`Queued URLs from 1 to ${this.queue.total.toLocaleString()}`,
);
}
const offsetValue = this.pageOffset + 1;
const countMax = Math.min(
this.pageOffset + this.pageSize,
this.queue.total,
);
const getInputWidth = (v: number | string) =>
`${Math.max(v.toString().length, 3) + 2}ch`;
return html`
<div class="flex items-center text-neutral-500">
${msg(html`
Queued URLs from
<btrix-inline-input
class="mx-1 inline-block"
style="width: ${Math.max(offsetValue.toString().length, 2) + 2}ch"
value="1"
inputmode="numeric"
size="small"
autocomplete="off"
@sl-input=${(e: SlInputEvent) => {
const input = e.target as SlInput;
input.style.width = getInputWidth(input.value);
}}
@sl-change=${async (e: SlChangeEvent) => {
const input = e.target as SlInput;
const int = +input.value.replace(/\D/g, "");
await this.updateComplete;
const value = Math.max(1, Math.min(int, this.queue!.total - 1));
input.value = value.toString();
this.pageOffset = value - 1;
}}
></btrix-inline-input>
to ${countMax.toLocaleString()} of
${this.queue.total.toLocaleString()}
`)}
</div>
`;
}
private renderContent() { private renderContent() {
if (!this.queue?.total) { if (!this.queue?.total) {
if (this.isLoading) { if (this.isLoading) {
@ -119,9 +183,9 @@ export class CrawlQueue extends LiteElement {
const isExcluded = !isMatch && this.isExcluded(url); const isExcluded = !isMatch && this.isExcluded(url);
return html` return html`
<btrix-numbered-list-item> <btrix-numbered-list-item>
<span class="${isMatch ? "text-red-600" : ""}" slot="marker" <span class="${isMatch ? "text-red-600" : ""}" slot="marker">
>${idx + 1}.</span ${(idx + this.pageOffset + 1).toLocaleString()}.
> </span>
<a <a
class="${isMatch class="${isMatch
? "text-red-500 hover:text-red-400" ? "text-red-500 hover:text-red-400"
@ -140,7 +204,7 @@ export class CrawlQueue extends LiteElement {
<footer class="text-center"> <footer class="text-center">
${when( ${when(
this.queue.total === this.queue.results.length, this.queue.total <= this.pageOffset + this.pageSize,
() => () =>
html`<div class="py-3 text-xs text-neutral-400"> html`<div class="py-3 text-xs text-neutral-400">
${msg("End of queue")} ${msg("End of queue")}
@ -165,14 +229,6 @@ export class CrawlQueue extends LiteElement {
if (!this.queue) return ""; if (!this.queue) return "";
return html` return html`
<btrix-badge class="ml-1">
${this.queue.total
? this.queue.total > 1
? msg(str`${this.queue.total.toLocaleString()} URLs`)
: msg(str`1 URL`)
: msg("No queue")}
</btrix-badge>
${this.matchedTotal ${this.matchedTotal
? html` ? html`
<btrix-badge variant="danger" class="ml-1"> <btrix-badge variant="danger" class="ml-1">
@ -230,10 +286,13 @@ export class CrawlQueue extends LiteElement {
} }
private async getQueue(): Promise<ResponseData> { private async getQueue(): Promise<ResponseData> {
const offset = "0";
const count = this.pageSize.toString(); const count = this.pageSize.toString();
const regex = this.regex; const regex = this.regex;
const params = new URLSearchParams({ offset, count, regex }); const params = new URLSearchParams({
offset: this.pageOffset.toString(),
count,
regex,
});
const data: ResponseData = await this.apiFetch( const data: ResponseData = await this.apiFetch(
`/orgs/${this.orgId}/crawls/${this.crawlId}/queue?${params.toString()}`, `/orgs/${this.orgId}/crawls/${this.crawlId}/queue?${params.toString()}`,
this.authState!, this.authState!,

View File

@ -1220,7 +1220,7 @@ export class WorkflowDetail extends LiteElement {
return html` return html`
<header class="flex items-center justify-between"> <header class="flex items-center justify-between">
<h3 class="mb-2 text-base font-semibold leading-none"> <h3 class="mb-2 text-base font-semibold leading-none">
${msg("Crawl URLs")} ${msg("Upcoming Pages")}
</h3> </h3>
<sl-button <sl-button
size="small" size="small"