Skip to content

Commit

Permalink
Display QA resources as table (webrecorder#1692)
Browse files Browse the repository at this point in the history
- Renders QA resource data as a basic table
- Updates screenshot and resource tab icons
  • Loading branch information
SuaYoo authored Apr 18, 2024
1 parent b87860c commit f0921fe
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 76 deletions.
4 changes: 2 additions & 2 deletions frontend/src/pages/org/archived-item-qa/archived-item-qa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ export class ArchivedItemQA extends TailwindElement {
?active=${this.tab === "screenshots"}
@click=${this.onTabNavClick}
>
<sl-icon name="camera-fill"></sl-icon>
<sl-icon name="images"></sl-icon>
${msg("Screenshots")}
${when(this.page?.qa || currentPage?.qa, (qa) =>
renderSeverityBadge(qa.screenshotMatch),
Expand All @@ -450,7 +450,7 @@ export class ArchivedItemQA extends TailwindElement {
?active=${this.tab === "resources"}
@click=${this.onTabNavClick}
>
<sl-icon name="list-check"></sl-icon>
<sl-icon name="server"></sl-icon>
${msg("Resources")}
</btrix-navigation-button>
<btrix-navigation-button
Expand Down
156 changes: 82 additions & 74 deletions frontend/src/pages/org/archived-item-qa/ui/resources.ts
Original file line number Diff line number Diff line change
@@ -1,105 +1,113 @@
import { msg } from "@lit/localize";
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 { renderSpinner } from "./spinner";

import { tw } from "@/utils/tailwind";

const diffImport = import("diff");
const TOTAL = "Total";

function renderDiff(
crawlResources: ResourcesPayload["resources"],
qaResources: ResourcesPayload["resources"],
) {
return until(
diffImport.then(({ diffJson }) => {
const diff = diffJson(crawlResources, qaResources);

const addedText = tw`bg-red-100 text-red-700`;
const removedText = tw`bg-red-100 text-red-100`;

return html`
<div
class=${tw`flex-1 overflow-hidden whitespace-pre-line rounded-lg border-dashed p-4 first-of-type:border-r`}
aria-labelledby="crawlResourcesHeading"
const columns = [
msg("Resource Type"),
msg("Good During Crawl"),
msg("Bad During Crawl"),
msg("Good in Replay"),
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`}
>
${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"
${qaResources[key].good.toLocaleString()}
</span>`,
html`<span
class=${crawlResources[key].bad !== qaResources[key].bad
? tw`font-semibold text-danger`
: tw`text-neutral-400`}
>
${diff.map((part) => {
return html`
<span
class=${part.added
? addedText
: part.removed
? removedText
: ""}
>${part.value}</span
>
`;
})}
</div>
`;
}),
);
${qaResources[key].bad.toLocaleString()}
</span>`,
]),
];

return html`
<btrix-data-table .columns=${columns} .rows=${rows}></btrix-data-table>
`;
}

export function renderResources(crawlData: ReplayData, qaData: ReplayData) {
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>
${msg("Resources data not available")}
</div>`;

return html`
<div class=${tw`flex h-full flex-col outline`}>
<div class=${tw`mb-2 flex font-semibold`}>
<h3 id="crawlResourcesHeading" class=${tw`flex-1`}>
${msg("Resources loaded during crawl")}
</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)
: noData}
</div>
`,
renderSpinner,
),
)}
<div class=${tw`flex-1 overflow-auto overscroll-contain pb-3`}>
${crawlData && qaData
? crawlData.resources && qaData.resources
? renderDiff(crawlData.resources, qaData.resources)
: noData
: renderSpinner()}
</div>
<footer class=${tw`border-t pt-2 text-xs text-neutral-600`}>
<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 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>
`;
}

0 comments on commit f0921fe

Please sign in to comment.