Edit crawl notes from crawl detail view (#595)

This commit is contained in:
sua yoo 2023-02-21 12:26:38 -06:00 committed by GitHub
parent 0fd18ed3dd
commit c309b809da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 17 deletions

View File

@ -51,7 +51,7 @@ export class DescList extends LitElement {
static styles = css`
dl {
display: grid;
grid-template-columns: auto;
grid-template-columns: 100%;
grid-gap: 1rem;
margin: 0;
}

View File

@ -14,6 +14,10 @@ export class Tag extends SLTag {
static styles = css`
${tagStyles}
:host {
max-width: 100%;
}
.tag {
height: var(--tag-height, 1.5rem);
background-color: var(--sl-color-blue-100);

View File

@ -4,6 +4,7 @@ import { when } from "lit/directives/when.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { msg, localized, str } from "@lit/localize";
import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
import type { SlTextarea } from "@shoelace-style/shoelace";
import Fuse from "fuse.js";
import type {
@ -29,6 +30,7 @@ const SECTIONS = [
type SectionName = typeof SECTIONS[number];
const POLL_INTERVAL_SECONDS = 10;
const CRAWL_NOTES_MAXLENGTH = 500;
/**
* Usage:
@ -209,15 +211,16 @@ export class CrawlDetail extends LiteElement {
${this.renderPanel(
html`
<div class="flex items-center justify-between">
${msg("Tags")}
${msg("Metadata")}
<sl-icon-button
class="text-base"
name="pencil"
@click=${this.openDetailEditor}
@click=${this.openMetadataEditor}
aria-label=${msg("Edit Metadata")}
></sl-icon-button>
</div>
`,
this.renderDetails()
this.renderMetadata()
)}
</div>
</div>
@ -266,13 +269,13 @@ export class CrawlDetail extends LiteElement {
</btrix-dialog>
<btrix-dialog
label=${msg("Edit Tags")}
label=${msg("Edit Metadata")}
?open=${this.openDialogName === "details"}
@sl-request-close=${() => (this.openDialogName = undefined)}
@sl-show=${() => (this.isDialogVisible = true)}
@sl-after-hide=${() => (this.isDialogVisible = false)}
>
${this.isDialogVisible ? this.renderEditDetails() : ""}
${this.isDialogVisible ? this.renderEditMetadata() : ""}
</btrix-dialog>
`;
}
@ -432,7 +435,7 @@ export class CrawlDetail extends LiteElement {
class="p-2 hover:bg-zinc-100 cursor-pointer"
role="menuitem"
@click=${(e: any) => {
this.openDetailEditor();
this.openMetadataEditor();
e.target.closest("sl-dropdown").hide();
}}
>
@ -441,7 +444,7 @@ export class CrawlDetail extends LiteElement {
name="pencil"
></sl-icon>
<span class="inline-block align-middle">
${msg("Edit Tags")}
${msg("Edit Metadata")}
</span>
</li>
<hr />
@ -774,21 +777,37 @@ export class CrawlDetail extends LiteElement {
`;
}
private renderDetails() {
private renderMetadata() {
const noneText = html`<span class="text-neutral-300">${msg("None")}</span>`;
return html`
<btrix-desc-list>
<btrix-desc-list-item label=${msg("Notes")}>
${when(
this.crawl,
() =>
when(
this.crawl!.notes?.length,
() => html`<pre class="whitespace-pre-line font-sans">
${this.crawl?.notes}
</pre
>`,
() => noneText
),
() => html`<sl-skeleton></sl-skeleton>`
)}
</btrix-desc-list-item>
<btrix-desc-list-item label=${msg("Tags")}>
${when(
this.crawl,
() =>
when(
this.crawl?.tags?.length,
this.crawl!.tags.length,
() =>
this.crawl!.tags!.map(
this.crawl!.tags.map(
(tag) =>
html`<btrix-tag class="mt-1 mr-2">${tag}</btrix-tag>`
),
() => html`${msg("None")}`
() => noneText
),
() => html`<sl-skeleton></sl-skeleton>`
)}
@ -898,15 +917,47 @@ export class CrawlDetail extends LiteElement {
`;
}
private renderEditDetails() {
private renderEditMetadata() {
if (!this.crawl) return;
const crawlNotesHelpText = msg(
str`Maximum ${CRAWL_NOTES_MAXLENGTH} characters`
);
return html`
<form
id="crawlDetailsForm"
@submit=${this.onSubmitDetails}
@submit=${this.onSubmitMetadata}
@reset=${() => (this.openDialogName = undefined)}
>
<sl-textarea
class="mb-3"
name="crawlNotes"
label=${msg("Notes")}
value=${this.crawl.notes || ""}
rows="3"
autocomplete="off"
resize="auto"
help-text=${crawlNotesHelpText}
style="--help-text-align: right"
@sl-input=${(e: CustomEvent) => {
const textarea = e.target as SlTextarea;
if (textarea.value.length > CRAWL_NOTES_MAXLENGTH) {
const overMax = textarea.value.length - CRAWL_NOTES_MAXLENGTH;
textarea.setCustomValidity(
msg(
str`Please shorten this text to ${CRAWL_NOTES_MAXLENGTH} or less characters.`
)
);
textarea.helpText =
overMax === 1
? msg(str`${overMax} character over limit`)
: msg(str`${overMax} characters over limit`);
} else {
textarea.setCustomValidity("");
textarea.helpText = crawlNotesHelpText;
}
}}
></sl-textarea>
<btrix-tag-input
.initialTags=${this.crawl.tags}
.tagOptions=${this.tagOptions}
@ -1086,16 +1137,30 @@ export class CrawlDetail extends LiteElement {
}
}
private openDetailEditor() {
private openMetadataEditor() {
this.fetchTags();
this.openDialogName = "details";
}
private async onSubmitDetails(e: SubmitEvent) {
private async onSubmitMetadata(e: SubmitEvent) {
e.preventDefault();
const formEl = e.target as HTMLFormElement;
if (!(await this.checkFormValidity(formEl))) return;
const { crawlNotes } = serialize(formEl);
if (
crawlNotes === (this.crawl!.notes ?? "") &&
JSON.stringify(this.tagsToSave) === JSON.stringify(this.crawl!.tags)
) {
// No changes have been made
this.openDialogName = undefined;
return;
}
const params = {
tags: this.tagsToSave,
notes: crawlNotes,
};
this.isSubmittingUpdate = true;
@ -1131,6 +1196,11 @@ export class CrawlDetail extends LiteElement {
this.isSubmittingUpdate = false;
}
async checkFormValidity(formEl: HTMLFormElement) {
await this.updateComplete;
return !formEl.querySelector("[data-invalid]");
}
private async scale(value: Crawl["scale"]) {
this.isSubmittingUpdate = true;

View File

@ -112,6 +112,8 @@ const theme = css`
sl-select::part(form-control-help-text) {
margin-top: var(--sl-spacing-x-small);
font-weight: 400;
/* Enable controlling help text text alignment from parent */
text-align: var(--help-text-align, left);
}
/* Elevate select and buttons */

View File

@ -26,7 +26,8 @@ export type Crawl = {
fileCount?: number;
fileSize?: number;
completions?: number;
tags?: string[];
tags: string[];
notes: string | null;
};
type ScopeType =