Edit crawl notes from crawl detail view (#595)
This commit is contained in:
parent
0fd18ed3dd
commit
c309b809da
@ -51,7 +51,7 @@ export class DescList extends LitElement {
|
|||||||
static styles = css`
|
static styles = css`
|
||||||
dl {
|
dl {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto;
|
grid-template-columns: 100%;
|
||||||
grid-gap: 1rem;
|
grid-gap: 1rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,10 @@ export class Tag extends SLTag {
|
|||||||
static styles = css`
|
static styles = css`
|
||||||
${tagStyles}
|
${tagStyles}
|
||||||
|
|
||||||
|
:host {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.tag {
|
.tag {
|
||||||
height: var(--tag-height, 1.5rem);
|
height: var(--tag-height, 1.5rem);
|
||||||
background-color: var(--sl-color-blue-100);
|
background-color: var(--sl-color-blue-100);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { when } from "lit/directives/when.js";
|
|||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
import { msg, localized, str } from "@lit/localize";
|
import { msg, localized, str } from "@lit/localize";
|
||||||
import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
|
import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
|
||||||
|
import type { SlTextarea } from "@shoelace-style/shoelace";
|
||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
@ -29,6 +30,7 @@ const SECTIONS = [
|
|||||||
type SectionName = typeof SECTIONS[number];
|
type SectionName = typeof SECTIONS[number];
|
||||||
|
|
||||||
const POLL_INTERVAL_SECONDS = 10;
|
const POLL_INTERVAL_SECONDS = 10;
|
||||||
|
const CRAWL_NOTES_MAXLENGTH = 500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usage:
|
* Usage:
|
||||||
@ -209,15 +211,16 @@ export class CrawlDetail extends LiteElement {
|
|||||||
${this.renderPanel(
|
${this.renderPanel(
|
||||||
html`
|
html`
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
${msg("Tags")}
|
${msg("Metadata")}
|
||||||
<sl-icon-button
|
<sl-icon-button
|
||||||
class="text-base"
|
class="text-base"
|
||||||
name="pencil"
|
name="pencil"
|
||||||
@click=${this.openDetailEditor}
|
@click=${this.openMetadataEditor}
|
||||||
|
aria-label=${msg("Edit Metadata")}
|
||||||
></sl-icon-button>
|
></sl-icon-button>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
this.renderDetails()
|
this.renderMetadata()
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -266,13 +269,13 @@ export class CrawlDetail extends LiteElement {
|
|||||||
</btrix-dialog>
|
</btrix-dialog>
|
||||||
|
|
||||||
<btrix-dialog
|
<btrix-dialog
|
||||||
label=${msg("Edit Tags")}
|
label=${msg("Edit Metadata")}
|
||||||
?open=${this.openDialogName === "details"}
|
?open=${this.openDialogName === "details"}
|
||||||
@sl-request-close=${() => (this.openDialogName = undefined)}
|
@sl-request-close=${() => (this.openDialogName = undefined)}
|
||||||
@sl-show=${() => (this.isDialogVisible = true)}
|
@sl-show=${() => (this.isDialogVisible = true)}
|
||||||
@sl-after-hide=${() => (this.isDialogVisible = false)}
|
@sl-after-hide=${() => (this.isDialogVisible = false)}
|
||||||
>
|
>
|
||||||
${this.isDialogVisible ? this.renderEditDetails() : ""}
|
${this.isDialogVisible ? this.renderEditMetadata() : ""}
|
||||||
</btrix-dialog>
|
</btrix-dialog>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -432,7 +435,7 @@ export class CrawlDetail extends LiteElement {
|
|||||||
class="p-2 hover:bg-zinc-100 cursor-pointer"
|
class="p-2 hover:bg-zinc-100 cursor-pointer"
|
||||||
role="menuitem"
|
role="menuitem"
|
||||||
@click=${(e: any) => {
|
@click=${(e: any) => {
|
||||||
this.openDetailEditor();
|
this.openMetadataEditor();
|
||||||
e.target.closest("sl-dropdown").hide();
|
e.target.closest("sl-dropdown").hide();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -441,7 +444,7 @@ export class CrawlDetail extends LiteElement {
|
|||||||
name="pencil"
|
name="pencil"
|
||||||
></sl-icon>
|
></sl-icon>
|
||||||
<span class="inline-block align-middle">
|
<span class="inline-block align-middle">
|
||||||
${msg("Edit Tags")}
|
${msg("Edit Metadata")}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<hr />
|
<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`
|
return html`
|
||||||
<btrix-desc-list>
|
<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")}>
|
<btrix-desc-list-item label=${msg("Tags")}>
|
||||||
${when(
|
${when(
|
||||||
this.crawl,
|
this.crawl,
|
||||||
() =>
|
() =>
|
||||||
when(
|
when(
|
||||||
this.crawl?.tags?.length,
|
this.crawl!.tags.length,
|
||||||
() =>
|
() =>
|
||||||
this.crawl!.tags!.map(
|
this.crawl!.tags.map(
|
||||||
(tag) =>
|
(tag) =>
|
||||||
html`<btrix-tag class="mt-1 mr-2">${tag}</btrix-tag>`
|
html`<btrix-tag class="mt-1 mr-2">${tag}</btrix-tag>`
|
||||||
),
|
),
|
||||||
() => html`${msg("None")}`
|
() => noneText
|
||||||
),
|
),
|
||||||
() => html`<sl-skeleton></sl-skeleton>`
|
() => html`<sl-skeleton></sl-skeleton>`
|
||||||
)}
|
)}
|
||||||
@ -898,15 +917,47 @@ export class CrawlDetail extends LiteElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderEditDetails() {
|
private renderEditMetadata() {
|
||||||
if (!this.crawl) return;
|
if (!this.crawl) return;
|
||||||
|
|
||||||
|
const crawlNotesHelpText = msg(
|
||||||
|
str`Maximum ${CRAWL_NOTES_MAXLENGTH} characters`
|
||||||
|
);
|
||||||
return html`
|
return html`
|
||||||
<form
|
<form
|
||||||
id="crawlDetailsForm"
|
id="crawlDetailsForm"
|
||||||
@submit=${this.onSubmitDetails}
|
@submit=${this.onSubmitMetadata}
|
||||||
@reset=${() => (this.openDialogName = undefined)}
|
@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
|
<btrix-tag-input
|
||||||
.initialTags=${this.crawl.tags}
|
.initialTags=${this.crawl.tags}
|
||||||
.tagOptions=${this.tagOptions}
|
.tagOptions=${this.tagOptions}
|
||||||
@ -1086,16 +1137,30 @@ export class CrawlDetail extends LiteElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private openDetailEditor() {
|
private openMetadataEditor() {
|
||||||
this.fetchTags();
|
this.fetchTags();
|
||||||
this.openDialogName = "details";
|
this.openDialogName = "details";
|
||||||
}
|
}
|
||||||
|
|
||||||
private async onSubmitDetails(e: SubmitEvent) {
|
private async onSubmitMetadata(e: SubmitEvent) {
|
||||||
e.preventDefault();
|
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 = {
|
const params = {
|
||||||
tags: this.tagsToSave,
|
tags: this.tagsToSave,
|
||||||
|
notes: crawlNotes,
|
||||||
};
|
};
|
||||||
this.isSubmittingUpdate = true;
|
this.isSubmittingUpdate = true;
|
||||||
|
|
||||||
@ -1131,6 +1196,11 @@ export class CrawlDetail extends LiteElement {
|
|||||||
this.isSubmittingUpdate = false;
|
this.isSubmittingUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkFormValidity(formEl: HTMLFormElement) {
|
||||||
|
await this.updateComplete;
|
||||||
|
return !formEl.querySelector("[data-invalid]");
|
||||||
|
}
|
||||||
|
|
||||||
private async scale(value: Crawl["scale"]) {
|
private async scale(value: Crawl["scale"]) {
|
||||||
this.isSubmittingUpdate = true;
|
this.isSubmittingUpdate = true;
|
||||||
|
|
||||||
|
|||||||
@ -112,6 +112,8 @@ const theme = css`
|
|||||||
sl-select::part(form-control-help-text) {
|
sl-select::part(form-control-help-text) {
|
||||||
margin-top: var(--sl-spacing-x-small);
|
margin-top: var(--sl-spacing-x-small);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
/* Enable controlling help text text alignment from parent */
|
||||||
|
text-align: var(--help-text-align, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Elevate select and buttons */
|
/* Elevate select and buttons */
|
||||||
|
|||||||
@ -26,7 +26,8 @@ export type Crawl = {
|
|||||||
fileCount?: number;
|
fileCount?: number;
|
||||||
fileSize?: number;
|
fileSize?: number;
|
||||||
completions?: number;
|
completions?: number;
|
||||||
tags?: string[];
|
tags: string[];
|
||||||
|
notes: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ScopeType =
|
type ScopeType =
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user