Autocomplete tag options (#505)

This commit is contained in:
sua yoo 2023-01-18 20:15:42 -08:00 committed by GitHub
parent be10ea5239
commit c0fdf738e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 11 deletions

View File

@ -10,6 +10,9 @@ export type Tags = string[];
export type TagsChangeEvent = CustomEvent<{
tags: string[];
}>;
export type TagInputEvent = CustomEvent<{
value: string;
}>;
/**
* Usage:
@ -20,6 +23,7 @@ export type TagsChangeEvent = CustomEvent<{
* ></btrix-tag-input>
* ```
*
* @events tag-input
* @events tags-change
*/
@localized()
@ -110,6 +114,9 @@ export class TagInput extends LitElement {
@property({ type: Array })
initialTags?: Tags;
@property({ type: Array })
tagOptions: Tags = [];
@property({ type: Boolean })
disabled = false;
@ -126,9 +133,6 @@ export class TagInput extends LitElement {
@state()
private dropdownIsOpen?: boolean;
@state()
private tagOptions: Tags = [];
@query("#input")
private input?: HTMLInputElement;
@ -300,8 +304,14 @@ export class TagInput extends LitElement {
this.inputValue = input.value;
if (input.value.length) {
this.dropdownIsOpen = true;
this.tagOptions = await this.getOptions();
} else {
this.dropdownIsOpen = false;
}
this.dispatchEvent(
<TagInputEvent>new CustomEvent("tag-input", {
detail: { value: input.value },
})
);
}) as any;
private onKeyup(e: KeyboardEvent) {
@ -346,10 +356,4 @@ export class TagInput extends LitElement {
})
);
}
private async getOptions() {
// TODO actual API call
// https://github.com/webrecorder/browsertrix-cloud/issues/453
return [];
}
}

View File

@ -18,6 +18,7 @@ import flow from "lodash/fp/flow";
import uniq from "lodash/fp/uniq";
import RegexColorize from "regex-colorize";
import ISO6391 from "iso-639-1";
import Fuse from "fuse.js";
import LiteElement, { html } from "../../utils/LiteElement";
import { regexEscape } from "../../utils/string";
@ -35,7 +36,11 @@ import type {
ExclusionChangeEvent,
} from "../../components/queue-exclusion-table";
import type { TimeInputChangeEvent } from "../../components/time-input";
import type { Tags, TagsChangeEvent } from "../../components/tag-input";
import type {
TagInputEvent,
Tags,
TagsChangeEvent,
} from "../../components/tag-input";
import type {
CrawlConfigParams,
Profile,
@ -195,6 +200,9 @@ export class CrawlConfigEditor extends LiteElement {
@property({ type: Object })
initialCrawlConfig?: InitialCrawlConfig;
@state()
private tagOptions: string[] = [];
@state()
private isSubmitting = false;
@ -210,6 +218,12 @@ export class CrawlConfigEditor extends LiteElement {
@state()
private serverError?: TemplateResult | string;
// For fuzzy search:
private fuse = new Fuse([], {
shouldSort: false,
threshold: 0.2, // stricter; default is 0.6
});
private get formHasError() {
return (
!this.hasRequiredFields() ||
@ -305,6 +319,9 @@ export class CrawlConfigEditor extends LiteElement {
}
}
}
if (changedProperties.get("orgId") && this.orgId) {
this.fetchTags();
}
}
async updated(changedProperties: Map<string, any>) {
@ -332,6 +349,8 @@ export class CrawlConfigEditor extends LiteElement {
"sl-input, sl-textarea, sl-select, sl-radio-group"
) as HTMLElement
)?.focus();
this.fetchTags();
}
private initializeEditor() {
@ -1317,6 +1336,8 @@ https://example.net`}
html`
<btrix-tag-input
.initialTags=${this.formState.tags}
.tagOptions=${this.tagOptions}
@tag-input=${this.onTagInput}
@tags-change=${(e: TagsChangeEvent) =>
this.updateFormState(
{
@ -1704,6 +1725,28 @@ https://example.net`}
`;
}
private onTagInput = (e: TagInputEvent) => {
const { value } = e.detail;
if (!value) return;
this.tagOptions = this.fuse.search(value).map(({ item }) => item);
};
private async fetchTags() {
this.tagOptions = [];
try {
const tags = await this.apiFetch(
`/orgs/${this.orgId}/crawlconfigs/tags`,
this.authState!
);
// Update search/filter collection
this.fuse.setCollection(tags as any);
} catch (e) {
// Fail silently, since users can still enter tags
console.debug(e);
}
}
private parseConfig(): NewCrawlConfigParams {
const config: NewCrawlConfigParams = {
jobType: this.jobType || "custom",