Display QA resources as table (#1692)

- Renders QA resource data as a basic table
- Updates screenshot and resource tab icons
This commit is contained in:
sua yoo 2024-04-17 19:43:34 -07:00 committed by GitHub
parent b87860c68a
commit f0921feb70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 84 additions and 76 deletions

View File

@ -426,7 +426,7 @@ export class ArchivedItemQA extends TailwindElement {
?active=${this.tab === "screenshots"} ?active=${this.tab === "screenshots"}
@click=${this.onTabNavClick} @click=${this.onTabNavClick}
> >
<sl-icon name="camera-fill"></sl-icon> <sl-icon name="images"></sl-icon>
${msg("Screenshots")} ${msg("Screenshots")}
${when(this.page?.qa || currentPage?.qa, (qa) => ${when(this.page?.qa || currentPage?.qa, (qa) =>
renderSeverityBadge(qa.screenshotMatch), renderSeverityBadge(qa.screenshotMatch),
@ -450,7 +450,7 @@ export class ArchivedItemQA extends TailwindElement {
?active=${this.tab === "resources"} ?active=${this.tab === "resources"}
@click=${this.onTabNavClick} @click=${this.onTabNavClick}
> >
<sl-icon name="list-check"></sl-icon> <sl-icon name="server"></sl-icon>
${msg("Resources")} ${msg("Resources")}
</btrix-navigation-button> </btrix-navigation-button>
<btrix-navigation-button <btrix-navigation-button

View File

@ -1,8 +1,5 @@
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { html } from "lit"; import { html } from "lit";
import { guard } from "lit/directives/guard.js";
import { until } from "lit/directives/until.js";
import { when } from "lit/directives/when.js";
import type { ReplayData, ResourcesPayload } from "../types"; import type { ReplayData, ResourcesPayload } from "../types";
@ -10,62 +7,78 @@ import { renderSpinner } from "./spinner";
import { tw } from "@/utils/tailwind"; import { tw } from "@/utils/tailwind";
const diffImport = import("diff"); const TOTAL = "Total";
function renderDiff( function renderDiff(
crawlResources: ResourcesPayload["resources"], crawlResources: ResourcesPayload["resources"],
qaResources: ResourcesPayload["resources"], qaResources: ResourcesPayload["resources"],
) { ) {
return until( const columns = [
diffImport.then(({ diffJson }) => { msg("Resource Type"),
const diff = diffJson(crawlResources, qaResources); msg("Good During Crawl"),
msg("Bad During Crawl"),
const addedText = tw`bg-red-100 text-red-700`; msg("Good in Replay"),
const removedText = tw`bg-red-100 text-red-100`; msg("Bad in Replay"),
];
const rows = [
[
html`<span class=${tw`font-semibold capitalize`}
>${msg("All Resources")}</span
>`,
html`<span class=${tw`font-semibold`}
>${crawlResources[TOTAL].good.toLocaleString()}</span
>`,
html`<span class=${tw`font-semibold`}
>${crawlResources[TOTAL].bad.toLocaleString()}</span
>`,
html`<span
class="${tw`font-semibold`} ${crawlResources[TOTAL].good !==
qaResources[TOTAL].good
? tw`text-danger`
: tw`text-neutral-700`}"
>
${qaResources[TOTAL].good.toLocaleString()}
</span>`,
html`<span
class="${tw`font-semibold`} ${crawlResources[TOTAL].bad !==
qaResources[TOTAL].bad
? tw`text-danger`
: tw`text-neutral-700`}"
>
${qaResources[TOTAL].bad.toLocaleString()}
</span>`,
],
...Object.keys(crawlResources)
.filter((key) => key !== TOTAL)
.map((key) => [
html`<span class=${tw`capitalize`}>${key}</span>`,
html`${crawlResources[key].good.toLocaleString()}`,
html`${crawlResources[key].bad.toLocaleString()}`,
html`<span
class=${crawlResources[key].good !== qaResources[key].good
? tw`text-danger`
: tw`text-neutral-400`}
>
${qaResources[key].good.toLocaleString()}
</span>`,
html`<span
class=${crawlResources[key].bad !== qaResources[key].bad
? tw`font-semibold text-danger`
: tw`text-neutral-400`}
>
${qaResources[key].bad.toLocaleString()}
</span>`,
]),
];
return html` return html`
<div <btrix-data-table .columns=${columns} .rows=${rows}></btrix-data-table>
class=${tw`flex-1 overflow-hidden whitespace-pre-line rounded-lg border-dashed p-4 first-of-type:border-r`}
aria-labelledby="crawlResourcesHeading"
>
${diff.map((part) => {
return html`
<span
class=${part.added
? removedText
: part.removed
? addedText
: ""}
>${part.value}</span
>
`; `;
})}
</div>
<div
class=${tw`flex-1 overflow-hidden whitespace-pre-line rounded-lg border-dashed p-4 first-of-type:border-r`}
aria-labelledby="qaResourcesHeading"
>
${diff.map((part) => {
return html`
<span
class=${part.added
? addedText
: part.removed
? removedText
: ""}
>${part.value}</span
>
`;
})}
</div>
`;
}),
);
} }
export function renderResources(crawlData: ReplayData, qaData: ReplayData) { export function renderResources(crawlData: ReplayData, qaData: ReplayData) {
const noData = html`<div const noData = html`<div
class=${tw`flex flex-col items-center justify-center gap-2 text-xs text-neutral-500`} class=${tw`flex h-full flex-col items-center justify-center gap-2 text-xs text-neutral-500`}
> >
<sl-icon name="slash-circle"></sl-icon> <sl-icon name="slash-circle"></sl-icon>
${msg("Resources data not available")} ${msg("Resources data not available")}
@ -73,33 +86,28 @@ export function renderResources(crawlData: ReplayData, qaData: ReplayData) {
return html` return html`
<div class=${tw`flex h-full flex-col outline`}> <div class=${tw`flex h-full flex-col outline`}>
<div class=${tw`mb-2 flex font-semibold`}> <div class=${tw`flex-1 overflow-auto overscroll-contain pb-3`}>
<h3 id="crawlResourcesHeading" class=${tw`flex-1`}> ${crawlData && qaData
${msg("Resources loaded during crawl")} ? crawlData.resources && qaData.resources
</h3>
<h3 id="qaResourcesHeading" class=${tw`flex-1`}>
${msg("Resources loaded in replay")}
</h3>
</div>
<div
class=${tw`flex-1 overflow-auto overscroll-contain rounded-lg border`}
>
${guard([crawlData, qaData], () =>
when(
crawlData && qaData,
() => html`
<div
class=${tw`flex min-h-full ${crawlData?.text && qaData?.text ? "" : tw`items-center justify-center`}`}
>
${crawlData?.resources && qaData?.resources
? renderDiff(crawlData.resources, qaData.resources) ? renderDiff(crawlData.resources, qaData.resources)
: noData} : noData
: renderSpinner()}
</div> </div>
`, <footer class=${tw`border-t pt-2 text-xs text-neutral-600`}>
renderSpinner, <p class=${tw`mb-2`}>
), ${msg('"Good" and "Bad" indicates the status code of the resource.')}
)} </p>
<dl>
<div class=${tw`flex gap-1`}>
<dt class=${tw`font-semibold`}>${msg("Good:")}</dt>
<dd>${msg("Status code between 200-399")}</dd>
</div> </div>
<div class=${tw`flex gap-1`}>
<dt class=${tw`font-semibold`}>${msg("Bad:")}</dt>
<dd>${msg("Status code between 400-599")}</dd>
</div>
</dl>
</footer>
</div> </div>
`; `;
} }