forked from hyperledger-cacti/cacti
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ledger-browser): rewrite fabric application
- Rewrite fabric app using MUI components and new database schema. - Improve `UITableListing` to support clickable tables. - The new app supports the following views: - Dashboard: Shows summary of blocks and transaction recorded in database. - Block list: Full list of blocks - Transaction list: Full list of transactions - Transaction details: Page that shows full transaction information, transaction actions (method calls) and endorsements. Depends on hyperledger-cacti#3308 Depends on hyperledger-cacti#3279 Signed-off-by: Michal Bajer <[email protected]>
- Loading branch information
Showing
38 changed files
with
1,379 additions
and
661 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 1 addition & 21 deletions
22
packages/cacti-ledger-browser/src/main/typescript/apps/eth/pages/Dashboard/Dashboard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
...s/cacti-ledger-browser/src/main/typescript/apps/fabric/components/BlockList/BlockList.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import * as React from "react"; | ||
import { fabricAllBlocksQuery } from "../../queries"; | ||
import { blockColumnsConfig } from "./blockColumnsConfig"; | ||
import type { UITableListingPaginationActionProps } from "../../../../components/ui/UITableListing/UITableListingPaginationAction"; | ||
import UITableListing from "../../../../components/ui/UITableListing/UITableListing"; | ||
|
||
/** | ||
* List of columns that can be rendered in a block list table | ||
*/ | ||
export type BlockListColumn = keyof typeof blockColumnsConfig; | ||
|
||
/** | ||
* BlockList properties. | ||
*/ | ||
export interface BlockListProps { | ||
footerComponent: React.ComponentType<UITableListingPaginationActionProps>; | ||
columns: BlockListColumn[]; | ||
rowsPerPage: number; | ||
tableSize?: "small" | "medium"; | ||
} | ||
|
||
/** | ||
* BlockList - Show table with fabric blocks. | ||
* | ||
* @param footerComponent component will be rendered in a footer of a transaction list table. | ||
* @param columns list of columns to be rendered. | ||
* @param rowsPerPage how many rows to show per page. | ||
*/ | ||
const BlockList: React.FC<BlockListProps> = ({ | ||
footerComponent, | ||
columns, | ||
rowsPerPage, | ||
tableSize, | ||
}) => { | ||
return ( | ||
<UITableListing | ||
queryFunction={fabricAllBlocksQuery} | ||
label="block" | ||
columnConfig={blockColumnsConfig} | ||
footerComponent={footerComponent} | ||
columns={columns} | ||
rowsPerPage={rowsPerPage} | ||
tableSize={tableSize} | ||
/> | ||
); | ||
}; | ||
|
||
export default BlockList; |
20 changes: 20 additions & 0 deletions
20
...ledger-browser/src/main/typescript/apps/fabric/components/BlockList/blockColumnsConfig.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* Component user can select columns to be rendered in a table list. | ||
* Possible fields and their configurations are defined in here. | ||
*/ | ||
export const blockColumnsConfig = { | ||
number: { | ||
name: "Number", | ||
field: "number", | ||
}, | ||
hash: { | ||
name: "Hash", | ||
field: "hash", | ||
isLongString: true, | ||
isUnique: true, | ||
}, | ||
txCount: { | ||
name: "Transaction Count", | ||
field: "transaction_count", | ||
}, | ||
}; |
169 changes: 169 additions & 0 deletions
169
...r/src/main/typescript/apps/fabric/components/CertificateDetails/CertificateDetailsBox.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import Box from "@mui/material/Box"; | ||
import Typography from "@mui/material/Typography"; | ||
import TextField from "@mui/material/TextField"; | ||
import { styled } from "@mui/material/styles"; | ||
|
||
import { FabricCertificate } from "../../fabric-supabase-types"; | ||
import StackedRowItems from "../ui/StackedRowItems"; | ||
|
||
const ListHeaderTypography = styled(Typography)(({ theme }) => ({ | ||
color: theme.palette.secondary.main, | ||
fontWeight: "bold", | ||
})); | ||
|
||
const TextFieldDisabledBlackFont = styled(TextField)(() => ({ | ||
"& .MuiInputBase-input.Mui-disabled": { | ||
WebkitTextFillColor: "black", | ||
}, | ||
})); | ||
|
||
function formatDateString(date: string | undefined) { | ||
if (date) { | ||
return new Date(date).toLocaleDateString(); | ||
} | ||
|
||
return "-"; | ||
} | ||
|
||
function formatCertificateAttr(attr: string | null | undefined) { | ||
if (attr) { | ||
return attr; | ||
} | ||
|
||
return "-"; | ||
} | ||
|
||
function formatCertificateSubject( | ||
certificate: FabricCertificate, | ||
fieldPrefix: "issuer" | "subject", | ||
) { | ||
return ( | ||
<ul style={{ margin: 0 }}> | ||
<li> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Common Name:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(certificate[`${fieldPrefix}_common_name`])} | ||
</Typography> | ||
</StackedRowItems> | ||
</li> | ||
<li> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Organization:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(certificate[`${fieldPrefix}_org`])} | ||
</Typography> | ||
</StackedRowItems> | ||
</li> | ||
<li> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Organization Unit:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(certificate[`${fieldPrefix}_org_unit`])} | ||
</Typography> | ||
</StackedRowItems> | ||
</li> | ||
<li> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Country:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(certificate[`${fieldPrefix}_country`])} | ||
</Typography> | ||
</StackedRowItems> | ||
</li> | ||
<li> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Locality:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(certificate[`${fieldPrefix}_locality`])} | ||
</Typography> | ||
</StackedRowItems> | ||
</li> | ||
<li> | ||
<StackedRowItems> | ||
<ListHeaderTypography>State:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(certificate[`${fieldPrefix}_state`])} | ||
</Typography> | ||
</StackedRowItems> | ||
</li> | ||
</ul> | ||
); | ||
} | ||
|
||
export interface CertificateDetailsBoxProps { | ||
certificate: FabricCertificate | undefined; | ||
} | ||
|
||
/** | ||
* Detailed information of provided fabric certificate. | ||
* @param certificate: Fabric certificate from the DB. | ||
*/ | ||
export default function CertificateDetailsBox({ | ||
certificate, | ||
}: CertificateDetailsBoxProps) { | ||
return ( | ||
<Box> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Serial Number:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(certificate?.serial_number)} | ||
</Typography> | ||
</StackedRowItems> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Valid From:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(formatDateString(certificate?.valid_from))} | ||
</Typography> | ||
</StackedRowItems> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Valid To:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(formatDateString(certificate?.valid_to))} | ||
</Typography> | ||
</StackedRowItems> | ||
<StackedRowItems> | ||
<ListHeaderTypography>Alt Name:</ListHeaderTypography> | ||
<Typography> | ||
{formatCertificateAttr(certificate?.subject_alt_name)} | ||
</Typography> | ||
</StackedRowItems> | ||
|
||
{certificate ? ( | ||
<> | ||
<ListHeaderTypography marginTop={2}>Subject:</ListHeaderTypography> | ||
{formatCertificateSubject(certificate, "subject")} | ||
</> | ||
) : ( | ||
<StackedRowItems> | ||
<ListHeaderTypography>Subject:</ListHeaderTypography> | ||
<Typography>-</Typography> | ||
</StackedRowItems> | ||
)} | ||
|
||
{certificate ? ( | ||
<> | ||
<ListHeaderTypography marginTop={2}>Issuer:</ListHeaderTypography> | ||
{formatCertificateSubject(certificate, "issuer")} | ||
</> | ||
) : ( | ||
<StackedRowItems> | ||
<ListHeaderTypography>Issuer:</ListHeaderTypography> | ||
<Typography>-</Typography> | ||
</StackedRowItems> | ||
)} | ||
|
||
<ListHeaderTypography marginTop={2}> | ||
Certificate (PEM): | ||
</ListHeaderTypography> | ||
<TextFieldDisabledBlackFont | ||
disabled | ||
fullWidth | ||
rows={5} | ||
multiline | ||
size="small" | ||
value={certificate?.pem ?? ""} | ||
/> | ||
</Box> | ||
); | ||
} |
73 changes: 73 additions & 0 deletions
73
...src/main/typescript/apps/fabric/components/CertificateDetails/CertificateDialogButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import * as React from "react"; | ||
import { useQuery } from "@tanstack/react-query"; | ||
import Button from "@mui/material/Button"; | ||
import Dialog from "@mui/material/Dialog"; | ||
import DialogTitle from "@mui/material/DialogTitle"; | ||
import DialogContent from "@mui/material/DialogContent"; | ||
|
||
import CertificateDetailsBox from "./CertificateDetailsBox"; | ||
import { fabricCertificate } from "../../queries"; | ||
import { useNotification } from "../../../../common/context/NotificationContext"; | ||
|
||
export interface CertificateDialogButtonProps { | ||
certId: string | null; | ||
} | ||
|
||
/** | ||
* Show a button with certificate common name and organization, that will | ||
* open a dialog with full certificate details on click. | ||
* | ||
* @warn Fetches the certificate from DB when mounted. | ||
* | ||
* @param certId ID of the certificate in database. | ||
*/ | ||
export default function CertificateDialogButton({ | ||
certId, | ||
}: CertificateDialogButtonProps) { | ||
const { showNotification } = useNotification(); | ||
const [openDialog, setOpenDialog] = React.useState(false); | ||
|
||
const { isError, data, error } = useQuery({ | ||
...fabricCertificate(certId ?? ""), | ||
enabled: !!certId, | ||
}); | ||
|
||
React.useEffect(() => { | ||
isError && | ||
showNotification( | ||
`Could not fetch creator certificate: ${error}`, | ||
"error", | ||
); | ||
}, [isError]); | ||
|
||
let creatorName = "unknownName"; | ||
if (data?.subject_common_name) { | ||
creatorName = data.subject_common_name; | ||
} | ||
|
||
let creatorOrg = "unknownOrg"; | ||
if (data?.subject_org) { | ||
creatorOrg = data.subject_org; | ||
} else if (data?.subject_org_unit) { | ||
creatorOrg = data.subject_org_unit; | ||
} | ||
|
||
return ( | ||
<> | ||
<Button | ||
disabled={!data} | ||
style={{ textTransform: "none" }} | ||
variant="outlined" | ||
onClick={() => setOpenDialog(true)} | ||
> | ||
{creatorName}@{creatorOrg} | ||
</Button> | ||
<Dialog onClose={() => setOpenDialog(false)} open={openDialog}> | ||
<DialogTitle color="primary">Certificate Details</DialogTitle> | ||
<DialogContent> | ||
<CertificateDetailsBox certificate={data} /> | ||
</DialogContent> | ||
</Dialog> | ||
</> | ||
); | ||
} |
18 changes: 0 additions & 18 deletions
18
...ti-ledger-browser/src/main/typescript/apps/fabric/components/TokenHeader/TokenAccount.tsx
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.