Allow users to configure offset when viewing crawl queued URLs (#1581)
This commit is contained in:
parent
1a668fe82f
commit
0479489bd8
@ -14,6 +14,7 @@ import("./desc-list");
|
||||
import("./details");
|
||||
import("./dialog");
|
||||
import("./file-list");
|
||||
import("./inline-input");
|
||||
import("./input");
|
||||
import("./language-select");
|
||||
import("./locale-picker");
|
||||
|
25
frontend/src/components/ui/inline-input.ts
Normal file
25
frontend/src/components/ui/inline-input.ts
Normal 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;
|
||||
}
|
@ -33,17 +33,12 @@ export class Pagination extends LitElement {
|
||||
static styles = [
|
||||
srOnly,
|
||||
css`
|
||||
:host {
|
||||
--sl-input-height-small: var(--sl-font-size-x-large);
|
||||
--sl-input-color: var(--sl-color-neutral-500);
|
||||
}
|
||||
|
||||
ul {
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--sl-input-color);
|
||||
color: var(--sl-color-neutral-500);
|
||||
}
|
||||
|
||||
ul.compact {
|
||||
@ -64,11 +59,6 @@ export class Pagination extends LitElement {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
sl-input::part(input) {
|
||||
text-align: center;
|
||||
padding: 0 0.5ch;
|
||||
}
|
||||
|
||||
.currentPage {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -211,7 +201,7 @@ export class Pagination extends LitElement {
|
||||
return html`
|
||||
<div class="pageInput">
|
||||
<div class="totalPages" role="none">${this.pages}</div>
|
||||
<sl-input
|
||||
<btrix-inline-input
|
||||
class="input"
|
||||
inputmode="numeric"
|
||||
size="small"
|
||||
@ -256,7 +246,7 @@ export class Pagination extends LitElement {
|
||||
// Select text on focus for easy typing
|
||||
(e.target as SlInput).select();
|
||||
}}
|
||||
></sl-input>
|
||||
></btrix-inline-input>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ export class Observable extends LitElement {
|
||||
|
||||
disconnectedCallback(): void {
|
||||
this.observer?.disconnect();
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
@ -1,4 +1,9 @@
|
||||
import { localized, msg, str } from "@lit/localize";
|
||||
import type {
|
||||
SlChangeEvent,
|
||||
SlInput,
|
||||
SlInputEvent,
|
||||
} from "@shoelace-style/shoelace";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { when } from "lit/directives/when.js";
|
||||
@ -60,6 +65,9 @@ export class CrawlQueue extends LiteElement {
|
||||
@state()
|
||||
private isLoading = false;
|
||||
|
||||
@state()
|
||||
private pageOffset = 0;
|
||||
|
||||
@state()
|
||||
private pageSize = 50;
|
||||
|
||||
@ -82,7 +90,10 @@ export class CrawlQueue extends LiteElement {
|
||||
changedProperties.has("orgId") ||
|
||||
changedProperties.has("crawlId") ||
|
||||
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();
|
||||
}
|
||||
@ -90,13 +101,66 @@ export class CrawlQueue extends LiteElement {
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<btrix-section-heading style="--margin: var(--sl-spacing-small)"
|
||||
>${msg("Queued URLs")} ${this.renderBadge()}</btrix-section-heading
|
||||
>
|
||||
<btrix-section-heading style="--margin: var(--sl-spacing-small)">
|
||||
${this.renderOffsetControl()} ${this.renderBadge()}
|
||||
</btrix-section-heading>
|
||||
${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() {
|
||||
if (!this.queue?.total) {
|
||||
if (this.isLoading) {
|
||||
@ -119,9 +183,9 @@ export class CrawlQueue extends LiteElement {
|
||||
const isExcluded = !isMatch && this.isExcluded(url);
|
||||
return html`
|
||||
<btrix-numbered-list-item>
|
||||
<span class="${isMatch ? "text-red-600" : ""}" slot="marker"
|
||||
>${idx + 1}.</span
|
||||
>
|
||||
<span class="${isMatch ? "text-red-600" : ""}" slot="marker">
|
||||
${(idx + this.pageOffset + 1).toLocaleString()}.
|
||||
</span>
|
||||
<a
|
||||
class="${isMatch
|
||||
? "text-red-500 hover:text-red-400"
|
||||
@ -140,7 +204,7 @@ export class CrawlQueue extends LiteElement {
|
||||
|
||||
<footer class="text-center">
|
||||
${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">
|
||||
${msg("End of queue")}
|
||||
@ -165,14 +229,6 @@ export class CrawlQueue extends LiteElement {
|
||||
if (!this.queue) return "";
|
||||
|
||||
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
|
||||
? html`
|
||||
<btrix-badge variant="danger" class="ml-1">
|
||||
@ -230,10 +286,13 @@ export class CrawlQueue extends LiteElement {
|
||||
}
|
||||
|
||||
private async getQueue(): Promise<ResponseData> {
|
||||
const offset = "0";
|
||||
const count = this.pageSize.toString();
|
||||
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(
|
||||
`/orgs/${this.orgId}/crawls/${this.crawlId}/queue?${params.toString()}`,
|
||||
this.authState!,
|
||||
|
@ -1220,7 +1220,7 @@ export class WorkflowDetail extends LiteElement {
|
||||
return html`
|
||||
<header class="flex items-center justify-between">
|
||||
<h3 class="mb-2 text-base font-semibold leading-none">
|
||||
${msg("Crawl URLs")}
|
||||
${msg("Upcoming Pages")}
|
||||
</h3>
|
||||
<sl-button
|
||||
size="small"
|
||||
|
Loading…
Reference in New Issue
Block a user