Skip to content

Commit

Permalink
Add CertificatesListLoading
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksandr-slobodian committed Jun 26, 2024
1 parent ea641f6 commit 780df70
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 80 deletions.
6 changes: 6 additions & 0 deletions src/components/certificates-list/CertificatesList.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@ export const Default: Story = {
})),
},
};

export const Empty: Story = {
args: {
certificates: [],
},
};
195 changes: 115 additions & 80 deletions src/components/certificates-list/CertificatesList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import React, { ComponentProps, useState } from "react";
import { useTranslation } from "react-i18next";
import clsx from "clsx";
import { Button, IconButton, Typography } from "@peculiar/react-components";
import {
Button,
IconButton,
Skeleton,
Typography,
} from "@peculiar/react-components";
import {
Table,
TableBody,
Expand Down Expand Up @@ -42,6 +47,7 @@ interface CertificatesListProps {
onViewDetails: (certificate: CertificateProps) => void;
className?: ComponentProps<"table">["className"];
highlightedText?: string;
loading?: boolean;
}

export const CertificatesList: React.FunctionComponent<
Expand All @@ -53,6 +59,7 @@ export const CertificatesList: React.FunctionComponent<
currentSortName,
currentSortDir,
highlightedText,
loading,
onSort,
onViewDetails,
onDelete,
Expand All @@ -62,7 +69,7 @@ export const CertificatesList: React.FunctionComponent<

const [currentRow, setCurrentRow] = useState<string>();

if (!certificates?.length) {
if (!certificates?.length && !loading) {
return (
<div className={styles.empty_list}>
<div className={styles.empty_list_icon}>
Expand All @@ -85,6 +92,7 @@ export const CertificatesList: React.FunctionComponent<
currentSortName === name && currentSortDir === "asc" ? "desc" : "asc"
)
}
disabled={loading}
>
{t(title)}
</SortButton>
Expand All @@ -111,87 +119,114 @@ export const CertificatesList: React.FunctionComponent<
</TableRow>
</TableHeader>
<TableBody>
{certificates.map((certificate) => {
const { id, providerID, serialNumber, type, label, notAfter, raw } =
certificate;
return (
<TableRow
tabIndex={0}
key={id}
onClick={() => onViewDetails(certificate)}
onFocus={() => setCurrentRow(id)}
onBlur={() => setCurrentRow(undefined)}
onKeyDown={(event) =>
["Space", "Enter"].includes(event.code) &&
onViewDetails(certificate)
}
onMouseOver={() => currentRow && setCurrentRow(undefined)}
className={clsx({
["current"]: currentRow === id,
})}
>
<TableCell>
<CertificateTypeLabel type={type} />
</TableCell>
{/* // TODO: not sure about label as name */}
<TableCell>
<CertificateName highlight={highlightedText} name={label} />
</TableCell>
<TableCell>
<CertificateSerialNumber value={serialNumber} />
</TableCell>
<TableCell>
<Date date={notAfter} />
<div
className={styles.list_table_actions}
onClick={(event) => event.stopPropagation()}
onKeyDown={(event) => event.stopPropagation()}
>
<Button
tabIndex={0}
className={styles.view_details_button}
variant="outlined"
size="small"
onClick={() => onViewDetails(certificate)}
>
{t("certificates.list.action.view-details")}
</Button>
<CopyIconButton
value={
raw.byteLength ? certificateRawToPem(raw, type) : ""
}
className={styles.action_icon_button}
/>
<IconButton
tabIndex={0}
title={t("certificates.list.action.download")}
onClick={() =>
raw.byteLength &&
downloadCertificate(label as string, raw, type)
}
size="small"
className={styles.action_icon_button}
>
<DownloadIcon />
</IconButton>
<IconButton
tabIndex={0}
title={t("certificates.list.action.delete")}
onClick={() =>
onDelete(id as string, providerID, label as string)
}
size="small"
className={styles.action_icon_button}
{loading ? (
<CertificatesListLoading />
) : (
certificates.map((certificate) => {
const {
id,
providerID,
serialNumber,
type,
label,
notAfter,
raw,
} = certificate;
return (
<TableRow
tabIndex={0}
key={id}
onClick={() => onViewDetails(certificate)}
onFocus={() => setCurrentRow(id)}
onBlur={() => setCurrentRow(undefined)}
onKeyDown={(event) =>
["Space", "Enter"].includes(event.code) &&
onViewDetails(certificate)
}
onMouseOver={() => currentRow && setCurrentRow(undefined)}
className={clsx({
["current"]: currentRow === id,
})}
>
<TableCell>
<CertificateTypeLabel type={type} />
</TableCell>
{/* // TODO: not sure about label as name */}
<TableCell>
<CertificateName highlight={highlightedText} name={label} />
</TableCell>
<TableCell>
<CertificateSerialNumber value={serialNumber} />
</TableCell>
<TableCell>
<Date date={notAfter} />
<div
className={styles.list_table_actions}
onClick={(event) => event.stopPropagation()}
onKeyDown={(event) => event.stopPropagation()}
>
<DeleteIcon />
</IconButton>
</div>
</TableCell>
</TableRow>
);
})}
<Button
tabIndex={0}
className={styles.view_details_button}
variant="outlined"
size="small"
onClick={() => onViewDetails(certificate)}
>
{t("certificates.list.action.view-details")}
</Button>
<CopyIconButton
value={
raw.byteLength ? certificateRawToPem(raw, type) : ""
}
className={styles.action_icon_button}
/>
<IconButton
tabIndex={0}
title={t("certificates.list.action.download")}
onClick={() =>
raw.byteLength &&
downloadCertificate(label as string, raw, type)
}
size="small"
className={styles.action_icon_button}
>
<DownloadIcon />
</IconButton>
<IconButton
tabIndex={0}
title={t("certificates.list.action.delete")}
onClick={() =>
onDelete(id as string, providerID, label as string)
}
size="small"
className={styles.action_icon_button}
>
<DeleteIcon />
</IconButton>
</div>
</TableCell>
</TableRow>
);
})
)}
</TableBody>
</Table>
</div>
);
};

function CertificatesListLoading() {
return [...Array(12).keys()].map((index) => (
<TableRow className={styles.skeleton_tr} key={`skel-row-${index}`}>
{[...Array(4).keys()].map((index) => (
<TableCell className={styles.skeleton_td}>
<Skeleton
key={`skel-td-${index}`}
className={styles.skeleton_td_item}
height={31}
/>
</TableCell>
))}
</TableRow>
));
}
37 changes: 37 additions & 0 deletions src/components/certificates-list/styles/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,40 @@
}
}
}

.skeleton_tr {
.skeleton_td {
border-bottom: none;
cursor: default;
&::after,
&::before {
display: none;
}
}
&:nth-child(odd) {
.skeleton_td:nth-child(1) .skeleton_td_item {
width: 46%;
}
.skeleton_td:nth-child(2) .skeleton_td_item {
width: 58%;
}
}
&:nth-child(even) {
.skeleton_td:nth-child(1) .skeleton_td_item {
width: 65%;
}
.skeleton_td:nth-child(2) .skeleton_td_item {
width: 46%;
}
}
.skeleton_td:nth-child(3) .skeleton_td_item {
width: 73%;
}
.skeleton_td:nth-child(4) {
text-align: right;
.skeleton_td_item {
width: 81%;
display: inline-block;
}
}
}

0 comments on commit 780df70

Please sign in to comment.