fix: Fix debounced inputs (#2191)
Fixes https://github.com/webrecorder/browsertrix/issues/2190 ## Changes - Fixes not being able to add live exclusion - Fixes not being able to delete last exclusion - Fixes collection list search - Refactors exclusion form event name
This commit is contained in:
parent
99115473e5
commit
2c2b8227d9
@ -89,7 +89,17 @@ export class ExclusionEditor extends LiteElement {
|
||||
? html`<btrix-queue-exclusion-table
|
||||
?removable=${this.isActiveCrawl}
|
||||
.exclusions=${this.config.exclude || []}
|
||||
@btrix-remove=${this.deleteExclusion}
|
||||
@btrix-change=${async (e: ExclusionRemoveEvent) => {
|
||||
await this.updateComplete;
|
||||
const { index, regex } = e.detail;
|
||||
if (this.config?.exclude && index === 0 && !regex) {
|
||||
void this.deleteExclusion({
|
||||
regex: this.config.exclude[index],
|
||||
});
|
||||
}
|
||||
}}
|
||||
@btrix-remove=${(e: ExclusionRemoveEvent) =>
|
||||
void this.deleteExclusion({ regex: e.detail.regex })}
|
||||
>
|
||||
</btrix-queue-exclusion-table>`
|
||||
: html`
|
||||
@ -102,8 +112,8 @@ export class ExclusionEditor extends LiteElement {
|
||||
<btrix-queue-exclusion-form
|
||||
?isSubmitting=${this.isSubmitting}
|
||||
fieldErrorMessage=${this.exclusionFieldErrorMessage}
|
||||
@on-change=${this.handleRegexChange}
|
||||
@on-add=${this.handleAddRegex}
|
||||
@btrix-change=${this.handleRegexChange}
|
||||
@btrix-add=${this.handleAddRegex}
|
||||
>
|
||||
</btrix-queue-exclusion-form>
|
||||
</div>`
|
||||
@ -138,9 +148,7 @@ export class ExclusionEditor extends LiteElement {
|
||||
}
|
||||
}
|
||||
|
||||
private async deleteExclusion(e: ExclusionRemoveEvent) {
|
||||
const { regex } = e.detail;
|
||||
|
||||
private async deleteExclusion({ regex }: { regex: string }) {
|
||||
try {
|
||||
const params = new URLSearchParams({ regex });
|
||||
const data = await this.apiFetch<{ success: boolean }>(
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { localized, msg } from "@lit/localize";
|
||||
import { type SlInput, type SlSelect } from "@shoelace-style/shoelace";
|
||||
import { type PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import debounce from "lodash/fp/debounce";
|
||||
|
||||
import type { UnderlyingFunction } from "@/types/utils";
|
||||
@ -31,13 +31,13 @@ const MIN_LENGTH = 2;
|
||||
* Usage example:
|
||||
* ```ts
|
||||
* <btrix-queue-exclusion-form
|
||||
* @on-change=${this.handleExclusionChange}
|
||||
* @on-add=${this.handleExclusionAdd}
|
||||
* @btrix-change=${this.handleExclusionChange}
|
||||
* @btrix-add=${this.handleExclusionAdd}
|
||||
* ></btrix-queue-exclusion-form>
|
||||
* ```
|
||||
*
|
||||
* @event on-change ExclusionChangeEvent
|
||||
* @event on-add ExclusionAddEvent
|
||||
* @fires btrix-change ExclusionChangeEvent
|
||||
* @fires btrix-add ExclusionAddEvent
|
||||
*/
|
||||
@localized()
|
||||
@customElement("btrix-queue-exclusion-form")
|
||||
@ -52,18 +52,21 @@ export class QueueExclusionForm extends LiteElement {
|
||||
private selectValue: Exclusion["type"] = "text";
|
||||
|
||||
@state()
|
||||
private inputValue = "";
|
||||
private regex = "";
|
||||
|
||||
@state()
|
||||
private isRegexInvalid = false;
|
||||
|
||||
@query("sl-input")
|
||||
private readonly input?: SlInput | null;
|
||||
|
||||
async willUpdate(
|
||||
changedProperties: PropertyValues<this> & Map<string, unknown>,
|
||||
) {
|
||||
if (
|
||||
changedProperties.get("selectValue") ||
|
||||
(changedProperties.has("inputValue") &&
|
||||
changedProperties.get("inputValue") !== undefined)
|
||||
(changedProperties.has("regex") &&
|
||||
changedProperties.get("regex") !== undefined)
|
||||
) {
|
||||
this.fieldErrorMessage = "";
|
||||
this.checkInputValidity();
|
||||
@ -107,7 +110,6 @@ export class QueueExclusionForm extends LiteElement {
|
||||
placeholder=${this.selectValue === "text"
|
||||
? "/skip-this-page"
|
||||
: "example.com/skip.*"}
|
||||
.value=${this.inputValue}
|
||||
?disabled=${this.isSubmitting}
|
||||
@keydown=${this.onKeyDown}
|
||||
@sl-input=${this.onInput as UnderlyingFunction<
|
||||
@ -151,7 +153,7 @@ export class QueueExclusionForm extends LiteElement {
|
||||
<btrix-button
|
||||
variant="neutral"
|
||||
raised
|
||||
?disabled=${!this.inputValue ||
|
||||
?disabled=${!this.regex ||
|
||||
this.isRegexInvalid ||
|
||||
this.isSubmitting}
|
||||
?loading=${this.isSubmitting}
|
||||
@ -166,8 +168,8 @@ export class QueueExclusionForm extends LiteElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private readonly onInput = debounce(200)((e: Event) => {
|
||||
this.inputValue = (e.target as SlInput).value;
|
||||
private readonly onInput = debounce(200)(() => {
|
||||
this.regex = this.input?.value || "";
|
||||
});
|
||||
|
||||
private onButtonClick() {
|
||||
@ -184,12 +186,12 @@ export class QueueExclusionForm extends LiteElement {
|
||||
private checkInputValidity(): void {
|
||||
let isValid = true;
|
||||
|
||||
if (!this.inputValue || this.inputValue.length < MIN_LENGTH) {
|
||||
if (!this.regex || this.regex.length < MIN_LENGTH) {
|
||||
isValid = false;
|
||||
} else if (this.selectValue === "regex") {
|
||||
try {
|
||||
// Check if valid regex
|
||||
new RegExp(this.inputValue);
|
||||
new RegExp(this.regex);
|
||||
} catch (err) {
|
||||
this.fieldErrorMessage = (err as Error).message;
|
||||
isValid = false;
|
||||
@ -202,12 +204,10 @@ export class QueueExclusionForm extends LiteElement {
|
||||
private async dispatchChangeEvent() {
|
||||
await this.updateComplete;
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("on-change", {
|
||||
new CustomEvent("btrix-change", {
|
||||
detail: {
|
||||
value:
|
||||
this.selectValue === "text"
|
||||
? regexEscape(this.inputValue)
|
||||
: this.inputValue,
|
||||
this.selectValue === "text" ? regexEscape(this.regex) : this.regex,
|
||||
valid: !this.isRegexInvalid,
|
||||
},
|
||||
}) as ExclusionChangeEvent,
|
||||
@ -217,19 +217,23 @@ export class QueueExclusionForm extends LiteElement {
|
||||
private async handleAdd() {
|
||||
this.onInput.flush();
|
||||
await this.updateComplete;
|
||||
if (!this.inputValue) return;
|
||||
if (!this.regex) return;
|
||||
|
||||
let regex = this.inputValue;
|
||||
if (this.input) {
|
||||
this.input.value = "";
|
||||
}
|
||||
|
||||
let regex = this.regex;
|
||||
if (this.selectValue === "text") {
|
||||
regex = regexEscape(this.inputValue);
|
||||
regex = regexEscape(this.regex);
|
||||
}
|
||||
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("on-add", {
|
||||
new CustomEvent("btrix-add", {
|
||||
detail: {
|
||||
regex,
|
||||
onSuccess: () => {
|
||||
this.inputValue = "";
|
||||
this.regex = "";
|
||||
},
|
||||
},
|
||||
}) as ExclusionAddEvent,
|
||||
|
@ -2,7 +2,7 @@ import { localized, msg } from "@lit/localize";
|
||||
import type { SlInput, SlMenuItem } from "@shoelace-style/shoelace";
|
||||
import Fuse from "fuse.js";
|
||||
import { html, type PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import { guard } from "lit/directives/guard.js";
|
||||
import { when } from "lit/directives/when.js";
|
||||
import debounce from "lodash/fp/debounce";
|
||||
@ -91,6 +91,9 @@ export class CollectionsList extends BtrixElement {
|
||||
@state()
|
||||
private fetchErrorStatusCode?: number;
|
||||
|
||||
@query("sl-input")
|
||||
private readonly input?: SlInput | null;
|
||||
|
||||
// For fuzzy search:
|
||||
private readonly fuse = new Fuse<{ key: "name"; value: string }>([], {
|
||||
keys: ["value"],
|
||||
@ -339,7 +342,6 @@ export class CollectionsList extends BtrixElement {
|
||||
size="small"
|
||||
placeholder=${msg("Search by Name")}
|
||||
clearable
|
||||
value=${this.searchByValue}
|
||||
@sl-clear=${() => {
|
||||
this.searchResultsOpen = false;
|
||||
this.onSearchInput.cancel();
|
||||
@ -627,8 +629,8 @@ export class CollectionsList extends BtrixElement {
|
||||
</div>
|
||||
`;
|
||||
|
||||
private readonly onSearchInput = debounce(150)((e: Event) => {
|
||||
this.searchByValue = (e.target as SlInput).value.trim();
|
||||
private readonly onSearchInput = debounce(150)(() => {
|
||||
this.searchByValue = this.input?.value.trim() || "";
|
||||
|
||||
if (!this.searchResultsOpen && this.hasSearchStr) {
|
||||
this.searchResultsOpen = true;
|
||||
|
Loading…
Reference in New Issue
Block a user