Skip to content

Commit

Permalink
Merge pull request #57 from DenizUgur/coverage_page
Browse files Browse the repository at this point in the history
Cleaner coverage page header
  • Loading branch information
cconcolato authored Aug 31, 2023
2 parents ef7a703 + 7452bfd commit 2aefa1e
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 129 deletions.
2 changes: 1 addition & 1 deletion conformance-search/src/components/SpecsCovered.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function SpecsCovered({
key={info.ISO}
className={clsx(
"group flex items-center justify-between gap-2 truncate px-3 py-2 font-light hover:bg-gray-100",
compact && "!py-1 text-sm font-normal"
compact && "text-sm font-normal"
)}
href={info.link}
rel="noreferrer"
Expand Down
25 changes: 11 additions & 14 deletions conformance-search/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,23 @@ code.basic {
@apply rounded bg-gray-300 px-1 font-mono text-black;
}

table {
@apply border-1 border-black bg-neutral-100;
progress[value] {
/* Reset the default appearance */
appearance: none;
}

thead {
@apply bg-black text-white;
progress[value]::-webkit-progress-bar {
@apply bg-gray-300;
}

tbody th {
@apply border-b-2 border-black px-2 text-center;
progress[value].low::-webkit-progress-value {
@apply bg-red-600;
}

tbody tr {
@apply border-b-1 border-black bg-white text-center last:border-0;
progress[value].med::-webkit-progress-value {
@apply bg-yellow-600;
}

tbody td {
@apply px-2;
}

input[type="number"]::-webkit-inner-spin-button {
opacity: 1;
progress[value].high::-webkit-progress-value {
@apply bg-green-600;
}
223 changes: 121 additions & 102 deletions conformance-search/src/pages/CoveragePage/CoverageHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,76 @@
import { Coverage } from "@/types/json";
import SpecsCovered from "@/components/SpecsCovered";
import clsx from "clsx";
import { Button, Modal, Tooltip } from "@mui/material";
import { AiOutlineInfoCircle } from "react-icons/ai";
import { useState } from "react";
import { MdClose } from "react-icons/md";

function StatisticDisplay({
label,
alt,
info,
value,
total,
excluded = 0
}: {
label: string;
alt: string;
info?: string;
value: number;
total: number;
excluded?: number;
}) {
const [open, setOpen] = useState(false);
const adjustedTotal = total - excluded;
let level = "low";
if (value / total >= 0.75) {
level = "high";
} else if (value / total >= 0.25) {
level = "med";
}

return (
<div className="flex grow flex-col gap-1 lg:grow-0">
<div className="flex items-center gap-2 font-bold">
<span>{label}</span>
{info && (
<Tooltip
arrow
onClose={() => setOpen(false)}
onOpen={() => setOpen(true)}
open={open}
placement="top"
title={info}
>
<button onClick={() => setOpen(true)} type="submit">
<AiOutlineInfoCircle />
</button>
</Tooltip>
)}
</div>
<div className="relative flex min-w-[180px] items-center gap-4 lg:min-w-[250px]">
<progress className={clsx("h-5 w-full", level)} max={adjustedTotal} value={value} />
<span className="absolute right-1 font-semibold">
{((value / adjustedTotal) * 100).toFixed(0)}%
</span>
</div>
<span className="text-xs font-light">
{value} of {adjustedTotal} {alt} {alt.includes("file") ? "published" : "covered"}
</span>
{excluded > 0 && (
<span className="text-xs font-light">
{excluded} {alt} are <u>under consideration</u> (excluded)
</span>
)}
</div>
);
}

StatisticDisplay.defaultProps = {
excluded: 0,
info: ""
};

export default function CoverageHeader({
coverageStats,
Expand All @@ -10,6 +81,7 @@ export default function CoverageHeader({
processedCoverageStats: Coverage;
depth: number;
}) {
const [open, setOpen] = useState(false);
const download = () => {
const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(
JSON.stringify(coverageStats)
Expand All @@ -21,111 +93,58 @@ export default function CoverageHeader({
downloadAnchorNode.remove();
};

const sumValues = (obj: Record<string, string[]>) => {
return Object.values(obj).reduce((acc, val) => acc + val.length, 0);
};

return (
<div className="flex w-full flex-col flex-wrap items-start gap-4 border-b-2 border-black pb-6 text-sm xs:text-base md:flex-row">
<table className="max-md:w-full">
<thead>
<tr>
<th colSpan={2}>File Statistics</th>
</tr>
</thead>
<tbody>
<tr>
<th>Count</th>
<th>Attribute</th>
</tr>
<tr>
<td>{coverageStats.files.count}</td>
<td>Files submitted</td>
</tr>
<tr>
<td>{coverageStats.files.published_count}</td>
<td>Published</td>
</tr>
<tr>
<td>{coverageStats.files.under_consideration_count}</td>
<td>Under consideration</td>
</tr>
</tbody>
</table>
<table className="max-md:w-full">
<thead>
<tr>
<th colSpan={2}>Boxes</th>
</tr>
</thead>
<tbody>
<tr>
<th>Count</th>
<th>Attribute</th>
</tr>
<tr>
<td>{processedCoverageStats.path_file_map.count}</td>
<td>All possible box locations</td>
</tr>
<tr>
<td>
{(
(processedCoverageStats.lists.boxes.covered.length /
(processedCoverageStats.lists.boxes.not_covered.length +
processedCoverageStats.lists.boxes.covered.length)) *
100
).toFixed(2)}
%
</td>
<td>Coverage percentage (depth={depth})</td>
</tr>
<tr>
<td>{processedCoverageStats.path_file_map.non_empty}</td>
<td>Unique box locations in files</td>
</tr>
<tr>
<td>{processedCoverageStats.path_file_map.published.count}</td>
<td>Published</td>
</tr>
<tr>
<td>{processedCoverageStats.path_file_map.under_consideration.count}</td>
<td>Under consideration</td>
</tr>
</tbody>
</table>
<table className="max-md:w-full">
<thead>
<tr>
<th colSpan={2}>User Defined Features</th>
</tr>
</thead>
<tbody>
<tr>
<th>Count</th>
<th>Attribute</th>
</tr>
<tr>
<td>{processedCoverageStats.feature_file_map.count}</td>
<td>Total number of features</td>
</tr>
<tr>
<td>{processedCoverageStats.feature_file_map.published_features}</td>
<td>Published</td>
</tr>
<tr>
<td>
{processedCoverageStats.feature_file_map.under_consideration_features}
</td>
<td>Under consideration</td>
</tr>
</tbody>
</table>
<div className="flex grow flex-col items-center max-md:w-full md:items-start">
<SpecsCovered compact />
<div className="flex w-full flex-col gap-4">
<div className="flex flex-wrap items-stretch gap-4">
<StatisticDisplay
alt="files"
label="Conformance Files"
total={processedCoverageStats.files.count}
value={processedCoverageStats.files.published_count}
/>
<StatisticDisplay
alt="features"
excluded={processedCoverageStats.lists.features.under_consideration.length}
label="Features"
total={sumValues(processedCoverageStats.lists.features)}
value={processedCoverageStats.lists.features.covered.length}
/>
<StatisticDisplay
alt="box paths"
excluded={processedCoverageStats.lists.boxes.under_consideration.length}
info={`This calculation is based on selected depth value of ${depth}`}
label="Box Paths"
total={sumValues(processedCoverageStats.lists.boxes)}
value={processedCoverageStats.lists.boxes.covered.length}
/>
</div>
<button
className="rounded-md border-1 bg-white px-3 py-2 shadow-md hover:shadow-sm"
onClick={download}
type="button"
<Button onClick={() => setOpen(true)} variant="outlined">
More information
</Button>
<Modal
className="flex items-center justify-center"
onClose={() => setOpen(false)}
open={open}
>
Download Coverage Report
</button>
<div className="flex flex-col items-stretch gap-6 rounded-lg bg-white p-6">
<div className="flex items-center justify-between">
<h1 className="text-xl font-bold">More Information</h1>
<button onClick={() => setOpen(false)} type="button">
<MdClose className="text-3xl font-thin" />
</button>
</div>
<div className="flex grow flex-col items-center max-md:w-full md:items-start">
<SpecsCovered compact />
</div>
<Button onClick={download} variant="outlined">
Download Coverage Report
</Button>
</div>
</Modal>
</div>
);
}
21 changes: 9 additions & 12 deletions conformance-search/src/pages/CoveragePage/CoveragePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,21 +199,19 @@ export default function CoveragePage() {
<>
<NavigationBar />
<div className="mx-auto flex min-h-0 w-full max-w-7xl flex-[1] flex-col items-start gap-3 p-2 xs:gap-4 xs:p-6">
<div className="flex w-full flex-col gap-4">
<CoverageHeader
coverageStats={coverageStats}
depth={depth}
processedCoverageStats={processedCoverageStats}
/>
</div>
<CoverageHeader
coverageStats={coverageStats}
depth={depth}
processedCoverageStats={processedCoverageStats}
/>
<div className="flex w-full flex-col items-start gap-2">
<input
className="w-full rounded-md border-1 border-black px-3 py-2"
className="w-full rounded border-1 px-3 py-2 shadow-md"
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setSearch((e.target as HTMLInputElement).value)
}
placeholder="Start by typing a feature or box fourcc..."
type="text"
type="search"
value={search}
/>
<span className="ml-1 text-xs text-gray-600">
Expand All @@ -222,11 +220,10 @@ export default function CoveragePage() {
for features/boxes ending in <code className="basic">avcC</code>.
</span>
<div className="flex w-full flex-row items-center gap-4">
<span className="text-2xl font-bold">Depth Setting</span>
<span className="whitespace-nowrap text-xl font-bold">Depth Setting</span>
<Slider
className="basis-1/2 lg:basis-1/3"
className="mr-1 grow lg:grow-0 lg:basis-1/3"
defaultValue={3}
marks
max={maxDepth}
min={1}
onChange={(_, value) => setDepth(value as number)}
Expand Down

0 comments on commit 2aefa1e

Please sign in to comment.