Skip to content

Commit

Permalink
Merge pull request #1569 from input-output-hk/djo/1554/explorer/impro…
Browse files Browse the repository at this point in the history
…ve-ctx-ui

Explorer: Improve Cardano Transaction Certification & Certificate Chain Validation UI
  • Loading branch information
Alenar authored Mar 18, 2024
2 parents 22dbdf1 + e591c7e commit 3fe1481
Show file tree
Hide file tree
Showing 58 changed files with 2,601 additions and 465 deletions.
20 changes: 20 additions & 0 deletions mithril-explorer/.fantasticonrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/** @type {import("fantasticon").RunnerOptions} */
module.exports = {
inputDir: "./icons",
outputDir: "./public/fonts",
fontTypes: ["woff", "woff2"],
assetTypes: ["css"],
fontsUrl: "/explorer/fonts",
formatOptions: {},
name: "mithril-icons",
prefix: "mi",
templates: {
css: "./font.css.hbs",
},
pathOptions: {
css: "./src/app/mithril-icons.css",
},
codepoints: {
logo: 57344, // 0xe000 = start of unicode private use area
},
};
1 change: 1 addition & 0 deletions mithril-explorer/.prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
out
explorer
font.css.hbs
5 changes: 5 additions & 0 deletions mithril-explorer/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ dev: build
@echo "\033[1mServing dev build at: http://localhost:3000/explorer \033[0m"
npm run dev

icons-font:
npm run icons-font
npm exec -- prettier ./src/app/mithril-icons.css --write

test: package-lock.json
npm run test:ci

Expand Down Expand Up @@ -61,6 +65,7 @@ upgrade: clean install
@testing-library/react@latest \
eslint@latest \
eslint-config-next@latest \
fantasticon@latest \
jest@latest \
jest-environment-jsdom@latest \
next-router-mock@latest \
Expand Down
21 changes: 21 additions & 0 deletions mithril-explorer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,24 @@ make dev
```

Open [http://localhost:3000](http://localhost:3000/explorer) with your browser to see the result.

## Adding or updating an icon of the 'Mithril' font

In the `./icons` folder add or modify a svg.

If you add a new icon you need to reference and associate it with a codepoint in the `./fantasticonrc.js`
configuration file.
The codepoint must be part of the [unicode private use area](https://www.unicode.org/charts/PDF/UE000.pdf), as
such it must be an integer between 57344 and 63743 (hex: E000-F8FF).

Then rebuild the font:

```bash
make icons-font
```

You can then use the icon in the js, ie if your icon name is `shield`:

```jsx
<i className={`bi mi mi-shield`}></i>
```
6 changes: 3 additions & 3 deletions mithril-explorer/__tests__/AggregatorSetter.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import AggregatorSetter from "../src/components/AggregatorSetter";
import { initStore } from "./helpers";
import { Provider } from "react-redux";
import default_available_aggregators from "../src/aggregators-list";
import { settingsSlice } from "../src/store/settingsSlice";
import AggregatorSetter from "#/AggregatorSetter";
import default_available_aggregators from "@/aggregators-list";
import { settingsSlice } from "@/store/settingsSlice";

function renderAggregatorSetter(default_state = undefined) {
const store = initStore(default_state);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { fireEvent, render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import CardanoTransactionsFormInput from "../src/components/CardanoTransactionsFormInput";
import CardanoTransactionsFormInput from "#/CardanoTransactionsFormInput";

function setup() {
const utils = [render(<CardanoTransactionsFormInput />)];
Expand Down
13 changes: 9 additions & 4 deletions mithril-explorer/__tests__/PoolTicker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import { initStore } from "./helpers";
import { Provider } from "react-redux";
import { poolsSlice } from "../src/store/poolsSlice";
import PoolTicker from "../src/components/PoolTicker";
import { getCExplorerUrlForPool } from "../src/utils";
import { settingsSlice } from "../src/store/settingsSlice";
import PoolTicker from "#/PoolTicker";
import { settingsSlice } from "@/store/settingsSlice";
import { poolsSlice } from "@/store/poolsSlice";
import { getCExplorerUrl } from "@/utils";

function renderPoolTickerComponent(partyId, default_state = undefined) {
const store = initStore(default_state);
Expand All @@ -19,6 +19,11 @@ function renderPoolTickerComponent(partyId, default_state = undefined) {
];
}

function getCExplorerUrlForPool(network, partyId) {
const cExplorerUrl = getCExplorerUrl(network);
return cExplorerUrl ? `${cExplorerUrl}/pool/${partyId}` : undefined;
}

describe("PoolTicker", () => {
it("Pool ticker not on the three main network doesn't show link to cexplorer", () => {
const partyId = "pool1zmtm8yef33z2n7x4nn0kvv9xpzjuj7725p9y9m5t960g5qy51ua";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import TransactionCertificationBreadcrumb from "#/CertifyCardanoTransactionsModal/TransactionCertificationBreadcrumb";
import { validationSteps } from "#/CertifyCardanoTransactionsModal";

function setup(currentStep, isProofValid, isCertificateChainValid) {
const utils = [
render(
<TransactionCertificationBreadcrumb
currentStep={currentStep}
isProofValid={isProofValid}
isCertificateChainValid={isCertificateChainValid}
/>,
),
];

const tabs = new Map();
tabs.set(validationSteps.fetchingProof, screen.getByText(/Fetching Transactions Proof/i));
tabs.set(validationSteps.validatingProof, screen.getByText(/Verifying Transactions Proof/i));
tabs.set(
validationSteps.validatingCertificateChain,
screen.getByText(/Validating Certificate Chain/i),
);
tabs.set(validationSteps.done, screen.getByText(/Finish/i));

return {
tabs: tabs,
...utils,
};
}

const classForVariant = (variant) => `list-group-item-${variant}`;

describe("TransactionCertificationBreadcrumb", () => {
it("The tab variant are light when default", () => {
const { tabs } = setup(validationSteps.ready, false, false);

for (const [_key, tab] of tabs) {
expect(tab).toHaveClass(classForVariant("light"));
}
});

it.each([
["fetchingProof", validationSteps.fetchingProof],
["validatingProof", validationSteps.validatingProof],
["validatingCertificateChain", validationSteps.validatingCertificateChain],
])("The tab variant is primary when current and checks are valid : %s", (stepName, stepIndex) => {
const { tabs } = setup(stepIndex, true, true);

expect(tabs.get(stepIndex)).toHaveClass(classForVariant("primary"));
});

it("Current step is done and checks are valid then tabs are light except done step tab that is success", () => {
const { tabs } = setup(validationSteps.done, true, true);

expect(tabs.get(validationSteps.fetchingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingCertificateChain)).toHaveClass(
classForVariant("light"),
);
expect(tabs.get(validationSteps.done)).toHaveClass(classForVariant("success"));
});

it("Current step is done and proof check is invalid then tabs are danger except tabs before proof validation", () => {
const { tabs } = setup(validationSteps.done, false, true);

expect(tabs.get(validationSteps.fetchingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingProof)).toHaveClass(classForVariant("danger"));
expect(tabs.get(validationSteps.validatingCertificateChain)).toHaveClass(
classForVariant("danger"),
);
expect(tabs.get(validationSteps.done)).toHaveClass(classForVariant("danger"));
});

it("Current step is done and certificate chain check is invalid then tabs are danger except tabs before certificate chain validation", () => {
const { tabs } = setup(validationSteps.done, true, false);

expect(tabs.get(validationSteps.fetchingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingCertificateChain)).toHaveClass(
classForVariant("danger"),
);
expect(tabs.get(validationSteps.done)).toHaveClass(classForVariant("danger"));
});
});
2 changes: 1 addition & 1 deletion mithril-explorer/__tests__/helpers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { saveToLocalStorage, storeBuilder } from "../src/store/store";
import { saveToLocalStorage, storeBuilder } from "@/store/store";
import * as mockRouter from "next-router-mock";

const baseLocation = "http://localhost";
Expand Down
2 changes: 1 addition & 1 deletion mithril-explorer/__tests__/partyIdFormat.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatPartyId } from "../src/utils";
import { formatPartyId } from "@/utils";

describe("Stake formatting", () => {
it.each([
Expand Down
2 changes: 1 addition & 1 deletion mithril-explorer/__tests__/stakeFormat.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatStake } from "../src/utils";
import { formatStake } from "@/utils";

const toLovelace = (ada) => ada * 1000000;

Expand Down
10 changes: 5 additions & 5 deletions mithril-explorer/__tests__/store.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import default_available_aggregators from "../src/aggregators-list";
import { signedEntityType } from "../src/constants";
import { poolsSlice } from "../src/store/poolsSlice";
import default_available_aggregators from "@/aggregators-list";
import { signedEntityType } from "@/constants";
import { poolsSlice } from "@/store/poolsSlice";
import {
removeSelectedAggregator,
selectAggregator,
settingsSlice,
setUpdateInterval,
toggleAutoUpdate,
} from "../src/store/settingsSlice";
import { saveToLocalStorage, storeBuilder } from "../src/store/store";
} from "@/store/settingsSlice";
import { saveToLocalStorage, storeBuilder } from "@/store/store";
import { waitFor } from "@testing-library/react";
import { initStore } from "./helpers";

Expand Down
28 changes: 28 additions & 0 deletions mithril-explorer/font.css.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* autogenerated file using `make icons-font` - don't modify manually */

@font-face {
font-display: block;
font-family: "{{ name }}";
src: {{{ fontSrc }}};
}

.{{ prefix }}::before,
[class^="{{ prefix }}-"]::before,
[class*=" {{ prefix }}-"]::before {
display: inline-block;
font-family: {{ name }} !important;
font-style: normal;
font-weight: normal !important;
font-variant: normal;
text-transform: none;
line-height: 1;
vertical-align: -.125em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

{{# each codepoints }}
.{{ ../prefix }}-{{ @key }}::before {
content: "\\{{ codepoint this }}";
}
{{/ each }}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions mithril-explorer/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"#/*": ["./src/components/*"]
}
}
}
Loading

0 comments on commit 3fe1481

Please sign in to comment.