Skip to content

Commit

Permalink
Initial QA Review UI! (#1624)
Browse files Browse the repository at this point in the history
QA Details page:
- Enables QA tab with ability to start automated analysis QA Run + view a and manual review status
- Pages listed with review status + overall crawl review status shown on QA details (relates to #1508)
- Initial placeholder for QA run analytics (part of #1589)
- Addresses a good deal of #1477

Automated Analysis QA in Review Mode:
- Ability to select from multiple analysis QA runs / view QA runs in QA details
- Shows analysis screenshot, text and resources compare and replay tabs (fixes #1496)
- Sorting by worst screenshot / worst text score for each QA run
- Includes pages sidebar with screenshot/text/resource compare results (fixes #1497)

Manual Review QA in Review Mode:
- Per-page replay available as separate tab (fixes #1499)
- Supports thumbs up, thumbs down, notes for each page
- Supports entering review status approval (good/acceptable/bad can be entered when finishing review

---------
Co-authored-by: Emma Segal-Grossman <hi@emma.cafe>
Co-authored-by: Ilya Kreymer <ikreymer@gmail.com>
Co-authored-by: Henry Wilkinson <henry@wilkinson.graphics>
  • Loading branch information
SuaYoo committed Apr 4, 2024
1 parent 432a727 commit 83c9203
Show file tree
Hide file tree
Showing 68 changed files with 4,008 additions and 591 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/frontend-build-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
working-directory: frontend
# TODO Reenable when https://github.com/webrecorder/browsertrix-cloud/issues/1618 is addressed
# run: yarn format:check
run: yarn prettier --list-different .
run: echo "yarn format:check disabled"
- name: Unit tests
working-directory: frontend
run: yarn test
Expand Down
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"cSpell.words": [
"Browsertrix",
"btrix",
"clsx",
"Elems",
"favicons",
"hoverable",
Expand Down Expand Up @@ -48,5 +49,9 @@
],
"eslint.workingDirectories": ["./frontend"],
"eslint.nodePath": "./frontend/node_modules",
"tailwindCSS.experimental.classRegex": ["tw`([^`]*)"]
"tailwindCSS.experimental.classRegex": ["tw`([^`]*)", "clsx\\(([^)]*)\\)"],
"html.customData": [
"./node_modules/@shoelace-style/shoelace/dist/vscode.html-custom-data.json"
],
"prettier.configPath": "./frontend/prettier.config.js"
}
22 changes: 22 additions & 0 deletions .vscode/snippets.code-snippets
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"Tailwind Component": {
"scope": "javascript,typescript",
"prefix": ["component", "@customElement"],
"body": [
"import { localized } from \"@lit/localize\";",
"import { html } from \"lit\";",
"import { customElement } from \"lit/decorators.js\";",
"",
"import { TailwindElement } from \"@/classes/TailwindElement\";",
"",
"@localized()",
"@customElement(\"btrix-${1:component}\")",
"export class ${2:Component} extends TailwindElement {",
"\trender() {",
"\t\treturn html``;",
"\t}",
"}",
""
]
}
}
2 changes: 1 addition & 1 deletion backend/btrixcloud/operator/crawls.py
Original file line number Diff line number Diff line change
Expand Up @@ -1266,7 +1266,7 @@ async def update_crawl_state(

# check for other statuses
else:
new_status: TYPE_RUNNING_STATES
new_status: Optional[TYPE_RUNNING_STATES] = None
if status_count.get("running"):
if status.state in ("generate-wacz", "uploading-wacz", "pending-wacz"):
new_status = "running"
Expand Down
6 changes: 6 additions & 0 deletions frontend/config/dev-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,11 @@ module.exports = {
res.set("Content-Type", "application/javascript");
res.redirect(307, RWP_BASE_URL + "ui.js");
});

// serve a 404 page for /replay/ path, as that should be taken over by RWP
server.app.get("/replay/*", (req, res) => {
res.set("Content-Type", "application/javascript");
res.status(404).send(`{"error": "placeholder_for_replay"}`);
});
},
};
6 changes: 6 additions & 0 deletions frontend/frontend.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ server {
return 307 ${RWP_BASE_URL}ui.js;
}

# serve a 404 page for /replay/ path, as that should be taken over by RWP
location /replay/ {
default_type application/json;
return 404 "{\"error\": \"placeholder_for_replay\"}";
}

# used by docker only: k8s deployment handles /api directly via ingress
location /api/ {
proxy_pass http://${BACKEND_HOST}:8000;
Expand Down
8 changes: 6 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
"@lit/localize": "^0.12.1",
"@novnc/novnc": "^1.4.0-beta",
"@rollup/plugin-commonjs": "^18.0.0",
"@shoelace-style/shoelace": "~2.10.0",
"@shoelace-style/shoelace": "~2.13.0",
"@tailwindcss/container-queries": "^0.1.1",
"@types/color": "^3.0.2",
"@types/diff": "^5.0.9",
"@types/lodash": "^4.14.178",
"@types/sinon": "^10.0.6",
"@typescript-eslint/eslint-plugin": "^6.20.0",
Expand All @@ -23,10 +25,12 @@
"autoprefixer": "^10.4.2",
"axios": "^0.22.0",
"broadcastchannel-polyfill": "^1.0.1",
"clsx": "^2.1.0",
"color": "^4.0.1",
"copy-webpack-plugin": "^9.1.0",
"css-loader": "^6.3.0",
"del-cli": "^4.0.1",
"diff": "^5.2.0",
"dotenv": "^10.0.0",
"dotenv-webpack": "^7.0.3",
"eslint": "^8.56.0",
Expand Down Expand Up @@ -99,7 +103,7 @@
"@web/dev-server-rollup": "^0.6.1",
"husky": "^8.0.3",
"lint-staged": "^13.1.0",
"prettier-plugin-tailwindcss": "^0.5.11",
"prettier-plugin-tailwindcss": "^0.5.12",
"rollup-plugin-typescript-paths": "^1.4.0",
"sinon": "^12.0.1",
"ts-lit-plugin": "^2.0.1",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/assets/icons/microscope.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 40 additions & 14 deletions frontend/src/components/ui/badge.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import SlBadge from "@shoelace-style/shoelace/dist/components/badge/badge.component.js";
import badgeStyles from "@shoelace-style/shoelace/dist/components/badge/badge.styles.js";
import { css } from "lit";
import { css, html } from "lit";
import { customElement, property } from "lit/decorators.js";

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

export type BadgeVariant =
| "success"
| "warning"
| "danger"
| "neutral"
| "primary"
| "high-contrast";

/**
* Show numeric value in a label
*
Expand All @@ -12,18 +21,35 @@ import { customElement, property } from "lit/decorators.js";
* ```
*/
@customElement("btrix-badge")
export class Badge extends SlBadge {
static styles = [
badgeStyles,
css`
.badge {
border-color: rgba(255, 255, 255, 0.5);
line-height: 1rem;
padding: 0 1ch;
}
`,
];
export class Badge extends TailwindElement {
@property({ type: String })
variant: BadgeVariant = "neutral";

@property({ type: String, reflect: true })
role: string | null = "status";

static styles = css`
:host {
display: inline-flex;
}
`;

render() {
return html`
<span
class="h-4.5 ${{
success: tw`bg-success-500 text-neutral-0`,
warning: tw`bg-warning-600 text-neutral-0`,
danger: tw`bg-danger-500 text-neutral-0`,
neutral: tw`bg-neutral-100 text-neutral-600`,
"high-contrast": tw`bg-neutral-600 text-neutral-0`,
primary: tw`bg-primary text-neutral-0`,
}[
this.variant
]} inline-flex items-center justify-center rounded-sm px-2 align-[1px] text-xs"
>
<slot></slot>
</span>
`;
}
}
2 changes: 1 addition & 1 deletion frontend/src/components/ui/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class Button extends TailwindElement {
type=${this.type === "submit" ? "submit" : "button"}
class=${[
tw`flex h-6 cursor-pointer items-center justify-center gap-2 rounded-sm text-center font-medium transition-all disabled:cursor-not-allowed disabled:text-neutral-300`,
this.icon ? tw`min-h-6 min-w-6 px-1` : tw`h-6 px-2`,
this.icon ? tw`min-h-8 min-w-8 px-1` : tw`h-6 px-2`,
this.raised ? tw`shadow-sm` : "",
{
primary: tw`bg-blue-50 text-blue-600 shadow-blue-800/20 hover:bg-blue-100`,
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/components/ui/card.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { html } from "lit";
import { customElement } from "lit/decorators.js";

import { TailwindElement } from "@/classes/TailwindElement";

@customElement("btrix-card")
export class Card extends TailwindElement {
render() {
return html`
<section class="flex h-full flex-col rounded border p-4">
<h2 class="mb-3 border-b pb-3 text-base font-semibold leading-none">
<slot name="title"></slot>
</h2>
<div class="flex-1">
<slot></slot>
</div>
<slot name="footer"></slot>
</section>
`;
}
}
2 changes: 1 addition & 1 deletion frontend/src/components/ui/desc-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class DescListItem extends LitElement {
render() {
return html`<div class="item">
<div class="content">
<dt>${this.label}</dt>
<dt>${this.label}<slot name="label"></slot></dt>
<dd><slot></slot></dd>
</div>
</div>`;
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import "./badge";
import "./navigation";

import("./button");
import("./card");
import("./code");
import("./combobox");
import("./config-details");
Expand All @@ -27,6 +28,7 @@ import("./relative-duration");
import("./search-combobox");
import("./section-heading");
import("./select-crawler");
import("./tab-group");
import("./tab-list");
import("./table");
import("./tag-input");
Expand Down
17 changes: 14 additions & 3 deletions frontend/src/components/ui/navigation/navigation-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ import { TailwindElement } from "@/classes/TailwindElement";
import { tw } from "@/utils/tailwind";

/**
* Custom styled button
* Custom styled button with active state
*
* Usage example:
* ```ts
* <btrix-navigation-button>Click me</btrix-navigation-button>
* ```
*
* @exportparts button
*/
@customElement("btrix-navigation-button")
export class Button extends TailwindElement {
export class NavigationButton extends TailwindElement {
@property({ type: Boolean })
active = false;

Expand All @@ -37,14 +39,21 @@ export class Button extends TailwindElement {
icon = false;

@property({ type: String, reflect: true })
role: ARIAMixin["role"] = "tab";
role: ARIAMixin["role"] = null;

@property({ type: String })
size: "small" | "medium" | "large" = "medium";

@property({ type: String })
align: "left" | "center" | "right" = "left";

connectedCallback(): void {
if (!this.role && !this.href) {
this.role = "tab";
}
super.connectedCallback();
}

protected willUpdate(changedProperties: PropertyValueMap<this>) {
if (changedProperties.has("active")) {
this.ariaSelected = this.active ? "true" : null;
Expand All @@ -66,6 +75,7 @@ export class Button extends TailwindElement {
const tag = this.href ? literal`a` : literal`button`;
return html`<${tag}
type=${this.type === "submit" ? "submit" : "button"}
part="button"
class=${[
tw`flex w-full cursor-pointer items-center gap-2 rounded font-medium leading-[16px] outline-primary-600 transition hover:transition-none focus-visible:outline focus-visible:outline-3 focus-visible:outline-offset-1 disabled:cursor-not-allowed disabled:bg-transparent disabled:opacity-50`,
this.icon ? tw`min-h-6 min-w-6` : tw``,
Expand All @@ -89,6 +99,7 @@ export class Button extends TailwindElement {
href=${ifDefined(this.href)}
aria-label=${ifDefined(this.label)}
@click=${this.handleClick}
>
<slot></slot>
</${tag}>`;
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/ui/tab-group/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import "./tab";
import "./tab-group";
import "./tab-panel";

0 comments on commit 83c9203

Please sign in to comment.