Skip to content

Commit

Permalink
fix: refactor CanaryPopup-related files
Browse files Browse the repository at this point in the history
  • Loading branch information
johnflank committed Nov 29, 2021
1 parent 48c8842 commit 90eca83
Show file tree
Hide file tree
Showing 9 changed files with 359 additions and 346 deletions.
151 changes: 151 additions & 0 deletions src/components/Canary/CanaryPopup/CheckDetails.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import React from "react";
import { usePrevious } from "../../../utils/hooks";
import { Badge } from "../../Badge";
import { toFormattedDuration } from "../renderers";
import { AccordionBox } from "../../AccordionBox";
import {
capitalizeFirstLetter,
toFixedIfNecessary
} from "../../../utils/common";
import styles from "../index.module.css";
import { PopupTabs } from "./tabs";
import { CheckStat } from "./CheckStat";
import { getUptimePercentage } from "./utils";
import { StatusHistory } from "./StatusHistory";
import { DetailField } from "./DetailField";

export function CheckDetails({ check, ...rest }) {
const prevCheck = usePrevious(check);
const validCheck = check || prevCheck;

const [val, unit] = toFormattedDuration(validCheck?.latency?.rolling1h);
const latencyValue = validCheck?.latency?.rolling1h ? `${val}${unit}` : "-";
const uptimeValue = toFixedIfNecessary(getUptimePercentage(validCheck), 2);
const validUptime =
!Number.isNaN(validCheck?.uptime?.passed) &&
!Number.isNaN(validCheck?.uptime?.failed);
const severityValue = validCheck?.severity || "-";
const statusHistoryList = validCheck?.checkStatuses;

const details = {
Name:
validCheck?.name || validCheck?.canaryName || validCheck?.endpoint || "-",
Type: validCheck?.type || "-",
Labels: (
<>
{validCheck?.labels &&
Object.entries(validCheck?.labels).map((entry) => {
const key = entry[0];
return <Badge className="mr-1 mb-1" key={key} text={key} />;
})}
</>
),
Owner: validCheck?.owner || "-",
Interval: validCheck?.interval || "-",
Location: validCheck?.location || "-",
Schedule: validCheck?.schedule || "-"
};

return (
<div {...rest}>
{/* stats section */}
<div className="flex flex-row flex-wrap mb-2">
<CheckStat
containerClass="w-52 mb-4"
title="Uptime"
value={
!Number.isNaN(uptimeValue)
? `${toFixedIfNecessary(uptimeValue, 2)}%`
: "-"
}
append={
validUptime &&
!Number.isNaN(uptimeValue) && (
<div className="flex flex-col justify-center mx-2 mt-0.5">
<span className="text-xs text-green-700 ">
{validCheck?.uptime?.passed} passed
</span>
<span className="text-xs text-red-600">
{validCheck?.uptime?.failed} failed
</span>
</div>
)
}
/>
<CheckStat
containerClass="w-52 mb-4"
title="Latency"
value={latencyValue}
/>
<CheckStat
containerClass="w-52 mb-4"
title="Severity"
value={capitalizeFirstLetter(severityValue)}
/>
</div>
{/* chart section */}
<div className="mb-6">
<div className="flex justify-between items-center mb-2">
<span className="text-lg font-medium">Health overview</span>
<span className="text-sm font-medium">(time dropdown)</span>
</div>
<div className="bg-gray-100 w-full h-52" />
</div>
<PopupTabs
style={{
display: "flex",
flexDirection: "column",
overflowY: "hidden"
}}
contentStyle={{
marginTop: "-1px",
display: "flex",
flexDirection: "column",
overflowY: "hidden"
}}
tabs={{
statusHistory: {
label: "Status history",
content: (
<div
key="status-history"
className={`border border-b-0 border-gray-300 overflow-hidden overflow-y-auto relative -mb-px ${styles.appleScrollbar}`}
>
{statusHistoryList && statusHistoryList.length > 0 ? (
<StatusHistory check={validCheck} sticky />
) : (
<div className="h-64 flex items-center justify-center text-gray-400 text-md">
No status history available
</div>
)}
</div>
),
class: "flex flex-col overflow-y-hidden border-b border-gray-300"
},
checkDetails: {
label: "Check details",
content: (
<div key="check-details" className="px-6 py-6">
<AccordionBox
content={
<div className="flex flex-row flex-wrap">
{Object.entries(details).map(([label, value]) => (
<DetailField
key={label}
className="w-1/2 mb-3 whitespace-nowrap"
label={label}
value={value}
/>
))}
</div>
}
/>
</div>
),
class: `flex flex-col overflow-y-auto border border-gray-300 ${styles.appleScrollbar}`
}
}}
/>
</div>
);
}
20 changes: 20 additions & 0 deletions src/components/Canary/CanaryPopup/CheckStat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

export function CheckStat({
title,
value,
append,
containerClass,
className,
...rest
}) {
return (
<div className={`flex flex-col ${containerClass} ${className}`} {...rest}>
<div className="text-sm font-medium text-gray-500">{title}</div>
<div className="flex">
<span className="text-4xl font-bold">{value}</span>
{append}
</div>
</div>
);
}
52 changes: 52 additions & 0 deletions src/components/Canary/CanaryPopup/CheckTitle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from "react";
import { usePrevious } from "../../../utils/hooks";
import { Badge } from "../../Badge";
import { Icon } from "../../Icon";

export function CheckTitle({ check, className, ...rest }) {
const prevCheck = usePrevious(check);
const validCheck = check || prevCheck;

return (
<div className={`flex flex-row ${className}`} {...rest}>
<div className="w-14 flex-shrink-0 pr-3">
<Icon
name={validCheck?.icon || validCheck?.type}
className="w-full h-12"
size="2xl"
/>
</div>
<div className="overflow-hidden mr-10">
<div className="flex flex-row items-center">
<span
title={validCheck?.name}
className="text-gray-800 text-2xl font-semibold whitespace-nowrap overflow-ellipsis overflow-hidden pr-4"
>
{validCheck?.name}
</span>
<span
className="hidden sm:block "
title={`Namespace for ${validCheck?.name}`}
style={{ paddingTop: "1px" }}
>
<Badge text={validCheck?.namespace} />
</span>
</div>
{true && (
<div
title={`Endpoint for ${validCheck?.name}`}
className="text-sm text-gray-400 mt-0.5 overflow-x-hidden overflow-ellipsis break-all"
>
{validCheck?.endpoint}
</div>
)}
<span
className="block sm:hidden mt-2"
title={`Namespace for ${validCheck?.name}`}
>
<Badge text={validCheck?.namespace} />
</span>
</div>
</div>
);
}
14 changes: 14 additions & 0 deletions src/components/Canary/CanaryPopup/DetailField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";

export function DetailField({ label, value, className, ...rest }) {
return (
<div className={`flex flex-col flex-shrink-0 pr-6 ${className}`} {...rest}>
<div className="text-sm font-medium text-gray-500 break-all overflow-hidden overflow-ellipsis">
{label}
</div>
<div className="mt-1 text-sm text-gray-900 break-all overflow-hidden overflow-ellipsis">
{value}
</div>
</div>
);
}
44 changes: 44 additions & 0 deletions src/components/Canary/CanaryPopup/StatusHistory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from "react";
import { format } from "timeago.js";
import { CanaryStatus, Duration } from "../renderers";
import { isEmpty } from "../utils";
import { Table } from "../../Table";

export function StatusHistory({ check, sticky = "false" }) {
const statii = check
? check.checkStatuses != null
? check.checkStatuses
: []
: [];
const data = [];
statii.forEach((status) => {
data.push({
key: `${check.key}.${check.description}`,
age: format(`${status.time} UTC`),
message: (
<>
<CanaryStatus status={status} /> {status.message}{" "}
{!isEmpty(status.error) &&
status.error.split("\n").map((item) => (
<>
{item}
<br />
</>
))}
</>
),
duration: <Duration ms={status.duration} />
});
});

return (
check && (
<Table
id={`${check.key}-table`}
data={data}
columns={["Age", "Duration", "Message"]}
sticky={sticky}
/>
)
);
}
Loading

0 comments on commit 90eca83

Please sign in to comment.