QA review tooltip + comment improvements (#1779)

Resolves https://github.com/webrecorder/browsertrix/issues/1761

<!-- Fixes #issue_number -->

### Changes

- Switches QA review page chip tooltip colors to dark text on light
background
- Shows newest comment when hovering over comment cell in QA tab page
list to match tooltip in QA review page list
- Validates textarea max entry for description and comments
This commit is contained in:
sua yoo 2024-05-01 16:30:24 -07:00 committed by GitHub
parent 26abbddd62
commit e7dbf914a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 76 additions and 24 deletions

View File

@ -98,6 +98,6 @@ export const pageDetails = (page: ArchivedItemQAPage) =>
name="chat-square-text-fill"
class="mr-2 h-4 w-4 flex-none text-blue-600"
></sl-icon>
${page.notes[page.notes.length - 1]?.text}
${page.notes[page.notes.length - 1].text}
</div>`
: nothing}`;

View File

@ -138,8 +138,10 @@ export class QaPage extends TailwindElement {
tabindex="0"
aria-selected=${this.selected}
>
<sl-tooltip placement="left" hoist>
<div slot="content" class="text-xs">${pageDetails(page)}</div>
<sl-tooltip class="invert-tooltip" placement="left" hoist>
<div slot="content" class="max-w-60 text-xs">
${pageDetails(page)}
</div>
<div
class="absolute -left-4 top-[50%] flex w-8 translate-y-[-50%] flex-col place-items-center gap-1 rounded-full border border-gray-300 bg-neutral-0 p-2 leading-[14px] shadow transition-transform hover:scale-110"
>

View File

@ -762,19 +762,31 @@ export class ArchivedItemDetailQA extends TailwindElement {
<btrix-table-cell
>${this.renderApprovalStatus(page)}</btrix-table-cell
>
<btrix-table-cell
>${page.notes?.length
? statusWithIcon(
html`<sl-icon
name="chat-square-text-fill"
class="text-blue-600"
></sl-icon>`,
`${page.notes.length.toLocaleString()} ${pluralOf("comments", page.notes.length)}`,
)
: html`<span class="text-neutral-400"
>${msg("None")}</span
>`}</btrix-table-cell
>
<btrix-table-cell>
${page.notes?.length
? html`
<sl-tooltip class="invert-tooltip">
<div slot="content">
<div class="text-xs text-neutral-400">
${msg("Newest comment:")}
</div>
<div class="leading04 max-w-60 text-xs">
${page.notes[page.notes.length - 1].text}
</div>
</div>
${statusWithIcon(
html`<sl-icon
name="chat-square-text-fill"
class="text-blue-600"
></sl-icon>`,
`${page.notes.length.toLocaleString()} ${pluralOf("comments", page.notes.length)}`,
)}
</sl-tooltip>
`
: html`<span class="text-neutral-400">
${msg("None")}
</span>`}
</btrix-table-cell>
</btrix-table-row>
`,
)}

View File

@ -43,6 +43,7 @@ import type { ArchivedItem, ArchivedItemPageComment } from "@/types/crawler";
import type { ArchivedItemQAPage, QARun } from "@/types/qa";
import { type AuthState } from "@/utils/AuthService";
import { finishedCrawlStates, isActive, renderName } from "@/utils/crawler";
import { maxLengthValidator } from "@/utils/form";
import { formatISODateString, getLocale } from "@/utils/localization";
const DEFAULT_PAGE_SIZE = 100;
@ -158,6 +159,8 @@ export class ArchivedItemQA extends TailwindElement {
private readonly notify = new NotifyController(this);
private readonly replaySwReg =
navigator.serviceWorker.getRegistration("/replay/");
private readonly validateItemDescriptionMax = maxLengthValidator(500);
private readonly validatePageCommentMax = maxLengthValidator(500);
@query("#replayframe")
private readonly replayFrame?: HTMLIFrameElement | null;
@ -581,11 +584,18 @@ export class ArchivedItemQA extends TailwindElement {
</sl-button>
</btrix-dialog>
${this.renderReviewDialog()}
`;
}
private renderReviewDialog() {
const { helpText, validate } = this.validateItemDescriptionMax;
return html`
<btrix-dialog
class="reviewDialog [--width:60rem]"
label=${msg("QA Review")}
>
<form class="qaReviewForm" @submit=${this.onReviewSubmit}>
<form class="qaReviewForm" @submit=${this.onSubmitReview}>
<div class="flex flex-col gap-6 md:flex-row">
<div>
<sl-radio-group
@ -642,7 +652,11 @@ export class ArchivedItemQA extends TailwindElement {
label=${msg("Update archived item description?")}
name="description"
value=${this.item?.description ?? ""}
placeholder=${msg("No description")}
placeholder=${msg("No description, yet")}
rows="10"
autocomplete="off"
help-text=${helpText}
@sl-input=${validate}
></sl-textarea>
</div>
</div>
@ -720,6 +734,7 @@ export class ArchivedItemQA extends TailwindElement {
}
private renderComments() {
const { helpText, validate } = this.validatePageCommentMax;
return html`
${when(
this.page?.notes?.length,
@ -770,8 +785,10 @@ export class ArchivedItemQA extends TailwindElement {
name="pageComment"
label=${msg("Add a comment")}
placeholder=${msg("Enter page feedback")}
minlength="1"
maxlength="500"
rows="4"
autocomplete="off"
help-text=${helpText}
@sl-input=${validate}
></sl-textarea>
</form>
`;
@ -941,6 +958,9 @@ export class ArchivedItemQA extends TailwindElement {
if (!value) return;
const formEl = e.target as HTMLFormElement;
if (!(await this.checkFormValidity(formEl))) return;
void this.commentDialog?.hide();
try {
@ -975,6 +995,11 @@ export class ArchivedItemQA extends TailwindElement {
}
}
async checkFormValidity(formEl: HTMLFormElement) {
await this.updateComplete;
return !formEl.querySelector("[data-invalid]");
}
private async deletePageComment(commentId: string): Promise<void> {
try {
await this.api.fetch(
@ -1293,14 +1318,15 @@ export class ArchivedItemQA extends TailwindElement {
);
}
private async onReviewSubmit(e: SubmitEvent) {
private async onSubmitReview(e: SubmitEvent) {
e.preventDefault();
const form = e.currentTarget as HTMLFormElement;
const params = serialize(form);
if (!params.reviewStatus) {
return;
}
if (!params.reviewStatus) return;
const formEl = e.target as HTMLFormElement;
if (!(await this.checkFormValidity(formEl))) return;
try {
const data = await this.api.fetch<{ updated: boolean }>(

View File

@ -196,6 +196,18 @@
min-width: min-content;
}
/* Style tooltip with white background */
sl-tooltip.invert-tooltip {
--sl-tooltip-arrow-size: 0;
--sl-tooltip-background-color: var(--sl-color-neutral-0);
--sl-tooltip-color: var(--sl-color-neutral-700);
}
sl-tooltip.invert-tooltip::part(body) {
outline: 1px solid var(--sl-panel-border-color);
box-shadow: var(--sl-shadow-large);
}
/* For single-input forms with submit button inline */
/* Requires form control and button to be direct children */
.inline-control-input,