Update Network Explorer Packages and add mix node identity key copy (#1142)
* Use new eslint rules and apply fixes. Use new logo component and shared theme + webpack config. * Add shared component to display a copy icon and copy to clipboard with confirmation state * Organise imports * Add copy mixnode identity key to list of mixnodes and detail view * Update nvm node version to 16 * Update GitHub Actions for Network Explorer to use yarn and yarn workspaces * Switch favicon for smaller N icon * Update README * Add error boundary
This commit is contained in:
@@ -16,8 +16,9 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- run: npm install
|
||||
node-version: '16'
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
- name: Run ESLint
|
||||
# GitHub should automatically annotate the PR
|
||||
run: npm run lint
|
||||
run: yarn && yarn lint
|
||||
@@ -19,14 +19,17 @@ jobs:
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- run: npm install
|
||||
node-version: '16'
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
continue-on-error: true
|
||||
- name: Build shared packages
|
||||
run: cd .. && yarn && yarn build
|
||||
- name: Set environment from the example
|
||||
run: cp .env.prod .env
|
||||
- run: npm run test
|
||||
continue-on-error: true
|
||||
- run: npm run build
|
||||
# - run: yarn test
|
||||
# continue-on-error: true
|
||||
- run: yarn && yarn build
|
||||
continue-on-error: true
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 48 KiB |
@@ -1,13 +1,10 @@
|
||||
<svg width="300" height="300" viewBox="0 0 296 296" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M148 296C229.738 296 296 229.738 296 148C296 66.2619 229.738 0 148 0C66.2619 0 0 66.2619 0 148C0 229.738 66.2619 296 148 296Z" fill="url(#paint0_linear_113_1244)"/>
|
||||
<path d="M148 285.875C224.147 285.875 285.875 224.146 285.875 148C285.875 71.8536 224.147 10.1248 148 10.1248C71.8538 10.1248 10.125 71.8536 10.125 148C10.125 224.146 71.8538 285.875 148 285.875Z" fill="#121725"/>
|
||||
<path d="M88.8829 120.143H88.7169V120.281V168.637L68.3289 120.226L68.3012 120.143H68.1905H56.6272H43.653H43.5146V120.281V175.719V175.857H43.653H56.6272H56.7655V175.719V127.28L77.2365 175.774L77.2642 175.857H77.3748H88.8829H101.829H101.968V175.719V120.281V120.143H101.829H88.8829Z" fill="white"/>
|
||||
<path d="M252.347 120.143H227.616H227.477L227.45 120.253L214.78 168.858L202.082 120.253L202.054 120.143H201.944H177.157H176.991V120.281V175.719V175.857H177.157H190.104H190.242V175.719V127.667L202.774 175.747L202.801 175.857H202.94H226.564H226.675L226.703 175.747L239.234 127.667V175.719V175.857H239.373H252.347H252.485V175.719V120.281V120.143H252.347Z" fill="white"/>
|
||||
<path d="M155.663 120.143H155.58L155.552 120.198L139.812 147.557L123.988 120.198L123.96 120.143H123.877H108.911H108.635L108.773 120.364L133.145 162.579V175.719V175.857H133.283H146.257H146.396V175.719V162.579L170.767 120.364L170.905 120.143H170.629H155.663Z" fill="white"/>
|
||||
<svg width="64" height="64" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M40 78.5C61.263 78.5 78.5 61.263 78.5 40C78.5 18.737 61.263 1.5 40 1.5C18.737 1.5 1.5 18.737 1.5 40C1.5 61.263 18.737 78.5 40 78.5Z" fill="#070B15" stroke="url(#paint0_linear_0_1)" stroke-width="3"/>
|
||||
<path d="M31.4894 27.56L41.8623 56H48.5106H56V24H48.5106V52.4L38.1777 24H31.4894H24V56H31.4894V27.56Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_113_1244" x1="0" y1="148" x2="296" y2="148" gradientUnits="userSpaceOnUse">
|
||||
<linearGradient id="paint0_linear_0_1" x1="0.839161" y1="80" x2="80" y2="80" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.09375" stop-color="#FB6E4E"/>
|
||||
<stop offset="1" stop-color="#FC1D60"/>
|
||||
<stop offset="1" stop-color="#F51473"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 672 B |
@@ -1,103 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"jest": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"ecmaVersion": 2019,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"plugins": ["react", "react-hooks", "jsx-a11y", "prettier", "jest"],
|
||||
"extends": ["plugin:react/recommended", "airbnb", "prettier", "plugin:jest/recommended", "plugin:jest/style"],
|
||||
"rules": {
|
||||
"jest/prefer-strict-equal": "error",
|
||||
"jest/prefer-to-have-length": "warn",
|
||||
"prettier/prettier": "error",
|
||||
"import/prefer-default-export": "off",
|
||||
"react/prop-types": "off",
|
||||
"react/jsx-filename-extension": "off",
|
||||
"react/jsx-props-no-spreading": "off",
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
"devDependencies": [
|
||||
"**/*.test.[jt]s",
|
||||
"**/*.spec.[jt]s",
|
||||
"**/*.test.[jt]sx",
|
||||
"**/*.spec.[jt]sx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"import/extensions": [
|
||||
"error",
|
||||
"ignorePackages",
|
||||
{
|
||||
"ts": "never",
|
||||
"tsx": "never",
|
||||
"js": "never",
|
||||
"jsx": "never"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": "**/*.+(ts|tsx)",
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"plugins": ["@typescript-eslint/eslint-plugin"],
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"no-use-before-define": [0],
|
||||
"@typescript-eslint/no-use-before-define": [1],
|
||||
"import/no-unresolved": 0,
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
"devDependencies": [
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.tsx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"quotes": "off",
|
||||
"@typescript-eslint/quotes": [
|
||||
2,
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-unused-vars": [2, { "argsIgnorePattern": "^_" }]
|
||||
}
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"root-import": {
|
||||
"rootPathPrefix": "@",
|
||||
"rootPathSuffix": "src",
|
||||
"extensions": [".js", ".ts", ".tsx", ".jsx", ".mdx"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": [
|
||||
"@nymproject/eslint-config-react-typescript"
|
||||
]
|
||||
}
|
||||
+1
-1
@@ -1 +1 @@
|
||||
14
|
||||
16
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"trailingComma": "all",
|
||||
"singleQuote": true,
|
||||
"printWidth": 80,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2
|
||||
}
|
||||
|
||||
+17
-5
@@ -8,12 +8,22 @@ You will need:
|
||||
|
||||
- NodeJS (use `nvm install` to automatically install the correct version)
|
||||
- `npm`
|
||||
- `yarn`
|
||||
|
||||
> **Note**: This project ipart of a mono repo, so you will need to build the shared packages before starting. And any time they change, you'll need to rebuild them.
|
||||
|
||||
From the [root of the repository](../README.md) run the following to build shared packages:
|
||||
|
||||
```
|
||||
yarn
|
||||
yarn build
|
||||
```
|
||||
|
||||
From the `explorer` directory of the `nym` monorepo, run:
|
||||
|
||||
```
|
||||
npm install
|
||||
npm run start
|
||||
cd explorer
|
||||
yarn start
|
||||
```
|
||||
|
||||
You can then open a browser to http://localhost:3000 and start development.
|
||||
@@ -24,11 +34,13 @@ Documentation for developers [can be found here](./docs).
|
||||
|
||||
## Deployment
|
||||
|
||||
Build the UI with:
|
||||
Build the UI with (starting in the repository root):
|
||||
|
||||
```
|
||||
npm install
|
||||
npm run build
|
||||
yarn
|
||||
yarn build
|
||||
cd explorer
|
||||
yarn build
|
||||
```
|
||||
|
||||
The output will be in the `dist` directory. Serve this with `nginx` or `httpd`.
|
||||
|
||||
Generated
-30225
File diff suppressed because it is too large
Load Diff
+35
-24
@@ -12,20 +12,27 @@
|
||||
"@mui/styles": "^5.0.1",
|
||||
"@mui/system": "^5.0.1",
|
||||
"@mui/x-data-grid": "^5.0.0-beta.5",
|
||||
"@nymproject/mui-theme": "^1.0.0",
|
||||
"@nymproject/nym-validator-client": "^0.18.0",
|
||||
"@nymproject/react": "^1.0.0",
|
||||
"d3-scale": "^4.0.0",
|
||||
"date-fns": "^2.24.0",
|
||||
"i18n-iso-countries": "^6.8.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-error-boundary": "^3.1.4",
|
||||
"react-google-charts": "^3.0.15",
|
||||
"react-identicons": "^1.2.5",
|
||||
"react-router": "^5.2.1",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-simple-maps": "^2.3.0",
|
||||
"react-tooltip": "^4.2.21"
|
||||
"react-tooltip": "^4.2.21",
|
||||
"use-clipboard-copy": "^0.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.0-rc.3",
|
||||
"@nymproject/eslint-config-react-typescript": "^1.0.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
|
||||
"@svgr/webpack": "^6.1.1",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
"@testing-library/react": "^12.0.0",
|
||||
"@types/d3-fetch": "^3.0.1",
|
||||
@@ -36,32 +43,36 @@
|
||||
"@types/node": "^16.7.13",
|
||||
"@types/react": "^17.0.34",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"@types/react-router": "^5.1.18",
|
||||
"@types/react-router-dom": "^5.1.8",
|
||||
"@types/react-simple-maps": "^1.0.6",
|
||||
"@types/react-tooltip": "^4.2.4",
|
||||
"@types/topojson-client": "^3.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "4.31.0",
|
||||
"@typescript-eslint/parser": "4.31.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
||||
"@typescript-eslint/parser": "^5.13.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-plugin-root-import": "^6.6.0",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"dotenv-webpack": "^7.0.3",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-airbnb": "18.2.1",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-import-resolver-root-import": "1.0.4",
|
||||
"eslint-plugin-import": "2.24.2",
|
||||
"eslint-plugin-jest": "^24.4.0",
|
||||
"eslint-plugin-jsx-a11y": "6.4.1",
|
||||
"eslint-plugin-prettier": "4.0.0",
|
||||
"eslint-plugin-react": "7.25.1",
|
||||
"eslint-plugin-react-hooks": "4.2.0",
|
||||
"fork-ts-checker-webpack-plugin": "^6.3.3",
|
||||
"eslint": "^8.10.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^16.1.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-root-import": "^1.0.4",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-jest": "^26.1.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-react": "^7.29.2",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"eslint-plugin-storybook": "^0.5.7",
|
||||
"favicons-webpack-plugin": "^5.0.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"fork-ts-checker-webpack-plugin": "^7.2.1",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"imports-loader": "^3.0.0",
|
||||
"jest": "^27.1.0",
|
||||
"loader-utils": "^2.0.0",
|
||||
"mini-css-extract-plugin": "^2.2.2",
|
||||
"prettier": "2.3.2",
|
||||
"react-refresh": "^0.10.0",
|
||||
@@ -69,14 +80,14 @@
|
||||
"style-loader": "^3.2.1",
|
||||
"ts-jest": "^27.0.5",
|
||||
"ts-loader": "^9.2.5",
|
||||
"tsconfig-paths-webpack-plugin": "^3.5.1",
|
||||
"typescript": "^4.4.2",
|
||||
"webpack": "^5.52.0",
|
||||
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
||||
"typescript": "^4.6.2",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.64.3",
|
||||
"webpack-cli": "^4.8.0",
|
||||
"webpack-dev-server": "^4.1.0",
|
||||
"webpack-favicons": "^1.0.7",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"yaml-loader": "^0.6.0"
|
||||
"webpack-dev-server": "^4.5.0",
|
||||
"webpack-favicons": "^1.3.8",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "webpack serve --progress --port 3000",
|
||||
|
||||
@@ -15,7 +15,6 @@ export const COUNTRY_DATA_API = `${API_BASE_URL}/countries`;
|
||||
export const UPTIME_STORY_API = `${VALIDATOR_API_BASE_URL}/api/v1/status/mixnode`; // add ID then '/history' to this.
|
||||
|
||||
// errors
|
||||
export const MIXNODE_API_ERROR =
|
||||
"We're having trouble finding that record, please try again or Contact Us.";
|
||||
export const MIXNODE_API_ERROR = "We're having trouble finding that record, please try again or Contact Us.";
|
||||
|
||||
export const NYM_WEBSITE = 'https://nymtech.net';
|
||||
|
||||
@@ -63,9 +63,7 @@ export class Api {
|
||||
return json;
|
||||
};
|
||||
|
||||
static fetchMixnodesActiveSetByStatus = async (
|
||||
status: MixnodeStatus,
|
||||
): Promise<MixNodeResponse> => {
|
||||
static fetchMixnodesActiveSetByStatus = async (status: MixnodeStatus): Promise<MixNodeResponse> => {
|
||||
const cachedMixnodes = getFromCache(`mixnodes-${status}`);
|
||||
if (cachedMixnodes) {
|
||||
return cachedMixnodes;
|
||||
@@ -76,9 +74,7 @@ export class Api {
|
||||
return json;
|
||||
};
|
||||
|
||||
static fetchMixnodeByID = async (
|
||||
id: string,
|
||||
): Promise<MixNodeResponseItem | undefined> => {
|
||||
static fetchMixnodeByID = async (id: string): Promise<MixNodeResponseItem | undefined> => {
|
||||
const response = await fetch(`${MIXNODE_API}/${id}`);
|
||||
|
||||
// when the mixnode is not found, returned undefined
|
||||
@@ -117,24 +113,17 @@ export class Api {
|
||||
return result;
|
||||
};
|
||||
|
||||
static fetchDelegationsById = async (
|
||||
id: string,
|
||||
): Promise<DelegationsResponse> =>
|
||||
static fetchDelegationsById = async (id: string): Promise<DelegationsResponse> =>
|
||||
(await fetch(`${MIXNODE_API}/${id}/delegations`)).json();
|
||||
|
||||
static fetchStatsById = async (id: string): Promise<StatsResponse> =>
|
||||
(await fetch(`${MIXNODE_API}/${id}/stats`)).json();
|
||||
|
||||
static fetchMixnodeDescriptionById = async (
|
||||
id: string,
|
||||
): Promise<MixNodeDescriptionResponse> =>
|
||||
static fetchMixnodeDescriptionById = async (id: string): Promise<MixNodeDescriptionResponse> =>
|
||||
(await fetch(`${MIXNODE_API}/${id}/description`)).json();
|
||||
|
||||
static fetchStatusById = async (id: string): Promise<StatusResponse> =>
|
||||
(await fetch(`${MIXNODE_PING}/${id}`)).json();
|
||||
static fetchStatusById = async (id: string): Promise<StatusResponse> => (await fetch(`${MIXNODE_PING}/${id}`)).json();
|
||||
|
||||
static fetchUptimeStoryById = async (
|
||||
id: string,
|
||||
): Promise<UptimeStoryResponse> =>
|
||||
static fetchUptimeStoryById = async (id: string): Promise<UptimeStoryResponse> =>
|
||||
(await fetch(`${UPTIME_STORY_API}/${id}/history`)).json();
|
||||
}
|
||||
|
||||
@@ -20,14 +20,7 @@ export const ContentCard: React.FC<ContentCardProps> = ({
|
||||
onClick,
|
||||
}) => (
|
||||
<Card onClick={onClick} sx={{ height: '100%' }}>
|
||||
{title && (
|
||||
<CardHeader
|
||||
title={title || ''}
|
||||
avatar={Icon}
|
||||
action={Action}
|
||||
subheader={subtitle}
|
||||
/>
|
||||
)}
|
||||
{title && <CardHeader title={title || ''} avatar={Icon} action={Action} subheader={subtitle} />}
|
||||
{children && <CardContent>{children}</CardContent>}
|
||||
{errorMsg && (
|
||||
<Typography variant="body2" sx={{ color: 'danger', padding: 2 }}>
|
||||
|
||||
@@ -2,9 +2,7 @@ import * as React from 'react';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import { ExpandLess, ExpandMore } from '@mui/icons-material';
|
||||
|
||||
export const CustomColumnHeading: React.FC<{ headingTitle: string }> = ({
|
||||
headingTitle,
|
||||
}) => {
|
||||
export const CustomColumnHeading: React.FC<{ headingTitle: string }> = ({ headingTitle }) => {
|
||||
const [filter, toggleFilter] = React.useState<boolean>(false);
|
||||
|
||||
const handleClick = () => {
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
} from '@mui/material';
|
||||
import { Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material';
|
||||
import { CopyToClipboard } from '@nymproject/react';
|
||||
import { Box } from '@mui/system';
|
||||
import { cellStyles } from './Universal-DataGrid';
|
||||
import { currencyToString } from '../utils/currency';
|
||||
import { MixnodeRowType } from './MixNodes';
|
||||
@@ -27,6 +21,18 @@ export interface UniversalTableProps {
|
||||
}
|
||||
|
||||
function formatCellValues(val: string | number, field: string) {
|
||||
if (field === 'identity_key' && typeof val === 'string') {
|
||||
return (
|
||||
<Box display="flex" justifyContent="flex-end">
|
||||
<CopyToClipboard
|
||||
sx={{ mr: 1, mt: 0.5, fontSize: '18px' }}
|
||||
value={val}
|
||||
tooltip={`Copy identity key ${val} to clipboard`}
|
||||
/>
|
||||
<span>{val}</span>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
if (field === 'bond') {
|
||||
return currencyToString(val.toString());
|
||||
}
|
||||
@@ -51,10 +57,7 @@ export const DetailTable: React.FC<{
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{rows.map((eachRow) => (
|
||||
<TableRow
|
||||
key={eachRow.id}
|
||||
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
|
||||
>
|
||||
<TableRow key={eachRow.id} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
|
||||
{columnsData?.map((_, index) => (
|
||||
<TableCell
|
||||
key={_.title}
|
||||
@@ -69,10 +72,7 @@ export const DetailTable: React.FC<{
|
||||
}}
|
||||
data-testid={`${_.title.replace(/ /g, '-')}-value`}
|
||||
>
|
||||
{formatCellValues(
|
||||
eachRow[columnsData[index].field],
|
||||
columnsData[index].field,
|
||||
)}
|
||||
{formatCellValues(eachRow[columnsData[index].field], columnsData[index].field)}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
|
||||
@@ -39,7 +39,7 @@ export const Footer: React.FC = () => {
|
||||
sx={{
|
||||
fontSize: 12,
|
||||
textAlign: isMobile ? 'center' : 'end',
|
||||
color: theme.palette.nym.text.footer,
|
||||
color: theme.palette.nym.muted.onDarkBg,
|
||||
}}
|
||||
>
|
||||
© {new Date().getFullYear()} Nym Technologies SA, all rights reserved
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as React from 'react';
|
||||
import { GatewayResponse } from '../typeDefs/explorer-api';
|
||||
|
||||
export type GatewayRowType = {
|
||||
@@ -10,9 +9,7 @@ export type GatewayRowType = {
|
||||
location: string;
|
||||
};
|
||||
|
||||
export function gatewayToGridRow(
|
||||
arrayOfGateways: GatewayResponse,
|
||||
): GatewayRowType[] {
|
||||
export function gatewayToGridRow(arrayOfGateways: GatewayResponse): GatewayRowType[] {
|
||||
return !arrayOfGateways
|
||||
? []
|
||||
: arrayOfGateways.map((gw) => ({
|
||||
@@ -1,15 +1,14 @@
|
||||
import * as React from 'react';
|
||||
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
|
||||
import PauseCircleOutlineIcon from '@mui/icons-material/PauseCircleOutline';
|
||||
import CircleOutlinedIcon from '@mui/icons-material/CircleOutlined';
|
||||
import { MixnodeStatus } from '../typeDefs/explorer-api';
|
||||
|
||||
export const Icons = {
|
||||
mixnodes: {
|
||||
status: {
|
||||
active: CheckCircleOutlineIcon,
|
||||
standby: PauseCircleOutlineIcon,
|
||||
inactive: CircleOutlinedIcon,
|
||||
Mixnodes: {
|
||||
Status: {
|
||||
Active: CheckCircleOutlineIcon,
|
||||
Standby: PauseCircleOutlineIcon,
|
||||
Inactive: CircleOutlinedIcon,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -18,12 +17,12 @@ export const getMixNodeIcon = (value: any) => {
|
||||
if (value && typeof value === 'string') {
|
||||
switch (value) {
|
||||
case MixnodeStatus.active:
|
||||
return Icons.mixnodes.status.active;
|
||||
return Icons.Mixnodes.Status.Active;
|
||||
case MixnodeStatus.standby:
|
||||
return Icons.mixnodes.status.standby;
|
||||
return Icons.Mixnodes.Status.Standby;
|
||||
default:
|
||||
return Icons.mixnodes.status.inactive;
|
||||
return Icons.Mixnodes.Status.Inactive;
|
||||
}
|
||||
}
|
||||
return Icons.mixnodes.status.inactive;
|
||||
return Icons.Mixnodes.Status.Inactive;
|
||||
};
|
||||
@@ -14,8 +14,7 @@ import { useMixnodeContext } from '../../context/mixnode';
|
||||
|
||||
export const BondBreakdownTable: React.FC = () => {
|
||||
const { mixNode, delegations } = useMixnodeContext();
|
||||
const [showDelegations, toggleShowDelegations] =
|
||||
React.useState<boolean>(false);
|
||||
const [showDelegations, toggleShowDelegations] = React.useState<boolean>(false);
|
||||
|
||||
const [bonds, setBonds] = React.useState({
|
||||
delegations: '0',
|
||||
@@ -43,9 +42,7 @@ export const BondBreakdownTable: React.FC = () => {
|
||||
// bonds total (del + pledges)
|
||||
const pledgesSum = Number(mixNode.data.pledge_amount.amount);
|
||||
const delegationsSum = Number(mixNode.data.total_delegation.amount);
|
||||
const bondsTotal = currencyToString(
|
||||
(delegationsSum + pledgesSum).toString(),
|
||||
);
|
||||
const bondsTotal = currencyToString((delegationsSum + pledgesSum).toString());
|
||||
|
||||
setBonds({
|
||||
delegations: decimalisedDelegations,
|
||||
@@ -79,116 +76,95 @@ export const BondBreakdownTable: React.FC = () => {
|
||||
return <Alert severity="error">Mixnode not found</Alert>;
|
||||
}
|
||||
if (delegations?.error) {
|
||||
return (
|
||||
<Alert severity="error">Unable to get delegations for mixnode</Alert>
|
||||
);
|
||||
return <Alert severity="error">Unable to get delegations for mixnode</Alert>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableContainer component={Paper}>
|
||||
<Table sx={{ minWidth: 650 }} aria-label="bond breakdown totals">
|
||||
<TableBody>
|
||||
<TableRow sx={matches ? { minWidth: '70vw' } : null}>
|
||||
<TableCell
|
||||
<TableContainer component={Paper}>
|
||||
<Table sx={{ minWidth: 650 }} aria-label="bond breakdown totals">
|
||||
<TableBody>
|
||||
<TableRow sx={matches ? { minWidth: '70vw' } : null}>
|
||||
<TableCell
|
||||
sx={{
|
||||
fontWeight: 400,
|
||||
width: '150px',
|
||||
}}
|
||||
align="left"
|
||||
>
|
||||
Bond total
|
||||
</TableCell>
|
||||
<TableCell align="left" data-testid="bond-total-amount">
|
||||
{bonds.bondsTotal}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell align="left">Pledge total</TableCell>
|
||||
<TableCell align="left" data-testid="pledge-total-amount">
|
||||
{bonds.pledges}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell onClick={expandDelegations} align="left">
|
||||
<Box
|
||||
sx={{
|
||||
fontWeight: 400,
|
||||
width: '150px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
align="left"
|
||||
>
|
||||
Bond total
|
||||
</TableCell>
|
||||
<TableCell align="left" data-testid="bond-total-amount">
|
||||
{bonds.bondsTotal}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell align="left">Pledge total</TableCell>
|
||||
<TableCell align="left" data-testid="pledge-total-amount">
|
||||
{bonds.pledges}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell onClick={expandDelegations} align="left">
|
||||
<Box
|
||||
Delegation total {'\u00A0'}
|
||||
{delegations?.data && delegations?.data?.length > 0 && <ExpandMore />}
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell align="left" data-testid="delegation-total-amount">
|
||||
{bonds.delegations}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
{showDelegations && (
|
||||
<Box
|
||||
sx={{
|
||||
maxHeight: 400,
|
||||
overflowY: 'scroll',
|
||||
}}
|
||||
>
|
||||
<Table stickyHeader>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell sx={{ fontWeight: 600, background: '#242C3D' }} align="left">
|
||||
Delegators
|
||||
</TableCell>
|
||||
<TableCell sx={{ fontWeight: 600, background: '#242C3D' }} align="left">
|
||||
Stake
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
fontWeight: 600,
|
||||
background: '#242C3D',
|
||||
width: '200px',
|
||||
}}
|
||||
align="left"
|
||||
>
|
||||
Delegation total {'\u00A0'}
|
||||
{delegations?.data && delegations?.data?.length > 0 && (
|
||||
<ExpandMore />
|
||||
)}
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell align="left" data-testid="delegation-total-amount">
|
||||
{bonds.delegations}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
Share from bond
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
{showDelegations && (
|
||||
<Box
|
||||
sx={{
|
||||
maxHeight: 400,
|
||||
overflowY: 'scroll',
|
||||
}}
|
||||
>
|
||||
<Table stickyHeader>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell
|
||||
sx={{ fontWeight: 600, background: '#242C3D' }}
|
||||
align="left"
|
||||
>
|
||||
Delegators
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{ fontWeight: 600, background: '#242C3D' }}
|
||||
align="left"
|
||||
>
|
||||
Stake
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
background: '#242C3D',
|
||||
width: '200px',
|
||||
}}
|
||||
align="left"
|
||||
>
|
||||
Share from bond
|
||||
<TableBody>
|
||||
{delegations?.data?.map(({ owner, amount: { amount, denom } }) => (
|
||||
<TableRow key={owner}>
|
||||
<TableCell sx={matches ? { width: 190 } : null} align="left">
|
||||
{owner}
|
||||
</TableCell>
|
||||
<TableCell align="left">{currencyToString(amount.toString(), denom)}</TableCell>
|
||||
<TableCell align="left">{calcBondPercentage(amount)}%</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
<TableBody>
|
||||
{delegations?.data?.map(
|
||||
({ owner, amount: { amount, denom } }) => (
|
||||
<TableRow key={owner}>
|
||||
<TableCell
|
||||
sx={matches ? { width: 190 } : null}
|
||||
align="left"
|
||||
>
|
||||
{owner}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{currencyToString(amount.toString(), denom)}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{calcBondPercentage(amount)}%
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
),
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Box>
|
||||
)}
|
||||
</TableContainer>
|
||||
</>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Box>
|
||||
)}
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -11,17 +11,11 @@ interface MixNodeDetailProps {
|
||||
mixnodeDescription: MixNodeDescriptionResponse;
|
||||
}
|
||||
|
||||
export const MixNodeDetailSection: React.FC<MixNodeDetailProps> = ({
|
||||
mixNodeRow,
|
||||
mixnodeDescription,
|
||||
}) => {
|
||||
export const MixNodeDetailSection: React.FC<MixNodeDetailProps> = ({ mixNodeRow, mixnodeDescription }) => {
|
||||
const theme = useTheme();
|
||||
const palette = [theme.palette.text.primary];
|
||||
const matches = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
const statusText = React.useMemo(
|
||||
() => getMixNodeStatusText(mixNodeRow.status),
|
||||
[mixNodeRow.status],
|
||||
);
|
||||
const statusText = React.useMemo(() => getMixNodeStatusText(mixNodeRow.status), [mixNodeRow.status]);
|
||||
return (
|
||||
<Grid container>
|
||||
<Grid item xs={12} sm={6}>
|
||||
@@ -40,17 +34,11 @@ export const MixNodeDetailSection: React.FC<MixNodeDetailProps> = ({
|
||||
placeItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Identicon
|
||||
size={43}
|
||||
string={mixNodeRow.identity_key}
|
||||
palette={palette}
|
||||
/>
|
||||
<Identicon size={43} string={mixNodeRow.identity_key} palette={palette} />
|
||||
</Box>
|
||||
<Box ml={2}>
|
||||
<Typography fontSize={21}>{mixnodeDescription.name}</Typography>
|
||||
<Typography>
|
||||
{(mixnodeDescription.description || '').slice(0, 1000)}
|
||||
</Typography>
|
||||
<Typography>{(mixnodeDescription.description || '').slice(0, 1000)}</Typography>
|
||||
<Button
|
||||
component="a"
|
||||
variant="text"
|
||||
@@ -76,14 +64,7 @@ export const MixNodeDetailSection: React.FC<MixNodeDetailProps> = ({
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
sm={6}
|
||||
display="flex"
|
||||
justifyContent="end"
|
||||
mt={matches ? 5 : undefined}
|
||||
>
|
||||
<Grid item xs={12} sm={6} display="flex" justifyContent="end" mt={matches ? 5 : undefined}>
|
||||
<Box display="flex" flexDirection="column">
|
||||
<Typography fontWeight="600" alignSelf="self-end">
|
||||
Node status:
|
||||
@@ -91,12 +72,7 @@ export const MixNodeDetailSection: React.FC<MixNodeDetailProps> = ({
|
||||
<Box mt={2} alignSelf="self-end">
|
||||
<MixNodeStatus status={mixNodeRow.status} />
|
||||
</Box>
|
||||
<Typography
|
||||
mt={1}
|
||||
alignSelf="self-end"
|
||||
color={theme.palette.text.secondary}
|
||||
fontSize="smaller"
|
||||
>
|
||||
<Typography mt={1} alignSelf="self-end" color={theme.palette.text.secondary} fontSize="smaller">
|
||||
This node is {statusText} in this epoch
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Typography } from '@mui/material';
|
||||
import * as React from 'react';
|
||||
import { Theme, useTheme } from '@mui/material/styles';
|
||||
import { MixnodeRowType } from '.';
|
||||
import { getMixNodeIcon } from '../Icons';
|
||||
import { MixnodeStatus } from '../../typeDefs/explorer-api';
|
||||
|
||||
@@ -9,21 +8,6 @@ interface MixNodeStatusProps {
|
||||
status: MixnodeStatus;
|
||||
}
|
||||
|
||||
export const MixNodeStatus: React.FC<MixNodeStatusProps> = ({ status }) => {
|
||||
const theme = useTheme();
|
||||
const Icon = React.useMemo(() => getMixNodeIcon(status), [status]);
|
||||
const color = React.useMemo(() => getMixNodeStatusColor(theme, status), [status, theme]);
|
||||
|
||||
return (
|
||||
<Typography color={color} display="flex" alignItems="center">
|
||||
<Icon />
|
||||
<Typography ml={1} component="span" color="inherit">
|
||||
{`${status[0].toUpperCase()}${status.slice(1)}`}
|
||||
</Typography>
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
export const getMixNodeStatusColor = (theme: Theme, status: MixnodeStatus) => {
|
||||
let color;
|
||||
switch (status) {
|
||||
@@ -51,3 +35,18 @@ export const getMixNodeStatusText = (status: MixnodeStatus) => {
|
||||
return 'inactive';
|
||||
}
|
||||
};
|
||||
|
||||
export const MixNodeStatus: React.FC<MixNodeStatusProps> = ({ status }) => {
|
||||
const theme = useTheme();
|
||||
const Icon = React.useMemo(() => getMixNodeIcon(status), [status]);
|
||||
const color = React.useMemo(() => getMixNodeStatusColor(theme, status), [status, theme]);
|
||||
|
||||
return (
|
||||
<Typography color={color} display="flex" alignItems="center">
|
||||
<Icon />
|
||||
<Typography ml={1} component="span" color="inherit">
|
||||
{`${status[0].toUpperCase()}${status.slice(1)}`}
|
||||
</Typography>
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,10 +5,7 @@ import { SelectInputProps } from '@mui/material/Select/SelectInput';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { SxProps } from '@mui/system';
|
||||
import { MixNodeStatus } from './Status';
|
||||
import {
|
||||
MixnodeStatus,
|
||||
MixnodeStatusWithAll,
|
||||
} from '../../typeDefs/explorer-api';
|
||||
import { MixnodeStatus, MixnodeStatusWithAll } from '../../typeDefs/explorer-api';
|
||||
|
||||
// TODO: replace with i18n
|
||||
const ALL_NODES = 'All nodes';
|
||||
@@ -19,26 +16,19 @@ interface MixNodeStatusDropdownProps {
|
||||
onSelectionChanged?: (status?: MixnodeStatusWithAll) => void;
|
||||
}
|
||||
|
||||
export const MixNodeStatusDropdown: React.FC<MixNodeStatusDropdownProps> = ({
|
||||
status,
|
||||
onSelectionChanged,
|
||||
sx,
|
||||
}) => {
|
||||
export const MixNodeStatusDropdown: React.FC<MixNodeStatusDropdownProps> = ({ status, onSelectionChanged, sx }) => {
|
||||
const theme = useTheme();
|
||||
const matches = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
const [statusValue, setStatusValue] = React.useState<MixnodeStatusWithAll>(
|
||||
status || MixnodeStatusWithAll.all,
|
||||
const [statusValue, setStatusValue] = React.useState<MixnodeStatusWithAll>(status || MixnodeStatusWithAll.all);
|
||||
const onChange: SelectInputProps<MixnodeStatusWithAll>['onChange'] = React.useCallback(
|
||||
({ target: { value } }) => {
|
||||
setStatusValue(value);
|
||||
if (onSelectionChanged) {
|
||||
onSelectionChanged(value);
|
||||
}
|
||||
},
|
||||
[onSelectionChanged],
|
||||
);
|
||||
const onChange: SelectInputProps<MixnodeStatusWithAll>['onChange'] =
|
||||
React.useCallback(
|
||||
({ target: { value } }) => {
|
||||
setStatusValue(value);
|
||||
if (onSelectionChanged) {
|
||||
onSelectionChanged(value);
|
||||
}
|
||||
},
|
||||
[onSelectionChanged],
|
||||
);
|
||||
|
||||
return (
|
||||
<Select
|
||||
@@ -61,28 +51,16 @@ export const MixNodeStatusDropdown: React.FC<MixNodeStatusDropdownProps> = ({
|
||||
...sx,
|
||||
}}
|
||||
>
|
||||
<MenuItem
|
||||
value={MixnodeStatus.active}
|
||||
data-testid="mixnodeStatusSelectOption_active"
|
||||
>
|
||||
<MenuItem value={MixnodeStatus.active} data-testid="mixnodeStatusSelectOption_active">
|
||||
<MixNodeStatus status={MixnodeStatus.active} />
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
value={MixnodeStatus.standby}
|
||||
data-testid="mixnodeStatusSelectOption_standby"
|
||||
>
|
||||
<MenuItem value={MixnodeStatus.standby} data-testid="mixnodeStatusSelectOption_standby">
|
||||
<MixNodeStatus status={MixnodeStatus.standby} />
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
value={MixnodeStatus.inactive}
|
||||
data-testid="mixnodeStatusSelectOption_inactive"
|
||||
>
|
||||
<MenuItem value={MixnodeStatus.inactive} data-testid="mixnodeStatusSelectOption_inactive">
|
||||
<MixNodeStatus status={MixnodeStatus.inactive} />
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
value={MixnodeStatusWithAll.all}
|
||||
data-testid="mixnodeStatusSelectOption_allNodes"
|
||||
>
|
||||
<MenuItem value={MixnodeStatusWithAll.all} data-testid="mixnodeStatusSelectOption_allNodes">
|
||||
{ALL_NODES}
|
||||
</MenuItem>
|
||||
</Select>
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
/* eslint-disable camelcase */
|
||||
import {
|
||||
MixNodeResponse,
|
||||
MixNodeResponseItem,
|
||||
MixnodeStatus,
|
||||
} from '../../typeDefs/explorer-api';
|
||||
import { MixNodeResponse, MixNodeResponseItem, MixnodeStatus } from '../../typeDefs/explorer-api';
|
||||
|
||||
export type MixnodeRowType = {
|
||||
id: string;
|
||||
@@ -17,15 +13,11 @@ export type MixnodeRowType = {
|
||||
layer: string;
|
||||
};
|
||||
|
||||
export function mixnodeToGridRow(
|
||||
arrayOfMixnodes?: MixNodeResponse,
|
||||
): MixnodeRowType[] {
|
||||
export function mixnodeToGridRow(arrayOfMixnodes?: MixNodeResponse): MixnodeRowType[] {
|
||||
return (arrayOfMixnodes || []).map(mixNodeResponseItemToMixnodeRowType);
|
||||
}
|
||||
|
||||
export function mixNodeResponseItemToMixnodeRowType(
|
||||
item: MixNodeResponseItem,
|
||||
): MixnodeRowType {
|
||||
export function mixNodeResponseItemToMixnodeRowType(item: MixNodeResponseItem): MixnodeRowType {
|
||||
const pledge = Number(item.pledge_amount.amount) || 0;
|
||||
const delegations = Number(item.total_delegation.amount) || 0;
|
||||
const totalBond = pledge + delegations;
|
||||
|
||||
@@ -16,9 +16,9 @@ import {
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { Menu } from '@mui/icons-material';
|
||||
import { NymLogoSVG } from 'src/icons/NymLogoSVG';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { MobileDrawerClose } from 'src/icons/MobileDrawerClose';
|
||||
import { NymLogo } from '@nymproject/react';
|
||||
import { useMainContext } from '../context/main';
|
||||
import { MobileDrawerClose } from '../icons/MobileDrawerClose';
|
||||
import { Footer } from './Footer';
|
||||
import { NYM_WEBSITE } from '../api/constants';
|
||||
import { ExpandableButton } from './Nav';
|
||||
@@ -28,9 +28,7 @@ type MobileNavProps = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export const MobileNav: React.FC<{ children: React.ReactNode }> = ({
|
||||
children,
|
||||
}: MobileNavProps) => {
|
||||
export const MobileNav: React.FC<{ children: React.ReactNode }> = ({ children }: MobileNavProps) => {
|
||||
const theme = useTheme();
|
||||
const { navState, updateNavState } = useMainContext();
|
||||
const [drawerOpen, setDrawerOpen] = React.useState(false);
|
||||
@@ -73,7 +71,7 @@ export const MobileNav: React.FC<{ children: React.ReactNode }> = ({
|
||||
}}
|
||||
>
|
||||
<IconButton component="a" href={NYM_WEBSITE} target="_blank">
|
||||
<NymLogoSVG />
|
||||
<NymLogo height="40px" width="40px" />
|
||||
</IconButton>
|
||||
<Typography
|
||||
variant="h6"
|
||||
@@ -85,12 +83,7 @@ export const MobileNav: React.FC<{ children: React.ReactNode }> = ({
|
||||
ml: 2,
|
||||
}}
|
||||
>
|
||||
<MuiLink
|
||||
component={Link}
|
||||
to="/overview"
|
||||
underline="none"
|
||||
color="inherit"
|
||||
>
|
||||
<MuiLink component={Link} to="/overview" underline="none" color="inherit">
|
||||
Network Explorer
|
||||
</MuiLink>
|
||||
</Typography>
|
||||
|
||||
@@ -14,10 +14,10 @@ import IconButton from '@mui/material/IconButton';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import { NymLogoSVG } from 'src/icons/NymLogoSVG';
|
||||
import { BIG_DIPPER, NYM_WEBSITE } from 'src/api/constants';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { MobileDrawerClose } from 'src/icons/MobileDrawerClose';
|
||||
import { NymLogo } from '@nymproject/react';
|
||||
import { BIG_DIPPER, NYM_WEBSITE } from '../api/constants';
|
||||
import { useMainContext } from '../context/main';
|
||||
import { MobileDrawerClose } from '../icons/MobileDrawerClose';
|
||||
import { OverviewSVG } from '../icons/OverviewSVG';
|
||||
import { NetworkComponentsSVG } from '../icons/NetworksSVG';
|
||||
import { NodemapSVG } from '../icons/NodemapSVG';
|
||||
@@ -70,17 +70,17 @@ const Drawer = styled(MuiDrawer, {
|
||||
}),
|
||||
}));
|
||||
|
||||
type navOptionType = {
|
||||
type NavOptionType = {
|
||||
id: number;
|
||||
isActive?: boolean;
|
||||
url: string;
|
||||
title: string;
|
||||
Icon?: React.ReactNode;
|
||||
nested?: navOptionType[];
|
||||
nested?: NavOptionType[];
|
||||
isExpandedChild?: boolean;
|
||||
};
|
||||
|
||||
export const originalNavOptions: navOptionType[] = [
|
||||
export const originalNavOptions: NavOptionType[] = [
|
||||
{
|
||||
id: 0,
|
||||
isActive: false,
|
||||
@@ -127,7 +127,7 @@ type ExpandableButtonType = {
|
||||
url: string;
|
||||
isActive?: boolean;
|
||||
Icon?: React.ReactNode;
|
||||
nested?: navOptionType[];
|
||||
nested?: NavOptionType[];
|
||||
isChild?: boolean;
|
||||
openDrawer: () => void;
|
||||
closeDrawer?: () => void;
|
||||
@@ -226,9 +226,7 @@ export const ExpandableButton: React.FC<ExpandableButtonType> = ({
|
||||
sx={{
|
||||
pt: 2,
|
||||
pb: 2,
|
||||
background: isChild
|
||||
? palette.nym.networkExplorer.nav.selected.nested
|
||||
: 'none',
|
||||
background: isChild ? palette.nym.networkExplorer.nav.selected.nested : 'none',
|
||||
}}
|
||||
>
|
||||
<ListItemIcon>{Icon}</ListItemIcon>
|
||||
@@ -334,7 +332,7 @@ export const Nav: React.FC = ({ children }) => {
|
||||
}}
|
||||
>
|
||||
<IconButton component="a" href={NYM_WEBSITE} target="_blank">
|
||||
<NymLogoSVG />
|
||||
<NymLogo height="40px" width="40px" />
|
||||
</IconButton>
|
||||
<Typography
|
||||
variant="h6"
|
||||
@@ -345,12 +343,7 @@ export const Nav: React.FC = ({ children }) => {
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
<MuiLink
|
||||
component={Link}
|
||||
to="/overview"
|
||||
underline="none"
|
||||
color="inherit"
|
||||
>
|
||||
<MuiLink component={Link} to="/overview" underline="none" color="inherit">
|
||||
Network Explorer
|
||||
</MuiLink>
|
||||
</Typography>
|
||||
@@ -408,11 +401,7 @@ export const Nav: React.FC = ({ children }) => {
|
||||
</IconButton>
|
||||
</DrawerHeader>
|
||||
|
||||
<List
|
||||
sx={{ pt: 0, pb: 0 }}
|
||||
onMouseEnter={tempDrawerOpen}
|
||||
onMouseLeave={tempDrawerClose}
|
||||
>
|
||||
<List sx={{ pt: 0, pb: 0 }} onMouseEnter={tempDrawerOpen} onMouseLeave={tempDrawerClose}>
|
||||
{navState.map((props) => (
|
||||
<ExpandableButton
|
||||
key={props.url}
|
||||
|
||||
@@ -19,38 +19,18 @@ export const Socials: React.FC<{ isFooter?: boolean }> = ({ isFooter }) => {
|
||||
: theme.palette.nym.networkExplorer.topNav.socialIcons;
|
||||
return (
|
||||
<Box>
|
||||
<IconButton
|
||||
component="a"
|
||||
href={TELEGRAM_LINK}
|
||||
target="_blank"
|
||||
data-testid="telegram"
|
||||
>
|
||||
<IconButton component="a" href={TELEGRAM_LINK} target="_blank" data-testid="telegram">
|
||||
<TelegramIcon color={color} size={24} />
|
||||
</IconButton>
|
||||
{false && (
|
||||
<IconButton
|
||||
component="a"
|
||||
href={DISCORD_LINK}
|
||||
target="_blank"
|
||||
data-testid="discord"
|
||||
>
|
||||
<IconButton component="a" href={DISCORD_LINK} target="_blank" data-testid="discord">
|
||||
<DiscordIcon color={color} size={24} />
|
||||
</IconButton>
|
||||
)}
|
||||
<IconButton
|
||||
component="a"
|
||||
href={TWITTER_LINK}
|
||||
target="_blank"
|
||||
data-testid="twitter"
|
||||
>
|
||||
<IconButton component="a" href={TWITTER_LINK} target="_blank" data-testid="twitter">
|
||||
<TwitterIcon color={color} size={24} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
component="a"
|
||||
href={GITHUB_LINK}
|
||||
target="_blank"
|
||||
data-testid="github"
|
||||
>
|
||||
<IconButton component="a" href={GITHUB_LINK} target="_blank" data-testid="github">
|
||||
<GitHubIcon color={color} size={24} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
|
||||
@@ -11,14 +11,7 @@ interface StatsCardProps {
|
||||
onClick?: () => void;
|
||||
color?: string;
|
||||
}
|
||||
export const StatsCard: React.FC<StatsCardProps> = ({
|
||||
icon,
|
||||
title,
|
||||
count,
|
||||
onClick,
|
||||
errorMsg,
|
||||
color: colorProp,
|
||||
}) => {
|
||||
export const StatsCard: React.FC<StatsCardProps> = ({ icon, title, count, onClick, errorMsg, color: colorProp }) => {
|
||||
const theme = useTheme();
|
||||
const color = colorProp || theme.palette.text.primary;
|
||||
return (
|
||||
@@ -38,21 +31,10 @@ export const StatsCard: React.FC<StatsCardProps> = ({
|
||||
<Box display="flex" alignItems="center" color={color}>
|
||||
<Box display="flex">
|
||||
{icon}
|
||||
<Typography
|
||||
ml={3}
|
||||
mr={0.75}
|
||||
fontSize="inherit"
|
||||
fontWeight="inherit"
|
||||
data-testid={`${title}-amount`}
|
||||
>
|
||||
<Typography ml={3} mr={0.75} fontSize="inherit" fontWeight="inherit" data-testid={`${title}-amount`}>
|
||||
{count === undefined || count === null ? '' : count}
|
||||
</Typography>
|
||||
<Typography
|
||||
mr={1}
|
||||
fontSize="inherit"
|
||||
fontWeight="inherit"
|
||||
data-testid={title}
|
||||
>
|
||||
<Typography mr={1} fontSize="inherit" fontWeight="inherit" data-testid={title}>
|
||||
{title}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Switch from '@mui/material/Switch';
|
||||
import { Button } from '@mui/material';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { useMainContext } from '../context/main';
|
||||
import { LightSwitchSVG } from '../icons/LightSwitchSVG';
|
||||
|
||||
export const DarkLightSwitch = styled(Switch)(({ theme }) => ({
|
||||
@@ -60,16 +60,10 @@ export const DarkLightSwitchMobile: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const DarkLightSwitchDesktop: React.FC<{ defaultChecked: boolean }> = ({
|
||||
defaultChecked,
|
||||
}) => {
|
||||
export const DarkLightSwitchDesktop: React.FC<{ defaultChecked: boolean }> = ({ defaultChecked }) => {
|
||||
const { toggleMode } = useMainContext();
|
||||
return (
|
||||
<Button
|
||||
sx={{ paddingLeft: 0 }}
|
||||
onClick={() => toggleMode()}
|
||||
data-testid="switch-button"
|
||||
>
|
||||
<Button sx={{ paddingLeft: 0 }} onClick={() => toggleMode()} data-testid="switch-button">
|
||||
<DarkLightSwitch defaultChecked={defaultChecked} />
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -23,55 +23,53 @@ export const TableToolbar: React.FC<TableToolBarProps> = ({
|
||||
const theme = useTheme();
|
||||
const matches = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
marginBottom: 2,
|
||||
display: 'flex',
|
||||
flexDirection: matches ? 'column-reverse' : 'row',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex', alignItems: 'middle' }}>
|
||||
{childrenBefore}
|
||||
<Select
|
||||
labelId="simple-select-label"
|
||||
id="simple-select"
|
||||
value={pageSize}
|
||||
onChange={onChangePageSize}
|
||||
sx={{
|
||||
width: matches ? 100 : 200,
|
||||
}}
|
||||
>
|
||||
<MenuItem value={10} data-testid="ten">
|
||||
10
|
||||
</MenuItem>
|
||||
<MenuItem value={30} data-testid="thirty">
|
||||
30
|
||||
</MenuItem>
|
||||
<MenuItem value={50} data-testid="fifty">
|
||||
50
|
||||
</MenuItem>
|
||||
<MenuItem value={100} data-testid="hundred">
|
||||
100
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', alignItems: 'middle' }}>
|
||||
<TextField
|
||||
sx={{
|
||||
width: matches ? '100%' : 350,
|
||||
marginBottom: matches ? 2 : 0,
|
||||
}}
|
||||
value={searchTerm}
|
||||
data-testid="search-box"
|
||||
placeholder="search"
|
||||
onChange={(event) => onChangeSearch(event.target.value)}
|
||||
/>
|
||||
{childrenAfter}
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
marginBottom: 2,
|
||||
display: 'flex',
|
||||
flexDirection: matches ? 'column-reverse' : 'row',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex', alignItems: 'middle' }}>
|
||||
{childrenBefore}
|
||||
<Select
|
||||
labelId="simple-select-label"
|
||||
id="simple-select"
|
||||
value={pageSize}
|
||||
onChange={onChangePageSize}
|
||||
sx={{
|
||||
width: matches ? 100 : 200,
|
||||
}}
|
||||
>
|
||||
<MenuItem value={10} data-testid="ten">
|
||||
10
|
||||
</MenuItem>
|
||||
<MenuItem value={30} data-testid="thirty">
|
||||
30
|
||||
</MenuItem>
|
||||
<MenuItem value={50} data-testid="fifty">
|
||||
50
|
||||
</MenuItem>
|
||||
<MenuItem value={100} data-testid="hundred">
|
||||
100
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</Box>
|
||||
</>
|
||||
<Box sx={{ display: 'flex', alignItems: 'middle' }}>
|
||||
<TextField
|
||||
sx={{
|
||||
width: matches ? '100%' : 350,
|
||||
marginBottom: matches ? 2 : 0,
|
||||
}}
|
||||
value={searchTerm}
|
||||
data-testid="search-box"
|
||||
placeholder="search"
|
||||
onChange={(event) => onChangeSearch(event.target.value)}
|
||||
/>
|
||||
{childrenAfter}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -31,23 +31,13 @@ export const TwoColSmallTable: React.FC<TableProps> = ({
|
||||
<>
|
||||
{title && <Typography sx={{ marginTop: 2 }}>{title}</Typography>}
|
||||
|
||||
<TableContainer
|
||||
component={Paper}
|
||||
sx={marginBottom ? { marginBottom: 4, marginTop: 2 } : { marginTop: 2 }}
|
||||
>
|
||||
<TableContainer component={Paper} sx={marginBottom ? { marginBottom: 4, marginTop: 2 } : { marginTop: 2 }}>
|
||||
<Table aria-label="two col small table">
|
||||
<TableBody>
|
||||
{keys.map((each: string, i: number) => (
|
||||
<TableRow key={each}>
|
||||
{icons && (
|
||||
<TableCell>
|
||||
{icons[i] ? <CheckCircleSharpIcon /> : <ErrorIcon />}
|
||||
</TableCell>
|
||||
)}
|
||||
<TableCell
|
||||
sx={error ? { opacity: 0.4 } : null}
|
||||
data-testid={each.replace(/ /g, '')}
|
||||
>
|
||||
{icons && <TableCell>{icons[i] ? <CheckCircleSharpIcon /> : <ErrorIcon />}</TableCell>}
|
||||
<TableCell sx={error ? { opacity: 0.4 } : null} data-testid={each.replace(/ /g, '')}>
|
||||
{each}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { makeStyles } from '@mui/styles';
|
||||
import {
|
||||
DataGrid,
|
||||
GridColDef,
|
||||
useGridApiContext,
|
||||
useGridState,
|
||||
} from '@mui/x-data-grid';
|
||||
import { DataGrid, GridColDef, useGridApiContext, useGridState } from '@mui/x-data-grid';
|
||||
import Pagination from '@mui/material/Pagination';
|
||||
import { SxProps } from '@mui/system';
|
||||
import { LinearProgress } from '@mui/material';
|
||||
@@ -30,7 +25,7 @@ export const cellStyles: SxProps = {
|
||||
whiteSpace: 'break-spaces',
|
||||
};
|
||||
|
||||
function CustomPagination() {
|
||||
const CustomPagination = () => {
|
||||
const apiRef = useGridApiContext();
|
||||
const [state] = useGridState(apiRef);
|
||||
|
||||
@@ -46,7 +41,7 @@ function CustomPagination() {
|
||||
onChange={(event, value) => apiRef.current.setPage(value - 1)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
type DataGridProps = {
|
||||
columns: GridColDef[];
|
||||
@@ -55,13 +50,7 @@ type DataGridProps = {
|
||||
rows: any;
|
||||
loading?: boolean;
|
||||
};
|
||||
export const UniversalDataGrid: React.FC<DataGridProps> = ({
|
||||
rows,
|
||||
columns,
|
||||
loading,
|
||||
pagination,
|
||||
pageSize,
|
||||
}) => {
|
||||
export const UniversalDataGrid: React.FC<DataGridProps> = ({ rows, columns, loading, pagination, pageSize }) => {
|
||||
if (loading) return <LinearProgress />;
|
||||
if (!loading)
|
||||
return (
|
||||
|
||||
@@ -2,8 +2,8 @@ import * as React from 'react';
|
||||
import { CircularProgress, Typography } from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { Chart } from 'react-google-charts';
|
||||
import { ApiState, UptimeStoryResponse } from 'src/typeDefs/explorer-api';
|
||||
import { format } from 'date-fns';
|
||||
import { ApiState, UptimeStoryResponse } from '../typeDefs/explorer-api';
|
||||
|
||||
interface ChartProps {
|
||||
title?: string;
|
||||
@@ -17,15 +17,8 @@ type FormattedDateRecord = [string, number];
|
||||
type FormattedChartHeadings = string[];
|
||||
type FormattedChartData = [FormattedChartHeadings | FormattedDateRecord];
|
||||
|
||||
export const UptimeChart: React.FC<ChartProps> = ({
|
||||
title,
|
||||
xLabel,
|
||||
yLabel,
|
||||
uptimeStory,
|
||||
loading,
|
||||
}) => {
|
||||
const [formattedChartData, setFormattedChartData] =
|
||||
React.useState<FormattedChartData>();
|
||||
export const UptimeChart: React.FC<ChartProps> = ({ title, xLabel, yLabel, uptimeStory, loading }) => {
|
||||
const [formattedChartData, setFormattedChartData] = React.useState<FormattedChartData>();
|
||||
const theme = useTheme();
|
||||
const color = theme.palette.text.primary;
|
||||
React.useEffect(() => {
|
||||
@@ -68,12 +61,8 @@ export const UptimeChart: React.FC<ChartProps> = ({
|
||||
}
|
||||
options={{
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'dark'
|
||||
? theme.palette.nym.networkExplorer.background.tertiary
|
||||
: undefined,
|
||||
color: uptimeStory.error
|
||||
? 'rgba(255, 255, 255, 0.4)'
|
||||
: 'rgba(255, 255, 255, 1)',
|
||||
theme.palette.mode === 'dark' ? theme.palette.nym.networkExplorer.background.tertiary : undefined,
|
||||
color: uptimeStory.error ? 'rgba(255, 255, 255, 0.4)' : 'rgba(255, 255, 255, 1)',
|
||||
colors: ['#FB7A21'],
|
||||
legend: {
|
||||
textStyle: {
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import * as React from 'react';
|
||||
import { scaleLinear } from 'd3-scale';
|
||||
import {
|
||||
ComposableMap,
|
||||
Geographies,
|
||||
Geography,
|
||||
Marker,
|
||||
ZoomableGroup,
|
||||
} from 'react-simple-maps';
|
||||
import { ComposableMap, Geographies, Geography, Marker, ZoomableGroup } from 'react-simple-maps';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
import { ApiState, CountryDataResponse } from 'src/typeDefs/explorer-api';
|
||||
import { CircularProgress } from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { ApiState, CountryDataResponse } from '../typeDefs/explorer-api';
|
||||
import MAP_TOPOJSON from '../assets/world-110m.json';
|
||||
|
||||
type MapProps = {
|
||||
@@ -20,35 +14,21 @@ type MapProps = {
|
||||
loading: boolean;
|
||||
};
|
||||
|
||||
export const WorldMap: React.FC<MapProps> = ({
|
||||
countryData,
|
||||
userLocation,
|
||||
loading,
|
||||
}) => {
|
||||
export const WorldMap: React.FC<MapProps> = ({ countryData, userLocation, loading }) => {
|
||||
const { palette } = useTheme();
|
||||
|
||||
const colorScale = React.useMemo(() => {
|
||||
if (countryData?.data) {
|
||||
const heighestNumberOfNodes = Math.max(
|
||||
...Object.values(countryData.data).map((country) => country.nodes),
|
||||
);
|
||||
const heighestNumberOfNodes = Math.max(...Object.values(countryData.data).map((country) => country.nodes));
|
||||
return scaleLinear<string, string>()
|
||||
.domain([
|
||||
0,
|
||||
1,
|
||||
heighestNumberOfNodes / 4,
|
||||
heighestNumberOfNodes / 2,
|
||||
heighestNumberOfNodes,
|
||||
])
|
||||
.domain([0, 1, heighestNumberOfNodes / 4, heighestNumberOfNodes / 2, heighestNumberOfNodes])
|
||||
.range(palette.nym.networkExplorer.map.fills)
|
||||
.unknown(palette.nym.networkExplorer.map.fills[0]);
|
||||
}
|
||||
return () => palette.nym.networkExplorer.map.fills[0];
|
||||
}, [countryData, palette]);
|
||||
|
||||
const [tooltipContent, setTooltipContent] = React.useState<string | null>(
|
||||
null,
|
||||
);
|
||||
const [tooltipContent, setTooltipContent] = React.useState<string | null>(null);
|
||||
|
||||
if (loading) {
|
||||
return <CircularProgress />;
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
import * as React from 'react';
|
||||
import { PaletteMode } from '@mui/material';
|
||||
import { MIXNODE_API_ERROR } from 'src/api/constants';
|
||||
import {
|
||||
ApiState,
|
||||
BlockResponse,
|
||||
CountryDataResponse,
|
||||
GatewayResponse,
|
||||
MixNodeResponse,
|
||||
ValidatorsResponse,
|
||||
BlockResponse,
|
||||
ApiState,
|
||||
MixNodeResponseItem,
|
||||
DelegationsResponse,
|
||||
StatsResponse,
|
||||
StatusResponse,
|
||||
UptimeStoryResponse,
|
||||
MixNodeDescriptionResponse,
|
||||
MixnodeStatus,
|
||||
SummaryOverviewResponse,
|
||||
} from 'src/typeDefs/explorer-api';
|
||||
ValidatorsResponse,
|
||||
} from '../typeDefs/explorer-api';
|
||||
import { Api } from '../api';
|
||||
import { navOptionType, originalNavOptions } from './nav';
|
||||
import { NavOptionType, originalNavOptions } from './nav';
|
||||
|
||||
interface StateData {
|
||||
summaryOverview?: ApiState<SummaryOverviewResponse>;
|
||||
@@ -28,7 +21,7 @@ interface StateData {
|
||||
globalError?: string | undefined;
|
||||
mixnodes?: ApiState<MixNodeResponse>;
|
||||
mode: PaletteMode;
|
||||
navState: navOptionType[];
|
||||
navState: NavOptionType[];
|
||||
validators?: ApiState<ValidatorsResponse>;
|
||||
}
|
||||
|
||||
@@ -50,30 +43,25 @@ export const MainContext = React.createContext<State>({
|
||||
fetchMixnodes: () => null,
|
||||
});
|
||||
|
||||
export const useMainContext = (): React.ContextType<typeof MainContext> =>
|
||||
React.useContext<State>(MainContext);
|
||||
export const useMainContext = (): React.ContextType<typeof MainContext> => React.useContext<State>(MainContext);
|
||||
|
||||
export const MainContextProvider: React.FC = ({ children }) => {
|
||||
// light/dark mode
|
||||
const [mode, setMode] = React.useState<PaletteMode>('dark');
|
||||
|
||||
// nav state
|
||||
const [navState, updateNav] =
|
||||
React.useState<navOptionType[]>(originalNavOptions);
|
||||
const [navState, updateNav] = React.useState<NavOptionType[]>(originalNavOptions);
|
||||
|
||||
// global / banner error messaging
|
||||
const [globalError, setGlobalError] = React.useState<string>();
|
||||
const [globalError] = React.useState<string>();
|
||||
|
||||
// various APIs for Overview page
|
||||
const [summaryOverview, setSummaryOverview] =
|
||||
React.useState<ApiState<SummaryOverviewResponse>>();
|
||||
const [summaryOverview, setSummaryOverview] = React.useState<ApiState<SummaryOverviewResponse>>();
|
||||
const [mixnodes, setMixnodes] = React.useState<ApiState<MixNodeResponse>>();
|
||||
const [gateways, setGateways] = React.useState<ApiState<GatewayResponse>>();
|
||||
const [validators, setValidators] =
|
||||
React.useState<ApiState<ValidatorsResponse>>();
|
||||
const [validators, setValidators] = React.useState<ApiState<ValidatorsResponse>>();
|
||||
const [block, setBlock] = React.useState<ApiState<BlockResponse>>();
|
||||
const [countryData, setCountryData] =
|
||||
React.useState<ApiState<CountryDataResponse>>();
|
||||
const [countryData, setCountryData] = React.useState<ApiState<CountryDataResponse>>();
|
||||
|
||||
const toggleMode = () => setMode((m) => (m !== 'light' ? 'light' : 'dark'));
|
||||
|
||||
@@ -83,10 +71,7 @@ export const MainContextProvider: React.FC = ({ children }) => {
|
||||
setSummaryOverview({ data, isLoading: false });
|
||||
} catch (error) {
|
||||
setSummaryOverview({
|
||||
error:
|
||||
error instanceof Error
|
||||
? error
|
||||
: new Error('Overview summary api fail'),
|
||||
error: error instanceof Error ? error : new Error('Overview summary api fail'),
|
||||
isLoading: false,
|
||||
});
|
||||
}
|
||||
@@ -95,9 +80,7 @@ export const MainContextProvider: React.FC = ({ children }) => {
|
||||
const fetchMixnodes = async (status?: MixnodeStatus) => {
|
||||
setMixnodes((d) => ({ ...d, isLoading: true }));
|
||||
try {
|
||||
const data = status
|
||||
? await Api.fetchMixnodesActiveSetByStatus(status)
|
||||
: await Api.fetchMixnodes();
|
||||
const data = status ? await Api.fetchMixnodesActiveSetByStatus(status) : await Api.fetchMixnodes();
|
||||
setMixnodes({ data, isLoading: false });
|
||||
} catch (error) {
|
||||
setMixnodes({
|
||||
@@ -126,8 +109,7 @@ export const MainContextProvider: React.FC = ({ children }) => {
|
||||
setValidators({ data, isLoading: false });
|
||||
} catch (error) {
|
||||
setValidators({
|
||||
error:
|
||||
error instanceof Error ? error : new Error('Validators api fail'),
|
||||
error: error instanceof Error ? error : new Error('Validators api fail'),
|
||||
isLoading: false,
|
||||
});
|
||||
}
|
||||
@@ -150,8 +132,7 @@ export const MainContextProvider: React.FC = ({ children }) => {
|
||||
setCountryData({ data: res, isLoading: false });
|
||||
} catch (error) {
|
||||
setCountryData({
|
||||
error:
|
||||
error instanceof Error ? error : new Error('Country Data api fail'),
|
||||
error: error instanceof Error ? error : new Error('Country Data api fail'),
|
||||
isLoading: false,
|
||||
});
|
||||
}
|
||||
@@ -164,34 +145,27 @@ export const MainContextProvider: React.FC = ({ children }) => {
|
||||
updateNav(updated);
|
||||
};
|
||||
React.useEffect(() => {
|
||||
Promise.all([
|
||||
fetchOverviewSummary(),
|
||||
fetchGateways(),
|
||||
fetchValidators(),
|
||||
fetchBlock(),
|
||||
fetchCountryData(),
|
||||
]);
|
||||
Promise.all([fetchOverviewSummary(), fetchGateways(), fetchValidators(), fetchBlock(), fetchCountryData()]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<MainContext.Provider
|
||||
value={{
|
||||
block,
|
||||
countryData,
|
||||
fetchMixnodes,
|
||||
filterMixnodes,
|
||||
gateways,
|
||||
globalError,
|
||||
mixnodes,
|
||||
mode,
|
||||
navState,
|
||||
summaryOverview,
|
||||
toggleMode,
|
||||
updateNavState,
|
||||
validators,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</MainContext.Provider>
|
||||
const state = React.useMemo<State>(
|
||||
() => ({
|
||||
block,
|
||||
countryData,
|
||||
fetchMixnodes,
|
||||
filterMixnodes,
|
||||
gateways,
|
||||
globalError,
|
||||
mixnodes,
|
||||
mode,
|
||||
navState,
|
||||
summaryOverview,
|
||||
toggleMode,
|
||||
updateNavState,
|
||||
validators,
|
||||
}),
|
||||
[block, countryData, gateways, globalError, mixnodes, mode, navState, summaryOverview, validators],
|
||||
);
|
||||
|
||||
return <MainContext.Provider value={state}>{children}</MainContext.Provider>;
|
||||
};
|
||||
|
||||
@@ -7,12 +7,9 @@ import {
|
||||
StatsResponse,
|
||||
StatusResponse,
|
||||
UptimeStoryResponse,
|
||||
} from 'src/typeDefs/explorer-api';
|
||||
} from '../typeDefs/explorer-api';
|
||||
import { Api } from '../api';
|
||||
import {
|
||||
mixNodeResponseItemToMixnodeRowType,
|
||||
MixnodeRowType,
|
||||
} from '../components/MixNodes';
|
||||
import { mixNodeResponseItemToMixnodeRowType, MixnodeRowType } from '../components/MixNodes';
|
||||
|
||||
/**
|
||||
* This context provides the state for a single mixnode by identity key.
|
||||
@@ -41,24 +38,20 @@ interface MixnodeContextProviderProps {
|
||||
* Provides a state context for a mixnode by identity
|
||||
* @param mixNodeIdentityKey The identity key of the mixnode
|
||||
*/
|
||||
export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
mixNodeIdentityKey,
|
||||
children,
|
||||
}) => {
|
||||
const [mixNode, fetchMixnodeById, clearMixnodeById] = useApiState<
|
||||
MixNodeResponseItem | undefined
|
||||
>(mixNodeIdentityKey, Api.fetchMixnodeByID, 'Failed to fetch mixnode by id');
|
||||
export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({ mixNodeIdentityKey, children }) => {
|
||||
const [mixNode, fetchMixnodeById, clearMixnodeById] = useApiState<MixNodeResponseItem | undefined>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchMixnodeByID,
|
||||
'Failed to fetch mixnode by id',
|
||||
);
|
||||
|
||||
const [mixNodeRow, setMixnodeRow] = React.useState<
|
||||
MixnodeRowType | undefined
|
||||
>();
|
||||
const [mixNodeRow, setMixnodeRow] = React.useState<MixnodeRowType | undefined>();
|
||||
|
||||
const [delegations, fetchDelegations, clearDelegations] =
|
||||
useApiState<DelegationsResponse>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchDelegationsById,
|
||||
'Failed to fetch delegations for mixnode',
|
||||
);
|
||||
const [delegations, fetchDelegations, clearDelegations] = useApiState<DelegationsResponse>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchDelegationsById,
|
||||
'Failed to fetch delegations for mixnode',
|
||||
);
|
||||
|
||||
const [status, fetchStatus, clearStatus] = useApiState<StatusResponse>(
|
||||
mixNodeIdentityKey,
|
||||
@@ -72,19 +65,17 @@ export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
'Failed to fetch mixnode stats',
|
||||
);
|
||||
|
||||
const [description, fetchDescription, clearDescription] =
|
||||
useApiState<MixNodeDescriptionResponse>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchMixnodeDescriptionById,
|
||||
'Failed to fetch mixnode description',
|
||||
);
|
||||
const [description, fetchDescription, clearDescription] = useApiState<MixNodeDescriptionResponse>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchMixnodeDescriptionById,
|
||||
'Failed to fetch mixnode description',
|
||||
);
|
||||
|
||||
const [uptimeStory, fetchUptimeHistory, clearUptimeHistory] =
|
||||
useApiState<UptimeStoryResponse>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchUptimeStoryById,
|
||||
'Failed to fetch mixnode uptime history',
|
||||
);
|
||||
const [uptimeStory, fetchUptimeHistory, clearUptimeHistory] = useApiState<UptimeStoryResponse>(
|
||||
mixNodeIdentityKey,
|
||||
Api.fetchUptimeStoryById,
|
||||
'Failed to fetch mixnode uptime history',
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
// when the identity key changes, remove all previous data
|
||||
@@ -102,19 +93,22 @@ export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
return;
|
||||
}
|
||||
setMixnodeRow(mixNodeResponseItemToMixnodeRowType(value.data));
|
||||
Promise.all([
|
||||
fetchDelegations(),
|
||||
fetchStatus(),
|
||||
fetchStats(),
|
||||
fetchDescription(),
|
||||
fetchUptimeHistory(),
|
||||
]);
|
||||
Promise.all([fetchDelegations(), fetchStatus(), fetchStats(), fetchDescription(), fetchUptimeHistory()]);
|
||||
});
|
||||
}, [mixNodeIdentityKey]);
|
||||
|
||||
return (
|
||||
<MixnodeContext.Provider
|
||||
value={{
|
||||
const state = React.useMemo<MixnodeState>(
|
||||
() => ({
|
||||
delegations,
|
||||
mixNode,
|
||||
mixNodeRow,
|
||||
description,
|
||||
stats,
|
||||
status,
|
||||
uptimeStory,
|
||||
}),
|
||||
[
|
||||
{
|
||||
delegations,
|
||||
mixNode,
|
||||
mixNodeRow,
|
||||
@@ -122,11 +116,11 @@ export const MixnodeContextProvider: React.FC<MixnodeContextProviderProps> = ({
|
||||
stats,
|
||||
status,
|
||||
uptimeStory,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</MixnodeContext.Provider>
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
return <MixnodeContext.Provider value={state}>{children}</MixnodeContext.Provider>;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import * as React from 'react';
|
||||
import { BIG_DIPPER } from 'src/api/constants';
|
||||
import { BIG_DIPPER } from '../api/constants';
|
||||
import { OverviewSVG } from '../icons/OverviewSVG';
|
||||
import { NodemapSVG } from '../icons/NodemapSVG';
|
||||
import { NetworkComponentsSVG } from '../icons/NetworksSVG';
|
||||
|
||||
export type navOptionType = {
|
||||
export type NavOptionType = {
|
||||
id: number;
|
||||
isActive?: boolean;
|
||||
url: string;
|
||||
title: string;
|
||||
Icon?: React.ReactNode;
|
||||
nested?: navOptionType[];
|
||||
nested?: NavOptionType[];
|
||||
isExpandedChild?: boolean;
|
||||
};
|
||||
|
||||
export const originalNavOptions: navOptionType[] = [
|
||||
export const originalNavOptions: NavOptionType[] = [
|
||||
{
|
||||
id: 0,
|
||||
isActive: false,
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as React from 'react';
|
||||
import { FallbackProps } from 'react-error-boundary';
|
||||
import { Alert, AlertTitle, Container } from '@mui/material';
|
||||
import { NymThemeProvider } from '@nymproject/mui-theme';
|
||||
import { NymLogo } from '@nymproject/react';
|
||||
|
||||
export const ErrorBoundaryContent: React.FC<FallbackProps> = ({ error }) => (
|
||||
<NymThemeProvider mode="dark">
|
||||
<Container sx={{ py: 4 }}>
|
||||
<NymLogo height="75px" width="75px" />
|
||||
<h1>Oh no! Sorry, something went wrong</h1>
|
||||
<Alert severity="error" data-testid="error-message">
|
||||
<AlertTitle>{error.name}</AlertTitle>
|
||||
{error.message}
|
||||
</Alert>
|
||||
{process.env.NODE_ENV === 'development' && (
|
||||
<Alert severity="info" sx={{ mt: 2 }} data-testid="stack-trace">
|
||||
<AlertTitle>Stack trace</AlertTitle>
|
||||
{error.stack}
|
||||
</Alert>
|
||||
)}
|
||||
</Container>
|
||||
</NymThemeProvider>
|
||||
);
|
||||
Binary file not shown.
Binary file not shown.
@@ -5,27 +5,9 @@ export const GatewaysSVG: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const color = theme.palette.text.primary;
|
||||
return (
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 26 26"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.2 12H22.7"
|
||||
stroke={color}
|
||||
strokeWidth="1.3"
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M1.30005 12H12"
|
||||
stroke={color}
|
||||
strokeWidth="1.3"
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.2 12H22.7" stroke={color} strokeWidth="1.3" strokeMiterlimit="10" strokeLinecap="round" />
|
||||
<path d="M1.30005 12H12" stroke={color} strokeWidth="1.3" strokeMiterlimit="10" strokeLinecap="round" />
|
||||
<path
|
||||
d="M20.1 9.40015L22.7 12.0001L20.1 14.6001"
|
||||
stroke={color}
|
||||
|
||||
@@ -4,21 +4,12 @@ import { useTheme } from '@mui/material/styles';
|
||||
export const LightSwitchSVG: React.FC = () => {
|
||||
const { palette } = useTheme();
|
||||
return (
|
||||
<svg
|
||||
width="26"
|
||||
height="26"
|
||||
viewBox="0 0 26 26"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12C22 6.5 17.5 2 12 2Z"
|
||||
fill={palette.background.default}
|
||||
/>
|
||||
<path
|
||||
d="M12 20C7.6 20 4 16.4 4 12C4 7.6 7.6 4 12 4V20Z"
|
||||
fill={palette.text.primary}
|
||||
/>
|
||||
<path d="M12 20C7.6 20 4 16.4 4 12C4 7.6 7.6 4 12 4V20Z" fill={palette.text.primary} />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,36 +6,14 @@ export const MixnodesSVG: React.FC = () => {
|
||||
const color = theme.palette.text.primary;
|
||||
|
||||
return (
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 26 26"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.0437 13.0291H2.97681" stroke={color} strokeMiterlimit="10" />
|
||||
<path d="M23.0437 2.99512H2.97681" stroke={color} strokeMiterlimit="10" />
|
||||
<path d="M23.0437 23.0625H2.97681" stroke={color} strokeMiterlimit="10" />
|
||||
<path
|
||||
d="M2.97681 23.0621L23.0437 2.99512"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M23.0437 23.0621L2.97681 2.99512"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M13.0103 23.0621L23.0437 2.99512"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M2.97681 2.99512L13.0103 23.0621"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path d="M2.97681 23.0621L23.0437 2.99512" stroke={color} strokeMiterlimit="10" />
|
||||
<path d="M23.0437 23.0621L2.97681 2.99512" stroke={color} strokeMiterlimit="10" />
|
||||
<path d="M13.0103 23.0621L23.0437 2.99512" stroke={color} strokeMiterlimit="10" />
|
||||
<path d="M2.97681 2.99512L13.0103 23.0621" stroke={color} strokeMiterlimit="10" />
|
||||
<path
|
||||
d="M13.0099 13.0289L23.0437 23.0621L13.0099 2.99512L2.97681 23.0621L13.0099 2.99512"
|
||||
stroke={color}
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export const MobileDrawerClose: React.FC = (props) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="-3 -5 24 24"
|
||||
width="25"
|
||||
height="25"
|
||||
{...props}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -5 24 24" width="25" height="25" {...props}>
|
||||
<path
|
||||
d="M0 12H13V10H0V12ZM0 7H10V5H0V7ZM0 0V2H13V0H0ZM18 9.59L14.42 6L18 2.41L16.59 1L11.59 6L16.59 11L18 9.59Z"
|
||||
fill="#F2F2F2"
|
||||
|
||||
@@ -5,28 +5,14 @@ export const NetworkComponentsSVG: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const color = theme.palette.nym.networkExplorer.nav.text;
|
||||
return (
|
||||
<svg
|
||||
width="25"
|
||||
height="25"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg width="25" height="25" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M17.2 10.5V4.40002L12 1.40002L6.8 4.40002V10.5L12 13.5L17.2 10.5Z"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M12 19.6V13.5L6.8 10.5L1.5 13.5V19.6L6.8 22.6L12 19.6Z"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M22.5 19.6V13.5L17.2 10.5L12 13.5V19.6L17.2 22.6L22.5 19.6Z"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path d="M12 19.6V13.5L6.8 10.5L1.5 13.5V19.6L6.8 22.6L12 19.6Z" stroke={color} strokeMiterlimit="10" />
|
||||
<path d="M22.5 19.6V13.5L17.2 10.5L12 13.5V19.6L17.2 22.6L22.5 19.6Z" stroke={color} strokeMiterlimit="10" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,13 +5,7 @@ export const NodemapSVG: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const color = theme.palette.nym.networkExplorer.nav.text;
|
||||
return (
|
||||
<svg
|
||||
width="25"
|
||||
height="25"
|
||||
viewBox="0 0 19 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg width="25" height="25" viewBox="0 0 19 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M1 9.6999C1 5.0999 4.7 1.3999 9.3 1.3999C13.9 1.3999 17.6 5.0999 17.6 9.6999C17.6 14.2999 9.3 21.5999 9.3 21.5999C9.3 21.5999 1 14.2999 1 9.6999Z"
|
||||
stroke={color}
|
||||
@@ -22,12 +16,7 @@ export const NodemapSVG: React.FC = () => {
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M1.5 22.5999H17.1"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path d="M1.5 22.5999H17.1" stroke={color} strokeMiterlimit="10" strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export const NymLogoSVG: React.FC = (props) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 5389.9 5389.9"
|
||||
width="40px"
|
||||
height="40px"
|
||||
{...props}
|
||||
>
|
||||
<circle cx={2695} cy={2695} r={2585} fill="#121726" />
|
||||
<linearGradient
|
||||
id="nym_logo_svg__a"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1={0}
|
||||
y1={8058.165}
|
||||
x2={5390}
|
||||
y2={8058.165}
|
||||
gradientTransform="matrix(1 0 0 -1 0 10753.165)"
|
||||
>
|
||||
<stop offset={0} stopColor="#f77846" />
|
||||
<stop offset={1} stopColor="#ed3572" />
|
||||
</linearGradient>
|
||||
<path
|
||||
d="M2695 5390c-182.8 0-365.5-18.4-543-54.8-173.1-35.4-343.3-88.3-506-157.1-159.7-67.6-313.7-151.2-457.8-248.5-142.7-96.4-276.8-207.1-398.8-329-121.9-121.9-232.6-256.1-329-398.8-97.4-144-181-298-248.6-457.8-68.8-162.6-121.6-332.9-157-506C18.4 3060.5 0 2877.8 0 2695s18.4-365.5 54.8-543c35.4-173.1 88.3-343.3 157.1-506 67.6-159.7 151.2-313.7 248.5-457.8 96.4-142.7 207.1-276.8 329-398.8s256.1-232.6 398.8-329c144.1-97.3 298.1-180.9 457.8-248.5 162.7-68.8 332.9-121.7 506-157.1C2329.5 18.4 2512.2 0 2695 0s365.5 18.4 543 54.8c173.1 35.4 343.3 88.3 506 157.1 159.7 67.6 313.7 151.2 457.8 248.5 142.7 96.4 276.8 207.1 398.8 329 121.9 121.9 232.6 256.1 329 398.8 97.3 144.1 180.9 298.1 248.5 457.8 68.8 162.7 121.7 332.9 157.1 506 36.3 177.5 54.8 360.2 54.8 543s-18.4 365.5-54.8 543c-35.4 173.1-88.3 343.3-157.1 506-67.6 159.7-151.2 313.7-248.5 457.8-96.4 142.7-207.1 276.8-329 398.8-121.9 121.9-256.1 232.6-398.8 329-144.1 97.3-298.1 180.9-457.8 248.5-162.7 68.8-332.9 121.7-506 157.1-177.5 36.4-360.2 54.8-543 54.8zm0-5170c-168 0-335.9 16.9-498.9 50.3-158.9 32.5-315.1 81-464.4 144.2-146.6 62-288.1 138.8-420.4 228.2C1180.2 731.3 1057 833 944.9 945c-112 112-213.7 235.3-302.3 366.4-89.4 132.3-166.2 273.7-228.2 420.4-63.2 149.3-111.7 305.6-144.2 464.4C236.9 2359.1 220 2527 220 2695s16.9 335.9 50.3 498.9c32.5 158.9 81 315.1 144.2 464.4 62 146.6 138.8 288.1 228.2 420.4C731.3 4209.8 833 4333 945 4445.1c112 112 235.3 213.7 366.4 302.3 132.3 89.4 273.7 166.2 420.4 228.2 149.3 63.2 305.6 111.7 464.4 144.2 163.1 33.4 330.9 50.3 498.9 50.3s335.9-16.9 498.9-50.3c158.9-32.5 315.1-81 464.4-144.2 146.6-62 288.1-138.8 420.4-228.2 131.1-88.6 254.3-190.3 366.4-302.3 112-112 213.7-235.3 302.3-366.4 89.4-132.3 166.2-273.7 228.2-420.4 63.2-149.3 111.7-305.6 144.2-464.4 33.4-163.1 50.3-330.9 50.3-498.9s-16.9-335.9-50.3-498.9c-32.5-158.9-81-315.1-144.2-464.4-62-146.6-138.8-288.1-228.2-420.4-88.6-131.1-190.3-254.3-302.3-366.4-112-112-235.3-213.7-366.4-302.3-132.3-89.4-273.7-166.2-420.4-228.2-149.3-63.2-305.6-111.7-464.4-144.2-163.1-33.3-331-50.2-499-50.2z"
|
||||
fill="url(#nym_logo_svg__a)"
|
||||
/>
|
||||
<path
|
||||
d="M1958.5 3160.4h-269.6l-735.8-725.3v725.3H734.6v-930.9h276.2l735.8 725.1v-725.1h211.9v930.9zm2420.4-930.9l-335.7 330.9-335.7-330.9h-276.2v930.9h218.4v-725.3l345.4 340.6c26.7 26.3 69.6 26.3 96.3 0l345.4-340.6v725.3h218.4v-930.9h-276.3zm-1789.8 485.9v445h218.4v-445l502.7-485.9H3034l-335.9 330.9-335.7-330.9h-276.2l502.9 485.9z"
|
||||
fill="#fff"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
@@ -6,37 +6,11 @@ export const OverviewSVG: React.FC = () => {
|
||||
const color = theme.palette.nym.networkExplorer.nav.text;
|
||||
|
||||
return (
|
||||
<svg
|
||||
width="25"
|
||||
height="25"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M1.4 21.6H22.6"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M14.1 2.40002H9.9V21.5H14.1V2.40002Z"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M20.8 6.59998H16.6V21.5H20.8V6.59998Z"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M7.4 11.8H3.2V21.6H7.4V11.8Z"
|
||||
stroke={color}
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<svg width="25" height="25" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.4 21.6H22.6" stroke={color} strokeMiterlimit="10" strokeLinecap="round" />
|
||||
<path d="M14.1 2.40002H9.9V21.5H14.1V2.40002Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" />
|
||||
<path d="M20.8 6.59998H16.6V21.5H20.8V6.59998Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" />
|
||||
<path d="M7.4 11.8H3.2V21.6H7.4V11.8Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,13 +5,7 @@ export const ValidatorsSVG: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const color = theme.palette.text.primary;
|
||||
return (
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 26 26"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clipPath="url(#clip0)">
|
||||
<path
|
||||
d="M18.2001 18.4V19.7001C18.2001 21.4001 16.9 22.7001 15.2 22.7001H4.30005C2.60005 22.7001 1.30005 21.4001 1.30005 19.7001V4.30005C1.30005 2.60005 2.60005 1.30005 4.30005 1.30005H15.1C16.8 1.30005 18.1 2.60005 18.1 4.30005V5.60005V18.4H18.2001Z"
|
||||
|
||||
@@ -6,10 +6,7 @@ interface DiscordIconProps {
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export const DiscordIcon: React.FC<DiscordIconProps> = ({
|
||||
size,
|
||||
color: colorProp,
|
||||
}) => {
|
||||
export const DiscordIcon: React.FC<DiscordIconProps> = ({ size, color: colorProp }) => {
|
||||
const theme = useTheme();
|
||||
const color = colorProp || theme.palette.text.primary;
|
||||
return (
|
||||
|
||||
@@ -6,10 +6,7 @@ interface GitHubIconProps {
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export const GitHubIcon: React.FC<GitHubIconProps> = ({
|
||||
size,
|
||||
color: colorProp,
|
||||
}) => {
|
||||
export const GitHubIcon: React.FC<GitHubIconProps> = ({ size, color: colorProp }) => {
|
||||
const theme = useTheme();
|
||||
const color = colorProp || theme.palette.text.primary;
|
||||
return (
|
||||
|
||||
@@ -6,10 +6,7 @@ interface TelegramIconProps {
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export const TelegramIcon: React.FC<TelegramIconProps> = ({
|
||||
size,
|
||||
color: colorProp,
|
||||
}) => {
|
||||
export const TelegramIcon: React.FC<TelegramIconProps> = ({ size, color: colorProp }) => {
|
||||
const theme = useTheme();
|
||||
const color = colorProp || theme.palette.text.primary;
|
||||
return (
|
||||
|
||||
@@ -6,10 +6,7 @@ interface TwitterIconProps {
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export const TwitterIcon: React.FC<TwitterIconProps> = ({
|
||||
size,
|
||||
color: colorProp,
|
||||
}) => {
|
||||
export const TwitterIcon: React.FC<TwitterIconProps> = ({ size, color: colorProp }) => {
|
||||
const theme = useTheme();
|
||||
const color = colorProp || theme.palette.text.primary;
|
||||
return (
|
||||
|
||||
+11
-7
@@ -1,18 +1,22 @@
|
||||
import * as React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { App } from './App';
|
||||
import { MainContextProvider } from './context/main';
|
||||
import './styles.css';
|
||||
import { NetworkExplorerThemeProvider } from './theme';
|
||||
import { ErrorBoundaryContent } from './errors/ErrorBoundaryContent';
|
||||
|
||||
ReactDOM.render(
|
||||
<MainContextProvider>
|
||||
<NetworkExplorerThemeProvider>
|
||||
<Router>
|
||||
<App />
|
||||
</Router>
|
||||
</NetworkExplorerThemeProvider>
|
||||
</MainContextProvider>,
|
||||
<ErrorBoundary FallbackComponent={ErrorBoundaryContent}>
|
||||
<MainContextProvider>
|
||||
<NetworkExplorerThemeProvider>
|
||||
<Router>
|
||||
<App />
|
||||
</Router>
|
||||
</NetworkExplorerThemeProvider>
|
||||
</MainContextProvider>
|
||||
</ErrorBoundary>,
|
||||
document.getElementById('app'),
|
||||
);
|
||||
|
||||
@@ -2,8 +2,8 @@ import * as React from 'react';
|
||||
import { Box, Button, Grid, Paper, Typography } from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { NymLogoSVG } from 'src/icons/NymLogoSVG';
|
||||
import { NymLogo } from '@nymproject/react';
|
||||
import { useMainContext } from '../../context/main';
|
||||
|
||||
export const Page404: React.FC = () => {
|
||||
const history = useHistory();
|
||||
@@ -21,18 +21,13 @@ export const Page404: React.FC = () => {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-evenly',
|
||||
flexDirection: 'column',
|
||||
background:
|
||||
mode === 'dark'
|
||||
? theme.palette.secondary.dark
|
||||
: theme.palette.primary.light,
|
||||
background: mode === 'dark' ? theme.palette.secondary.dark : theme.palette.primary.light,
|
||||
borderRadius: 10,
|
||||
}}
|
||||
>
|
||||
<NymLogoSVG />
|
||||
<NymLogo height="40px" width="40px" />
|
||||
<Typography variant="h2">Oh No!</Typography>
|
||||
<Typography variant="body1">
|
||||
It looks like you might be lost.
|
||||
</Typography>
|
||||
<Typography variant="body1">It looks like you might be lost.</Typography>
|
||||
<Typography variant="body1" textAlign="center">
|
||||
Please try the link again or navigate back to{' '}
|
||||
</Typography>
|
||||
|
||||
@@ -2,22 +2,18 @@ import * as React from 'react';
|
||||
import { Button, Card, Grid, Typography } from '@mui/material';
|
||||
import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid';
|
||||
import { SelectChangeEvent } from '@mui/material/Select';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { gatewayToGridRow } from 'src/components/Gateways';
|
||||
import { GatewayResponse } from 'src/typeDefs/explorer-api';
|
||||
import { TableToolbar } from 'src/components/TableToolbar';
|
||||
import { CustomColumnHeading } from 'src/components/CustomColumnHeading';
|
||||
import { Title } from 'src/components/Title';
|
||||
import {
|
||||
cellStyles,
|
||||
UniversalDataGrid,
|
||||
} from 'src/components/Universal-DataGrid';
|
||||
import { useMainContext } from '../../context/main';
|
||||
import { gatewayToGridRow } from '../../components/Gateways';
|
||||
import { GatewayResponse } from '../../typeDefs/explorer-api';
|
||||
import { TableToolbar } from '../../components/TableToolbar';
|
||||
import { CustomColumnHeading } from '../../components/CustomColumnHeading';
|
||||
import { Title } from '../../components/Title';
|
||||
import { cellStyles, UniversalDataGrid } from '../../components/Universal-DataGrid';
|
||||
import { currencyToString } from '../../utils/currency';
|
||||
|
||||
export const PageGateways: React.FC = () => {
|
||||
const { gateways } = useMainContext();
|
||||
const [filteredGateways, setFilteredGateways] =
|
||||
React.useState<GatewayResponse>([]);
|
||||
const [filteredGateways, setFilteredGateways] = React.useState<GatewayResponse>([]);
|
||||
const [pageSize, setPageSize] = React.useState<string>('50');
|
||||
const [searchTerm, setSearchTerm] = React.useState<string>('');
|
||||
|
||||
@@ -137,11 +133,7 @@ export const PageGateways: React.FC = () => {
|
||||
pageSize={pageSize}
|
||||
searchTerm={searchTerm}
|
||||
/>
|
||||
<UniversalDataGrid
|
||||
rows={gatewayToGridRow(filteredGateways)}
|
||||
columns={columns}
|
||||
pageSize={pageSize}
|
||||
/>
|
||||
<UniversalDataGrid rows={gatewayToGridRow(filteredGateways)} columns={columns} pageSize={pageSize} />
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Alert,
|
||||
AlertTitle,
|
||||
Box,
|
||||
CircularProgress,
|
||||
Grid,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { ColumnsType, DetailTable } from 'src/components/DetailTable';
|
||||
import { Alert, AlertTitle, Box, CircularProgress, Grid, Typography } from '@mui/material';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { BondBreakdownTable } from 'src/components/MixNodes/BondBreakdown';
|
||||
import { ComponentError } from 'src/components/ComponentError';
|
||||
import { ContentCard } from 'src/components/ContentCard';
|
||||
import { TwoColSmallTable } from 'src/components/TwoColSmallTable';
|
||||
import { UptimeChart } from 'src/components/UptimeChart';
|
||||
import { WorldMap } from 'src/components/WorldMap';
|
||||
import { ColumnsType, DetailTable } from '../../components/DetailTable';
|
||||
import { BondBreakdownTable } from '../../components/MixNodes/BondBreakdown';
|
||||
import { ComponentError } from '../../components/ComponentError';
|
||||
import { ContentCard } from '../../components/ContentCard';
|
||||
import { TwoColSmallTable } from '../../components/TwoColSmallTable';
|
||||
import { UptimeChart } from '../../components/UptimeChart';
|
||||
import { WorldMap } from '../../components/WorldMap';
|
||||
import { MixNodeDetailSection } from '../../components/MixNodes/DetailSection';
|
||||
import {
|
||||
MixnodeContextProvider,
|
||||
useMixnodeContext,
|
||||
} from '../../context/mixnode';
|
||||
import { MixnodeContextProvider, useMixnodeContext } from '../../context/mixnode';
|
||||
import { Title } from '../../components/Title';
|
||||
|
||||
const columns: ColumnsType[] = [
|
||||
@@ -69,21 +59,111 @@ const columns: ColumnsType[] = [
|
||||
];
|
||||
|
||||
/**
|
||||
* Wrapper component that adds the mixnode content based on the `id` in the address URL
|
||||
* Shows mix node details
|
||||
*/
|
||||
export const PageMixnodeDetail: React.FC = () => {
|
||||
const { id } = useParams<{ id: string | undefined }>();
|
||||
|
||||
if (!id) {
|
||||
return (
|
||||
<Alert severity="error">Oh no! No mixnode identity key specified</Alert>
|
||||
);
|
||||
}
|
||||
const PageMixnodeDetailWithState: React.FC = () => {
|
||||
const { mixNode, mixNodeRow, description, stats, status, uptimeStory } = useMixnodeContext();
|
||||
|
||||
return (
|
||||
<MixnodeContextProvider mixNodeIdentityKey={id}>
|
||||
<PageMixnodeDetailGuard />
|
||||
</MixnodeContextProvider>
|
||||
<Box component="main">
|
||||
<Title text="Mixnode Detail" />
|
||||
|
||||
<Grid container spacing={2} mt={1} mb={6}>
|
||||
<Grid item xs={12}>
|
||||
{mixNodeRow && description?.data && (
|
||||
<MixNodeDetailSection mixNodeRow={mixNodeRow} mixnodeDescription={description.data} />
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
<DetailTable columnsData={columns} tableName="Mixnode detail table" rows={mixNodeRow ? [mixNodeRow] : []} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={2} mt={0}>
|
||||
<Grid item xs={12}>
|
||||
<ContentCard title="Bond Breakdown">
|
||||
<BondBreakdownTable />
|
||||
</ContentCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={2} mt={0}>
|
||||
<Grid item xs={12} md={4}>
|
||||
<ContentCard title="Mixnode Stats">
|
||||
{stats && (
|
||||
<>
|
||||
{stats.error && <ComponentError text="There was a problem retrieving this nodes stats." />}
|
||||
<TwoColSmallTable
|
||||
loading={stats.isLoading}
|
||||
error={stats?.error?.message}
|
||||
title="Since startup"
|
||||
keys={['Received', 'Sent', 'Explicitly dropped']}
|
||||
values={[
|
||||
stats?.data?.packets_received_since_startup || 0,
|
||||
stats?.data?.packets_sent_since_startup || 0,
|
||||
stats?.data?.packets_explicitly_dropped_since_startup || 0,
|
||||
]}
|
||||
/>
|
||||
<TwoColSmallTable
|
||||
loading={stats.isLoading}
|
||||
error={stats?.error?.message}
|
||||
title="Since last update"
|
||||
keys={['Received', 'Sent', 'Explicitly dropped']}
|
||||
values={[
|
||||
stats?.data?.packets_received_since_last_update || 0,
|
||||
stats?.data?.packets_sent_since_last_update || 0,
|
||||
stats?.data?.packets_explicitly_dropped_since_last_update || 0,
|
||||
]}
|
||||
marginBottom
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{!stats && <Typography>No stats information</Typography>}
|
||||
</ContentCard>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={8}>
|
||||
{uptimeStory && (
|
||||
<ContentCard title="Uptime story">
|
||||
{uptimeStory.error && <ComponentError text="There was a problem retrieving uptime history." />}
|
||||
<UptimeChart loading={uptimeStory.isLoading} xLabel="date" yLabel="uptime" uptimeStory={uptimeStory} />
|
||||
</ContentCard>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={2} mt={0}>
|
||||
<Grid item xs={12} md={4}>
|
||||
{status && (
|
||||
<ContentCard title="Mixnode Status">
|
||||
{status.error && <ComponentError text="There was a problem retrieving port information" />}
|
||||
<TwoColSmallTable
|
||||
loading={status.isLoading}
|
||||
error={status?.error?.message}
|
||||
keys={['Mix port', 'Verloc port', 'HTTP port']}
|
||||
values={[1789, 1790, 8000].map((each) => each)}
|
||||
icons={(status?.data?.ports && Object.values(status.data.ports)) || [false, false, false]}
|
||||
/>
|
||||
</ContentCard>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12} md={8}>
|
||||
{mixNode && (
|
||||
<ContentCard title="Location">
|
||||
{mixNode?.error && <ComponentError text="There was a problem retrieving this mixnode location" />}
|
||||
{mixNode.data && mixNode?.data?.location && (
|
||||
<WorldMap
|
||||
loading={mixNode.isLoading}
|
||||
userLocation={[mixNode?.data?.location?.lng, mixNode?.data?.location?.lat]}
|
||||
/>
|
||||
)}
|
||||
</ContentCard>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -99,6 +179,7 @@ const PageMixnodeDetailGuard: React.FC = () => {
|
||||
}
|
||||
|
||||
if (mixNode?.error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(mixNode?.error);
|
||||
return (
|
||||
<Alert severity="error">
|
||||
@@ -121,141 +202,18 @@ const PageMixnodeDetailGuard: React.FC = () => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows mix node details
|
||||
* Wrapper component that adds the mixnode content based on the `id` in the address URL
|
||||
*/
|
||||
const PageMixnodeDetailWithState: React.FC = () => {
|
||||
const { mixNode, mixNodeRow, description, stats, status, uptimeStory } =
|
||||
useMixnodeContext();
|
||||
export const PageMixnodeDetail: React.FC = () => {
|
||||
const { id } = useParams<{ id: string | undefined }>();
|
||||
|
||||
if (!id) {
|
||||
return <Alert severity="error">Oh no! No mixnode identity key specified</Alert>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box component="main">
|
||||
<Title text="Mixnode Detail" />
|
||||
|
||||
<Grid container spacing={2} mt={1} mb={6}>
|
||||
<Grid item xs={12}>
|
||||
{mixNodeRow && description?.data && (
|
||||
<MixNodeDetailSection
|
||||
mixNodeRow={mixNodeRow}
|
||||
mixnodeDescription={description.data}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
<DetailTable
|
||||
columnsData={columns}
|
||||
tableName="Mixnode detail table"
|
||||
rows={mixNodeRow ? [mixNodeRow] : []}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={2} mt={0}>
|
||||
<Grid item xs={12}>
|
||||
<ContentCard title="Bond Breakdown">
|
||||
<BondBreakdownTable />
|
||||
</ContentCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={2} mt={0}>
|
||||
<Grid item xs={12} md={4}>
|
||||
<ContentCard title="Mixnode Stats">
|
||||
{stats && (
|
||||
<>
|
||||
{stats.error && (
|
||||
<ComponentError text="There was a problem retrieving this nodes stats." />
|
||||
)}
|
||||
<TwoColSmallTable
|
||||
loading={stats.isLoading}
|
||||
error={stats?.error?.message}
|
||||
title="Since startup"
|
||||
keys={['Received', 'Sent', 'Explicitly dropped']}
|
||||
values={[
|
||||
stats?.data?.packets_received_since_startup || 0,
|
||||
stats?.data?.packets_sent_since_startup || 0,
|
||||
stats?.data?.packets_explicitly_dropped_since_startup || 0,
|
||||
]}
|
||||
/>
|
||||
<TwoColSmallTable
|
||||
loading={stats.isLoading}
|
||||
error={stats?.error?.message}
|
||||
title="Since last update"
|
||||
keys={['Received', 'Sent', 'Explicitly dropped']}
|
||||
values={[
|
||||
stats?.data?.packets_received_since_last_update || 0,
|
||||
stats?.data?.packets_sent_since_last_update || 0,
|
||||
stats?.data?.packets_explicitly_dropped_since_last_update ||
|
||||
0,
|
||||
]}
|
||||
marginBottom
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{!stats && <Typography>No stats information</Typography>}
|
||||
</ContentCard>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={8}>
|
||||
{uptimeStory && (
|
||||
<ContentCard title="Uptime story">
|
||||
{uptimeStory.error && (
|
||||
<ComponentError text="There was a problem retrieving uptime history." />
|
||||
)}
|
||||
<UptimeChart
|
||||
loading={uptimeStory.isLoading}
|
||||
xLabel="date"
|
||||
yLabel="uptime"
|
||||
uptimeStory={uptimeStory}
|
||||
/>
|
||||
</ContentCard>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={2} mt={0}>
|
||||
<Grid item xs={12} md={4}>
|
||||
{status && (
|
||||
<ContentCard title="Mixnode Status">
|
||||
{status.error && (
|
||||
<ComponentError text="There was a problem retrieving port information" />
|
||||
)}
|
||||
<TwoColSmallTable
|
||||
loading={status.isLoading}
|
||||
error={status?.error?.message}
|
||||
keys={['Mix port', 'Verloc port', 'HTTP port']}
|
||||
values={[1789, 1790, 8000].map((each) => each)}
|
||||
icons={
|
||||
(status?.data?.ports && Object.values(status.data.ports)) || [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ContentCard>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12} md={8}>
|
||||
{mixNode && (
|
||||
<ContentCard title="Location">
|
||||
{mixNode?.error && (
|
||||
<ComponentError text="There was a problem retrieving this mixnode location" />
|
||||
)}
|
||||
{mixNode.data && mixNode?.data?.location && (
|
||||
<WorldMap
|
||||
loading={mixNode.isLoading}
|
||||
userLocation={[
|
||||
mixNode?.data?.location?.lng,
|
||||
mixNode?.data?.location?.lat,
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</ContentCard>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
<MixnodeContextProvider mixNodeIdentityKey={id}>
|
||||
<PageMixnodeDetailGuard />
|
||||
</MixnodeContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,32 +3,40 @@ import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid';
|
||||
import { Button, Card, Grid, Link as MuiLink } from '@mui/material';
|
||||
import { Link as RRDLink, useParams } from 'react-router-dom';
|
||||
import { SelectChangeEvent } from '@mui/material/Select';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { MixnodeRowType, mixnodeToGridRow } from 'src/components/MixNodes';
|
||||
import { TableToolbar } from 'src/components/TableToolbar';
|
||||
import {
|
||||
MixNodeResponse,
|
||||
MixnodeStatusWithAll,
|
||||
toMixnodeStatus,
|
||||
} from 'src/typeDefs/explorer-api';
|
||||
import { BIG_DIPPER } from 'src/api/constants';
|
||||
import { CustomColumnHeading } from 'src/components/CustomColumnHeading';
|
||||
import { Title } from 'src/components/Title';
|
||||
import {
|
||||
cellStyles,
|
||||
UniversalDataGrid,
|
||||
} from 'src/components/Universal-DataGrid';
|
||||
import { SxProps } from '@mui/system';
|
||||
import { Theme, useTheme } from '@mui/material/styles';
|
||||
import { useHistory } from 'react-router';
|
||||
import { CopyToClipboard } from '@nymproject/react';
|
||||
import { useMainContext } from '../../context/main';
|
||||
import { MixnodeRowType, mixnodeToGridRow } from '../../components/MixNodes';
|
||||
import { TableToolbar } from '../../components/TableToolbar';
|
||||
import { MixNodeResponse, MixnodeStatusWithAll, toMixnodeStatus } from '../../typeDefs/explorer-api';
|
||||
import { BIG_DIPPER } from '../../api/constants';
|
||||
import { CustomColumnHeading } from '../../components/CustomColumnHeading';
|
||||
import { Title } from '../../components/Title';
|
||||
import { cellStyles, UniversalDataGrid } from '../../components/Universal-DataGrid';
|
||||
import { currencyToString } from '../../utils/currency';
|
||||
import { getMixNodeStatusColor } from '../../components/MixNodes/Status';
|
||||
import { MixNodeStatusDropdown } from '../../components/MixNodes/StatusDropdown';
|
||||
|
||||
const getCellFontStyle = (theme: Theme, row: MixnodeRowType) => {
|
||||
const color = getMixNodeStatusColor(theme, row.status);
|
||||
return {
|
||||
fontWeight: 400,
|
||||
fontSize: 12,
|
||||
color,
|
||||
};
|
||||
};
|
||||
|
||||
const getCellStyles = (theme: Theme, row: MixnodeRowType): SxProps => ({
|
||||
...cellStyles,
|
||||
// TODO: should these be here, or change in `cellStyles`??
|
||||
...getCellFontStyle(theme, row),
|
||||
});
|
||||
|
||||
export const PageMixnodes: React.FC = () => {
|
||||
const { mixnodes, fetchMixnodes } = useMainContext();
|
||||
const [filteredMixnodes, setFilteredMixnodes] =
|
||||
React.useState<MixNodeResponse>([]);
|
||||
const [filteredMixnodes, setFilteredMixnodes] = React.useState<MixNodeResponse>([]);
|
||||
const [pageSize, setPageSize] = React.useState<string>('10');
|
||||
const [searchTerm, setSearchTerm] = React.useState<string>('');
|
||||
const theme = useTheme();
|
||||
@@ -99,14 +107,21 @@ export const PageMixnodes: React.FC = () => {
|
||||
width: 380,
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={getCellStyles(theme, params.row)}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnode/${params.value}`}
|
||||
data-testid="identity-link"
|
||||
>
|
||||
{params.value}
|
||||
</MuiLink>
|
||||
<>
|
||||
<CopyToClipboard
|
||||
sx={{ ...getCellFontStyle(theme, params.row), mr: 1 }}
|
||||
value={params.value}
|
||||
tooltip={`Copy identity key ${params.value} to clipboard`}
|
||||
/>
|
||||
<MuiLink
|
||||
sx={getCellStyles(theme, params.row)}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnode/${params.value}`}
|
||||
data-testid="identity-link"
|
||||
>
|
||||
{params.value}
|
||||
</MuiLink>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -217,11 +232,7 @@ export const PageMixnodes: React.FC = () => {
|
||||
>
|
||||
<TableToolbar
|
||||
childrenBefore={
|
||||
<MixNodeStatusDropdown
|
||||
sx={{ mr: 2 }}
|
||||
status={status}
|
||||
onSelectionChanged={handleMixnodeStatusChanged}
|
||||
/>
|
||||
<MixNodeStatusDropdown sx={{ mr: 2 }} status={status} onSelectionChanged={handleMixnodeStatusChanged} />
|
||||
}
|
||||
onChangeSearch={handleSearch}
|
||||
onChangePageSize={handlePageSize}
|
||||
@@ -241,14 +252,3 @@ export const PageMixnodes: React.FC = () => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getCellStyles = (theme: Theme, row: MixnodeRowType): SxProps => {
|
||||
const color = getMixNodeStatusColor(theme, row.status);
|
||||
return {
|
||||
...cellStyles,
|
||||
// TODO: should these be here, or change in `cellStyles`??
|
||||
fontWeight: 400,
|
||||
fontSize: 12,
|
||||
color,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,31 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
CircularProgress,
|
||||
Grid,
|
||||
SelectChangeEvent,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { Alert, Box, CircularProgress, Grid, SelectChangeEvent, Typography } from '@mui/material';
|
||||
import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid';
|
||||
import { ContentCard } from 'src/components/ContentCard';
|
||||
import { CustomColumnHeading } from 'src/components/CustomColumnHeading';
|
||||
import { TableToolbar } from 'src/components/TableToolbar';
|
||||
import { Title } from 'src/components/Title';
|
||||
import {
|
||||
UniversalDataGrid,
|
||||
cellStyles,
|
||||
} from 'src/components/Universal-DataGrid';
|
||||
import { WorldMap } from 'src/components/WorldMap';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { CountryDataRowType, countryDataToGridRow } from 'src/utils';
|
||||
import { ContentCard } from '../../components/ContentCard';
|
||||
import { CustomColumnHeading } from '../../components/CustomColumnHeading';
|
||||
import { TableToolbar } from '../../components/TableToolbar';
|
||||
import { Title } from '../../components/Title';
|
||||
import { UniversalDataGrid, cellStyles } from '../../components/Universal-DataGrid';
|
||||
import { WorldMap } from '../../components/WorldMap';
|
||||
import { useMainContext } from '../../context/main';
|
||||
import { CountryDataRowType, countryDataToGridRow } from '../../utils';
|
||||
|
||||
export const PageMixnodesMap: React.FC = () => {
|
||||
const { countryData } = useMainContext();
|
||||
const [pageSize, setPageSize] = React.useState<string>('10');
|
||||
const [formattedCountries, setFormattedCountries] = React.useState<
|
||||
CountryDataRowType[]
|
||||
>([]);
|
||||
const [formattedCountries, setFormattedCountries] = React.useState<CountryDataRowType[]>([]);
|
||||
const [searchTerm, setSearchTerm] = React.useState<string>('');
|
||||
|
||||
const handleSearch = (str: string) => {
|
||||
@@ -51,9 +39,7 @@ export const PageMixnodesMap: React.FC = () => {
|
||||
},
|
||||
{
|
||||
field: 'nodes',
|
||||
renderHeader: () => (
|
||||
<CustomColumnHeading headingTitle="Number of Nodes" />
|
||||
),
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Number of Nodes" />,
|
||||
flex: 1,
|
||||
headerAlign: 'left',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
@@ -79,15 +65,11 @@ export const PageMixnodesMap: React.FC = () => {
|
||||
|
||||
React.useEffect(() => {
|
||||
if (countryData?.data && searchTerm === '') {
|
||||
setFormattedCountries(
|
||||
countryDataToGridRow(Object.values(countryData.data)),
|
||||
);
|
||||
setFormattedCountries(countryDataToGridRow(Object.values(countryData.data)));
|
||||
} else if (countryData?.data !== undefined && searchTerm !== '') {
|
||||
const formatted = countryDataToGridRow(Object.values(countryData?.data));
|
||||
const filtered = formatted.filter(
|
||||
(m) =>
|
||||
m?.countryName?.toLowerCase().includes(searchTerm) ||
|
||||
m?.ISO3?.toLowerCase().includes(searchTerm),
|
||||
(m) => m?.countryName?.toLowerCase().includes(searchTerm) || m?.ISO3?.toLowerCase().includes(searchTerm),
|
||||
);
|
||||
if (filtered) {
|
||||
setFormattedCountries(filtered);
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Grid, Link, Typography } from '@mui/material';
|
||||
import { WorldMap } from 'src/components/WorldMap';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { formatNumber } from 'src/utils';
|
||||
import { BIG_DIPPER } from 'src/api/constants';
|
||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||
import { ValidatorsSVG } from 'src/icons/ValidatorsSVG';
|
||||
import { GatewaysSVG } from 'src/icons/GatewaysSVG';
|
||||
import { MixnodesSVG } from 'src/icons/MixnodesSVG';
|
||||
import { Title } from 'src/components/Title';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { WorldMap } from '../../components/WorldMap';
|
||||
import { useMainContext } from '../../context/main';
|
||||
import { formatNumber } from '../../utils';
|
||||
import { BIG_DIPPER } from '../../api/constants';
|
||||
import { ValidatorsSVG } from '../../icons/ValidatorsSVG';
|
||||
import { GatewaysSVG } from '../../icons/GatewaysSVG';
|
||||
import { MixnodesSVG } from '../../icons/MixnodesSVG';
|
||||
import { Title } from '../../components/Title';
|
||||
import { ContentCard } from '../../components/ContentCard';
|
||||
import { StatsCard } from '../../components/StatsCard';
|
||||
import { Icons } from '../../components/Icons';
|
||||
@@ -18,120 +18,102 @@ import { Icons } from '../../components/Icons';
|
||||
export const PageOverview: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const history = useHistory();
|
||||
const { summaryOverview, gateways, validators, block, countryData } =
|
||||
useMainContext();
|
||||
const { summaryOverview, gateways, validators, block, countryData } = useMainContext();
|
||||
return (
|
||||
<>
|
||||
<Box component="main" sx={{ flexGrow: 1 }}>
|
||||
<Grid>
|
||||
<Grid item paddingBottom={3}>
|
||||
<Title text="Overview" />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid container spacing={3}>
|
||||
{summaryOverview && (
|
||||
<>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() =>
|
||||
history.push('/network-components/mixnodes')
|
||||
}
|
||||
title="Mixnodes"
|
||||
icon={<MixnodesSVG />}
|
||||
count={summaryOverview.data?.mixnodes.count || ''}
|
||||
errorMsg={summaryOverview?.error}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() =>
|
||||
history.push('/network-components/mixnodes/active')
|
||||
}
|
||||
title="Active nodes"
|
||||
icon={<Icons.mixnodes.status.active />}
|
||||
color={
|
||||
theme.palette.nym.networkExplorer.mixnodes.status.active
|
||||
}
|
||||
count={summaryOverview.data?.mixnodes.activeset.active}
|
||||
errorMsg={summaryOverview?.error}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() =>
|
||||
history.push('/network-components/mixnodes/standby')
|
||||
}
|
||||
title="Standby nodes"
|
||||
color={
|
||||
theme.palette.nym.networkExplorer.mixnodes.status
|
||||
.standby
|
||||
}
|
||||
icon={<Icons.mixnodes.status.standby />}
|
||||
count={summaryOverview.data?.mixnodes.activeset.standby}
|
||||
errorMsg={summaryOverview?.error}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
{gateways && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<Box component="main" sx={{ flexGrow: 1 }}>
|
||||
<Grid>
|
||||
<Grid item paddingBottom={3}>
|
||||
<Title text="Overview" />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid container spacing={3}>
|
||||
{summaryOverview && (
|
||||
<>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() => history.push('/network-components/gateways')}
|
||||
title="Gateways"
|
||||
count={gateways?.data?.length || ''}
|
||||
errorMsg={gateways?.error}
|
||||
icon={<GatewaysSVG />}
|
||||
onClick={() => history.push('/network-components/mixnodes')}
|
||||
title="Mixnodes"
|
||||
icon={<MixnodesSVG />}
|
||||
count={summaryOverview.data?.mixnodes.count || ''}
|
||||
errorMsg={summaryOverview?.error}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{validators && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() => window.open(`${BIG_DIPPER}/validators`)}
|
||||
title="Validators"
|
||||
count={validators?.data?.count || ''}
|
||||
errorMsg={validators?.error}
|
||||
icon={<ValidatorsSVG />}
|
||||
onClick={() => history.push('/network-components/mixnodes/active')}
|
||||
title="Active nodes"
|
||||
icon={<Icons.Mixnodes.Status.Active />}
|
||||
color={theme.palette.nym.networkExplorer.mixnodes.status.active}
|
||||
count={summaryOverview.data?.mixnodes.activeset.active}
|
||||
errorMsg={summaryOverview?.error}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
{block?.data && (
|
||||
<Grid item xs={12}>
|
||||
<Link
|
||||
href={`${BIG_DIPPER}/blocks`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
underline="none"
|
||||
color="inherit"
|
||||
marginY={2}
|
||||
paddingX={3}
|
||||
paddingY={0.25}
|
||||
fontSize={14}
|
||||
fontWeight={600}
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
>
|
||||
<Typography fontWeight="inherit" fontSize="inherit">
|
||||
Current block height is {formatNumber(block.data)}
|
||||
</Typography>
|
||||
<OpenInNewIcon
|
||||
fontWeight="inherit"
|
||||
fontSize="inherit"
|
||||
sx={{ ml: 0.5 }}
|
||||
/>
|
||||
</Link>
|
||||
<Grid item xs={12} md={4}>
|
||||
<StatsCard
|
||||
onClick={() => history.push('/network-components/mixnodes/standby')}
|
||||
title="Standby nodes"
|
||||
color={theme.palette.nym.networkExplorer.mixnodes.status.standby}
|
||||
icon={<Icons.Mixnodes.Status.Standby />}
|
||||
count={summaryOverview.data?.mixnodes.activeset.standby}
|
||||
errorMsg={summaryOverview?.error}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12}>
|
||||
<ContentCard title="Distribution of nodes around the world">
|
||||
<WorldMap loading={false} countryData={countryData} />
|
||||
</ContentCard>
|
||||
</>
|
||||
)}
|
||||
{gateways && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<StatsCard
|
||||
onClick={() => history.push('/network-components/gateways')}
|
||||
title="Gateways"
|
||||
count={gateways?.data?.length || ''}
|
||||
errorMsg={gateways?.error}
|
||||
icon={<GatewaysSVG />}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{validators && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<StatsCard
|
||||
onClick={() => window.open(`${BIG_DIPPER}/validators`)}
|
||||
title="Validators"
|
||||
count={validators?.data?.count || ''}
|
||||
errorMsg={validators?.error}
|
||||
icon={<ValidatorsSVG />}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
{block?.data && (
|
||||
<Grid item xs={12}>
|
||||
<Link
|
||||
href={`${BIG_DIPPER}/blocks`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
underline="none"
|
||||
color="inherit"
|
||||
marginY={2}
|
||||
paddingX={3}
|
||||
paddingY={0.25}
|
||||
fontSize={14}
|
||||
fontWeight={600}
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
>
|
||||
<Typography fontWeight="inherit" fontSize="inherit">
|
||||
Current block height is {formatNumber(block.data)}
|
||||
</Typography>
|
||||
<OpenInNewIcon fontWeight="inherit" fontSize="inherit" sx={{ ml: 0.5 }} />
|
||||
</Link>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12}>
|
||||
<ContentCard title="Distribution of nodes around the world">
|
||||
<WorldMap loading={false} countryData={countryData} />
|
||||
</ContentCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { Route, Switch, Redirect } from 'react-router-dom';
|
||||
import { PageOverview } from 'src/pages/Overview';
|
||||
import { PageMixnodesMap } from 'src/pages/MixnodesMap';
|
||||
import { PageOverview } from '../pages/Overview';
|
||||
import { PageMixnodesMap } from '../pages/MixnodesMap';
|
||||
import { Page404 } from '../pages/404';
|
||||
import { NetworkComponentsRoutes } from './network-components';
|
||||
|
||||
|
||||
@@ -1,36 +1,34 @@
|
||||
import * as React from 'react';
|
||||
import { Switch, Route, RouteComponentProps } from 'react-router-dom';
|
||||
import { BIG_DIPPER } from 'src/api/constants';
|
||||
import { PageGateways } from 'src/pages/Gateways';
|
||||
import { PageMixnodeDetail } from 'src/pages/MixnodeDetail';
|
||||
import { BIG_DIPPER } from '../api/constants';
|
||||
import { PageGateways } from '../pages/Gateways';
|
||||
import { PageMixnodeDetail } from '../pages/MixnodeDetail';
|
||||
import { PageMixnodes } from '../pages/Mixnodes';
|
||||
|
||||
export const NetworkComponentsRoutes: React.FC = () => (
|
||||
<>
|
||||
<Switch>
|
||||
<Route exact path="/network-components/mixnodes/:status">
|
||||
<PageMixnodes />
|
||||
</Route>
|
||||
<Route exact path="/network-components/mixnodes">
|
||||
<PageMixnodes />
|
||||
</Route>
|
||||
<Route path="/network-components/mixnode/:id">
|
||||
<PageMixnodeDetail />
|
||||
</Route>
|
||||
<Route path="/network-components/gateways">
|
||||
<PageGateways />
|
||||
</Route>
|
||||
<Route
|
||||
path="/network-components/validators"
|
||||
component={(props: RouteComponentProps) => {
|
||||
window.open(`${BIG_DIPPER}/validators`);
|
||||
props.history.goBack();
|
||||
return null;
|
||||
}}
|
||||
/>
|
||||
<Route path="/network-components/gateways/:id">
|
||||
<h1> Specific Gateways ID</h1>
|
||||
</Route>
|
||||
</Switch>
|
||||
</>
|
||||
<Switch>
|
||||
<Route exact path="/network-components/mixnodes/:status">
|
||||
<PageMixnodes />
|
||||
</Route>
|
||||
<Route exact path="/network-components/mixnodes">
|
||||
<PageMixnodes />
|
||||
</Route>
|
||||
<Route path="/network-components/mixnode/:id">
|
||||
<PageMixnodeDetail />
|
||||
</Route>
|
||||
<Route path="/network-components/gateways">
|
||||
<PageGateways />
|
||||
</Route>
|
||||
<Route
|
||||
path="/network-components/validators"
|
||||
component={(props: RouteComponentProps) => {
|
||||
window.open(`${BIG_DIPPER}/validators`);
|
||||
props.history.goBack();
|
||||
return null;
|
||||
}}
|
||||
/>
|
||||
<Route path="/network-components/gateways/:id">
|
||||
<h1> Specific Gateways ID</h1>
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
/* last resort for styles that cannot be handled by Material UI and Emotion JS */
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('./fonts/OpenSans-VariableFont_wdth,wght.ttf') format('truetype-variations'),
|
||||
url('./fonts/OpenSans-Italic-VariableFont_wdth,wght.ttf') format('truetype-variations');
|
||||
font-weight: 100 1000;
|
||||
}
|
||||
|
||||
/* TODO - this override should take place in either
|
||||
the theme declaration in index.tsx or the style prop
|
||||
in <DataGrid /> */
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# Nym Material UI Theme
|
||||
|
||||
This directory contains the theme overrides that customise the Material UI default theme to Nym branding.
|
||||
|
||||
## Getting started
|
||||
|
||||
If you are unfamiliar with Material UI theming, please read the following first:
|
||||
- https://mui.com/customization/theming/
|
||||
- https://mui.com/customization/palette/
|
||||
- https://mui.com/customization/dark-mode/#dark-mode-with-custom-palette
|
||||
|
||||
[mui-theme.d.ts](./mui-theme.d.ts) adds typings to the theme using Typescript's module augmentation.
|
||||
|
||||
Read the following if you are unfamiliar with module augmentation and declaration merging. Then
|
||||
look at the recommendations from Material UI docs for implementation:
|
||||
- https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
|
||||
- https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces
|
||||
- https://mui.com/customization/palette/#adding-new-colors
|
||||
|
||||
## Typings
|
||||
|
||||
[mui-theme.d.ts](./mui-theme.d.ts) contains the typings for the Nym theme additions and specific Network Explorer theme elements.
|
||||
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||
import { CssBaseline } from '@mui/material';
|
||||
import { getDesignTokens } from './theme';
|
||||
import { NymNetworkExplorerThemeProvider } from '@nymproject/mui-theme';
|
||||
import { useMainContext } from '../context/main';
|
||||
|
||||
/**
|
||||
* Provides the theme for the Network Explorer by reacting to the light/dark mode choice stored in the app context.
|
||||
*/
|
||||
export const NetworkExplorerThemeProvider: React.FC = ({ children }) => {
|
||||
const { mode } = useMainContext();
|
||||
const theme = React.useMemo(() => createTheme(getDesignTokens(mode)), [mode]);
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
);
|
||||
return <NymNetworkExplorerThemeProvider mode={mode}>{children}</NymNetworkExplorerThemeProvider>;
|
||||
};
|
||||
|
||||
Vendored
+5
-96
@@ -1,11 +1,6 @@
|
||||
/* eslint-disable no-shadow,@typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-interface */
|
||||
import {
|
||||
Theme,
|
||||
ThemeOptions,
|
||||
Palette,
|
||||
PaletteOptions,
|
||||
} from '@mui/material/styles';
|
||||
import { PaletteMode } from '@mui/material';
|
||||
/* eslint-disable no-shadow,@typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-interface,import/no-extraneous-dependencies */
|
||||
import { Theme, ThemeOptions, Palette, PaletteOptions } from '@mui/material/styles';
|
||||
import { NymTheme, NymPaletteWithExtensions, NymPaletteWithExtensionsOptions } from '@nymproject/mui-theme';
|
||||
|
||||
/**
|
||||
* If you are unfamiliar with Material UI theming, please read the following first:
|
||||
@@ -29,92 +24,6 @@ import { PaletteMode } from '@mui/material';
|
||||
*/
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
/**
|
||||
* This interface defines a palette used across Nym for branding
|
||||
*/
|
||||
interface NymPalette {
|
||||
highlight: string;
|
||||
text: {
|
||||
nav: string;
|
||||
footer: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface NymPaletteVariant {
|
||||
mode: PaletteMode;
|
||||
background: {
|
||||
main: string;
|
||||
paper: string;
|
||||
};
|
||||
text: {
|
||||
main: string;
|
||||
};
|
||||
topNav: {
|
||||
background: string;
|
||||
};
|
||||
nav: {
|
||||
background: string;
|
||||
hover: string;
|
||||
};
|
||||
mixnodes: {
|
||||
status: {
|
||||
active: string;
|
||||
standby: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A palette definition only for the Network Explorer that extends the Nym palette
|
||||
*/
|
||||
interface NetworkExplorerPalette {
|
||||
networkExplorer: {
|
||||
map: {
|
||||
stroke: string;
|
||||
fills: string[];
|
||||
};
|
||||
background: {
|
||||
tertiary: string;
|
||||
};
|
||||
topNav: {
|
||||
background: string;
|
||||
socialIcons: string;
|
||||
appBar: string;
|
||||
};
|
||||
nav: {
|
||||
selected: {
|
||||
main: string;
|
||||
nested: string;
|
||||
};
|
||||
background: string;
|
||||
hover: string;
|
||||
text: string;
|
||||
};
|
||||
footer: {
|
||||
socialIcons: string;
|
||||
};
|
||||
mixnodes: {
|
||||
status: {
|
||||
active: string;
|
||||
standby: string;
|
||||
inactive: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
interface NymPaletteAndNetworkExplorerPalette {
|
||||
nym: NymPalette & NetworkExplorerPalette;
|
||||
}
|
||||
|
||||
type NymPaletteAndNetworkExplorerPaletteOptions =
|
||||
Partial<NymPaletteAndNetworkExplorerPalette>;
|
||||
|
||||
/**
|
||||
* Add anything not palette related to the theme here
|
||||
*/
|
||||
interface NymTheme {}
|
||||
|
||||
/**
|
||||
* This augments the definitions of the MUI Theme with the Nym theme, as well as
|
||||
* a partial `ThemeOptions` type used by `createTheme`
|
||||
@@ -123,6 +32,6 @@ declare module '@mui/material/styles' {
|
||||
*/
|
||||
interface Theme extends NymTheme {}
|
||||
interface ThemeOptions extends Partial<NymTheme> {}
|
||||
interface Palette extends NymPaletteAndNetworkExplorerPalette {}
|
||||
interface PaletteOptions extends NymPaletteAndNetworkExplorerPaletteOptions {}
|
||||
interface Palette extends NymPaletteWithExtensions {}
|
||||
interface PaletteOptions extends NymPaletteWithExtensionsOptions {}
|
||||
}
|
||||
|
||||
@@ -1,287 +0,0 @@
|
||||
import { PaletteMode } from '@mui/material';
|
||||
import {
|
||||
PaletteOptions,
|
||||
NymPalette,
|
||||
NetworkExplorerPalette,
|
||||
ThemeOptions,
|
||||
createTheme,
|
||||
NymPaletteVariant,
|
||||
} from '@mui/material/styles';
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// Nym palette type definitions
|
||||
//
|
||||
|
||||
/**
|
||||
* The Nym palette.
|
||||
*
|
||||
* IMPORTANT: do not export this constant, always use the MUI `useTheme` hook to get the correct
|
||||
* colours for dark/light mode.
|
||||
*/
|
||||
const nymPalette: NymPalette = {
|
||||
/** emphasises important elements */
|
||||
highlight: '#FB6E4E',
|
||||
text: {
|
||||
nav: '#F2F2F2',
|
||||
/** footer text colour */
|
||||
footer: '#666B77',
|
||||
},
|
||||
};
|
||||
|
||||
const darkMode: NymPaletteVariant = {
|
||||
mode: 'dark',
|
||||
background: {
|
||||
main: '#111826',
|
||||
paper: '#242C3D',
|
||||
},
|
||||
text: {
|
||||
main: '#F2F2F2',
|
||||
},
|
||||
topNav: {
|
||||
background: '#111826',
|
||||
},
|
||||
nav: {
|
||||
background: '#242C3D',
|
||||
hover: '#111826',
|
||||
},
|
||||
mixnodes: {
|
||||
status: {
|
||||
active: '#20D073',
|
||||
standby: '#5FD7EF',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const lightMode: NymPaletteVariant = {
|
||||
mode: 'light',
|
||||
background: {
|
||||
main: '#F2F2F2',
|
||||
paper: '#FFFFFF',
|
||||
},
|
||||
text: {
|
||||
main: '#666666',
|
||||
},
|
||||
topNav: {
|
||||
background: '#111826',
|
||||
},
|
||||
nav: {
|
||||
background: '#242C3D',
|
||||
hover: '#111826',
|
||||
},
|
||||
mixnodes: {
|
||||
status: {
|
||||
active: '#1CBB67',
|
||||
standby: '#55C1D7',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Nym palette specific to the Network Explorer
|
||||
*
|
||||
* IMPORTANT: do not export this constant, always use the MUI `useTheme` hook to get the correct
|
||||
* colours for dark/light mode.
|
||||
*/
|
||||
const networkExplorerPalette = (
|
||||
variant: NymPaletteVariant,
|
||||
): NetworkExplorerPalette => ({
|
||||
networkExplorer: {
|
||||
/** world map styles */
|
||||
map: {
|
||||
stroke: '#333333',
|
||||
fills: [
|
||||
'rgba(255,255,255,0.2)',
|
||||
'#EFEFEF',
|
||||
'#FBE7E1',
|
||||
'#F7D1C6',
|
||||
'#F09379',
|
||||
],
|
||||
},
|
||||
background: {
|
||||
tertiary: variant.mode === 'light' ? '#F4F8FA' : '#323C51',
|
||||
},
|
||||
/** left nav styles */
|
||||
nav: {
|
||||
selected: {
|
||||
main: '#111826',
|
||||
nested: '#3C4558',
|
||||
},
|
||||
background: variant.nav.background,
|
||||
hover: variant.nav.hover,
|
||||
text: nymPalette.text.nav,
|
||||
},
|
||||
topNav: {
|
||||
...variant.topNav,
|
||||
appBar: '#080715',
|
||||
socialIcons: '#F2F2F2',
|
||||
},
|
||||
footer: {
|
||||
socialIcons:
|
||||
variant.mode === 'light' ? nymPalette.text.footer : darkMode.text.main,
|
||||
},
|
||||
mixnodes: {
|
||||
status: {
|
||||
active: variant.mixnodes.status.active,
|
||||
standby: variant.mixnodes.status.standby,
|
||||
inactive: variant.text.main,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// Nym palettes for light and dark mode
|
||||
//
|
||||
|
||||
/**
|
||||
* Map a Nym palette variant onto the MUI palette
|
||||
*/
|
||||
const variantToMUIPalette = (variant: NymPaletteVariant): PaletteOptions => ({
|
||||
text: {
|
||||
primary: variant.text.main,
|
||||
},
|
||||
primary: {
|
||||
main: nymPalette.highlight,
|
||||
contrastText: '#fff',
|
||||
},
|
||||
background: {
|
||||
default: variant.background.main,
|
||||
paper: variant.background.paper,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the Network Explorer palette for light mode.
|
||||
*/
|
||||
const createLightModePalette = (): PaletteOptions => ({
|
||||
nym: {
|
||||
...nymPalette,
|
||||
...networkExplorerPalette(lightMode),
|
||||
},
|
||||
...variantToMUIPalette(lightMode),
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the Network Explorer palette for dark mode.
|
||||
*/
|
||||
const createDarkModePalette = (): PaletteOptions => ({
|
||||
nym: {
|
||||
...nymPalette,
|
||||
...networkExplorerPalette(darkMode),
|
||||
},
|
||||
...variantToMUIPalette(darkMode),
|
||||
});
|
||||
|
||||
/**
|
||||
* IMPORTANT: if you need to get the default MUI theme, use the following
|
||||
*
|
||||
* import { createTheme as systemCreateTheme } from '@mui/system';
|
||||
*
|
||||
* // get the MUI system defaults for light mode
|
||||
* const systemTheme = systemCreateTheme({ palette: { mode: 'light' } });
|
||||
*
|
||||
*
|
||||
* return {
|
||||
* // change `primary` to default MUI `success`
|
||||
* primary: {
|
||||
* main: systemTheme.palette.success.main,
|
||||
* },
|
||||
* nym: {
|
||||
* ...nymPalette,
|
||||
* ...networkExplorerPalette,
|
||||
* },
|
||||
* };
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// Nym theme overrides
|
||||
//
|
||||
|
||||
/**
|
||||
* Gets the theme options to be passed to `createTheme`.
|
||||
*
|
||||
* Based on pattern from https://mui.com/customization/dark-mode/#dark-mode-with-custom-palette.
|
||||
*
|
||||
* @param mode The theme mode: 'light' or 'dark'
|
||||
*/
|
||||
export const getDesignTokens = (mode: PaletteMode): ThemeOptions => {
|
||||
// first, create the palette from user's choice of light or dark mode
|
||||
const { palette } = createTheme({
|
||||
palette: {
|
||||
mode,
|
||||
...(mode === 'light'
|
||||
? createLightModePalette()
|
||||
: createDarkModePalette()),
|
||||
},
|
||||
});
|
||||
|
||||
// then customise theme and components
|
||||
return {
|
||||
typography: {
|
||||
fontFamily: [
|
||||
'Open Sans',
|
||||
'sans-serif',
|
||||
'BlinkMacSystemFont',
|
||||
'Roboto',
|
||||
'Oxygen',
|
||||
'Ubuntu',
|
||||
'Helvetica Neue',
|
||||
].join(','),
|
||||
fontSize: 14,
|
||||
fontWeightRegular: 400,
|
||||
},
|
||||
transitions: {
|
||||
duration: {
|
||||
shortest: 150,
|
||||
shorter: 200,
|
||||
short: 250,
|
||||
standard: 300,
|
||||
complex: 375,
|
||||
enteringScreen: 225,
|
||||
leavingScreen: 195,
|
||||
},
|
||||
easing: {
|
||||
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
MuiCardHeader: {
|
||||
styleOverrides: {
|
||||
title: {
|
||||
fontSize: 16,
|
||||
fontWeight: 600,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDrawer: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
background: palette.secondary.dark,
|
||||
marginTop: 64,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiListItem: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
background: palette.secondary.dark,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiPaper: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderRadius: '10px',
|
||||
},
|
||||
elevation1: {
|
||||
backgroundImage: mode === 'dark' ? 'none' : undefined,
|
||||
},
|
||||
elevation2: {
|
||||
backgroundImage: mode === 'dark' ? 'none' : undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
palette,
|
||||
};
|
||||
};
|
||||
@@ -62,9 +62,7 @@ export enum MixnodeStatusWithAll {
|
||||
all = 'all', // any status
|
||||
}
|
||||
|
||||
export const toMixnodeStatus = (
|
||||
status?: MixnodeStatusWithAll,
|
||||
): MixnodeStatus | undefined => {
|
||||
export const toMixnodeStatus = (status?: MixnodeStatusWithAll): MixnodeStatus | undefined => {
|
||||
if (!status || status === MixnodeStatusWithAll.all) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
+1
-3
@@ -12,9 +12,7 @@ declare module 'react-identicons' {
|
||||
// getColor: Function;
|
||||
}
|
||||
|
||||
declare function Identicon(
|
||||
props: IdenticonProps,
|
||||
): React.ReactElement<IdenticonProps>;
|
||||
declare function Identicon(props: IdenticonProps): React.ReactElement<IdenticonProps>;
|
||||
|
||||
export default Identicon;
|
||||
}
|
||||
|
||||
@@ -9,10 +9,7 @@ export const currencyToString = (amount: string, denom: string = DENOM) =>
|
||||
denom,
|
||||
});
|
||||
|
||||
export const stakingCurrencyToString = (
|
||||
amount: string,
|
||||
denom: string = DENOM_STAKING,
|
||||
) =>
|
||||
export const stakingCurrencyToString = (amount: string, denom: string = DENOM_STAKING) =>
|
||||
printableCoin({
|
||||
amount,
|
||||
denom,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { MutableRefObject } from 'react';
|
||||
import { CountryData } from 'src/typeDefs/explorer-api';
|
||||
import { registerLocale, getName } from 'i18n-iso-countries';
|
||||
import { CountryData } from '../typeDefs/explorer-api';
|
||||
|
||||
registerLocale(require('i18n-iso-countries/langs/en.json'));
|
||||
|
||||
@@ -9,9 +9,7 @@ export function formatNumber(num: number): string {
|
||||
return new Intl.NumberFormat().format(num);
|
||||
}
|
||||
|
||||
export function scrollToRef(
|
||||
ref: MutableRefObject<HTMLDivElement | undefined>,
|
||||
): void {
|
||||
export function scrollToRef(ref: MutableRefObject<HTMLDivElement | undefined>): void {
|
||||
if (ref?.current) ref.current.scrollIntoView();
|
||||
}
|
||||
|
||||
@@ -23,9 +21,7 @@ export type CountryDataRowType = {
|
||||
percentage: string;
|
||||
};
|
||||
|
||||
export function countryDataToGridRow(
|
||||
countriesData: CountryData[],
|
||||
): CountryDataRowType[] {
|
||||
export function countryDataToGridRow(countriesData: CountryData[]): CountryDataRowType[] {
|
||||
const totalNodes = countriesData.reduce((acc, obj) => acc + obj.nodes, 0);
|
||||
const formatted = countriesData.map((each: CountryData, index: number) => {
|
||||
const updatedCountryRecord: CountryDataRowType = {
|
||||
|
||||
+8
-24
@@ -1,32 +1,16 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"extends": "../ts-packages/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": false,
|
||||
"jsx": "react-jsx",
|
||||
"sourceMap": true,
|
||||
"baseUrl": "."
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*.ts",
|
||||
"./src/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"jest.config.js",
|
||||
"webpack.config.js",
|
||||
"webpack.prod.js",
|
||||
"webpack.common.js"
|
||||
"build",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
|
||||
+16
-79
@@ -1,52 +1,21 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const WebpackFavicons = require('webpack-favicons');
|
||||
const Dotenv = require('dotenv-webpack');
|
||||
const { mergeWithRules } = require('webpack-merge');
|
||||
const { webpackCommon } = require('@nymproject/webpack');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.tsx',
|
||||
module.exports = mergeWithRules({
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.mdx?$/,
|
||||
use: ['babel-loader', './webpack/plugins/mdx-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg|md)$/i,
|
||||
// More information here https://webpack.js.org/guides/asset-modules/
|
||||
type: 'asset',
|
||||
},
|
||||
{
|
||||
// See https://webpack.js.org/guides/asset-management/#loading-fonts
|
||||
test: /\.(woff|woff2|eot|ttf|otf)$/i,
|
||||
type: 'asset/resource',
|
||||
},
|
||||
{
|
||||
test: /\.ya?ml$/,
|
||||
type: 'json',
|
||||
use: 'yaml-loader',
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
test: 'match',
|
||||
use: 'replace',
|
||||
},
|
||||
},
|
||||
})(webpackCommon(__dirname), {
|
||||
entry: path.resolve(__dirname, 'src/index.tsx'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
publicPath: '/',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js'],
|
||||
plugins: [new TsconfigPathsPlugin()],
|
||||
alias: {
|
||||
'react/jsx-runtime': require.resolve('react/jsx-runtime'),
|
||||
},
|
||||
fallback: {
|
||||
fs: false,
|
||||
tls: false,
|
||||
@@ -57,38 +26,6 @@ module.exports = {
|
||||
crypto: false,
|
||||
net: false,
|
||||
zlib: false,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
Buffer: ['buffer', 'Buffer'],
|
||||
}),
|
||||
|
||||
new CleanWebpackPlugin(),
|
||||
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: path.resolve(__dirname, 'src/index.html'),
|
||||
}),
|
||||
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: {
|
||||
mode: 'write-references',
|
||||
diagnosticOptions: {
|
||||
semantic: true,
|
||||
syntactic: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
new WebpackFavicons({
|
||||
src: 'src/logo.svg',
|
||||
}),
|
||||
|
||||
new Dotenv(),
|
||||
],
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
publicPath: '/',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,7 +13,6 @@ module.exports = mergeWithRules({
|
||||
},
|
||||
})(commonConfig, {
|
||||
mode: 'development',
|
||||
entry: './src/index.tsx',
|
||||
devtool: 'inline-source-map',
|
||||
module: {
|
||||
rules: [
|
||||
@@ -30,20 +29,6 @@ module.exports = mergeWithRules({
|
||||
transpileOnly: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
|
||||
// More information here https://webpack.js.org/guides/asset-modules/
|
||||
type: 'asset',
|
||||
},
|
||||
{
|
||||
test: /\.ya?ml$/,
|
||||
type: 'json',
|
||||
use: 'yaml-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState, useContext } from 'react'
|
||||
import { Button, List, ListItem, ListItemIcon, ListItemText, ListSubheader, Popover } from '@mui/material'
|
||||
import { ArrowDropDown, CheckSharp } from '@mui/icons-material'
|
||||
import { ClientContext, IS_DEV_MODE } from '../context/main'
|
||||
import { Network } from 'src/types'
|
||||
import { Network } from '../types'
|
||||
|
||||
const networks: { networkName: Network; name: string }[] = [
|
||||
{ networkName: 'MAINNET', name: 'Nym Mainnet' },
|
||||
@@ -10,7 +10,7 @@ const networks: { networkName: Network; name: string }[] = [
|
||||
{ networkName: 'QA', name: 'QA' },
|
||||
]
|
||||
|
||||
export const NetworkSelector = () => {
|
||||
export function NetworkSelector() {
|
||||
const { network, switchNetwork } = useContext(ClientContext)
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||
import { CssBaseline, PaletteMode } from '@mui/material';
|
||||
import { getDesignTokens } from './theme';
|
||||
import { getNetworkExplorerDesignTokens } from './network-explorer';
|
||||
|
||||
/**
|
||||
* Provides the theme for the Nym Components by reacting to the light/dark mode choice.
|
||||
@@ -18,5 +19,22 @@ export const NymThemeProvider: React.FC<{ mode: PaletteMode }> = ({ mode, childr
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides the theme with overrides for Network Explorer Components
|
||||
*
|
||||
* TODO: remove this provider and theme tokens to unify theme
|
||||
*
|
||||
*/
|
||||
export const NymNetworkExplorerThemeProvider: React.FC<{ mode: PaletteMode }> = ({ mode, children }) => {
|
||||
const theme = React.useMemo(() => createTheme(getNetworkExplorerDesignTokens(mode)), [mode]);
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export type { NymPalette, NymPaletteVariant } from './common';
|
||||
export type { NymTheme, NymPaletteWithExtensions, NymPaletteWithExtensionsOptions } from './theme';
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { darkMode, nymPalette, NymPaletteVariant } from './common';
|
||||
import { PaletteMode } from '@mui/material';
|
||||
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
||||
import { createDarkModePalette, createLightModePalette } from './theme';
|
||||
|
||||
/**
|
||||
* A palette definition only for the Network Explorer that extends the Nym palette
|
||||
@@ -83,3 +86,93 @@ export const networkExplorerPalette = (variant: NymPaletteVariant): NetworkExplo
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets the theme options to be passed to `createTheme` for Network Explorer.
|
||||
*
|
||||
* Based on pattern from https://mui.com/customization/dark-mode/#dark-mode-with-custom-palette.
|
||||
*
|
||||
* TODO: remove this by unifying theme
|
||||
*
|
||||
* @param mode The theme mode: 'light' or 'dark'
|
||||
*/
|
||||
export const getNetworkExplorerDesignTokens = (mode: PaletteMode): ThemeOptions => {
|
||||
// first, create the palette from user's choice of light or dark mode
|
||||
const { palette } = createTheme({
|
||||
palette: {
|
||||
mode,
|
||||
...(mode === 'light' ? createLightModePalette() : createDarkModePalette()),
|
||||
},
|
||||
});
|
||||
|
||||
// then customise theme and components
|
||||
return {
|
||||
typography: {
|
||||
fontFamily: [
|
||||
'Open Sans',
|
||||
'sans-serif',
|
||||
'BlinkMacSystemFont',
|
||||
'Roboto',
|
||||
'Oxygen',
|
||||
'Ubuntu',
|
||||
'Helvetica Neue',
|
||||
].join(','),
|
||||
fontSize: 14,
|
||||
fontWeightRegular: 400,
|
||||
},
|
||||
transitions: {
|
||||
duration: {
|
||||
shortest: 150,
|
||||
shorter: 200,
|
||||
short: 250,
|
||||
standard: 300,
|
||||
complex: 375,
|
||||
enteringScreen: 225,
|
||||
leavingScreen: 195,
|
||||
},
|
||||
easing: {
|
||||
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
MuiCardHeader: {
|
||||
styleOverrides: {
|
||||
title: {
|
||||
fontSize: 16,
|
||||
fontWeight: 600,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDrawer: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
background: palette.secondary.dark,
|
||||
marginTop: 64,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiListItem: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
background: palette.secondary.dark,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiPaper: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderRadius: '10px',
|
||||
},
|
||||
elevation1: {
|
||||
backgroundImage: mode === 'dark' ? 'none' : undefined,
|
||||
},
|
||||
elevation2: {
|
||||
backgroundImage: mode === 'dark' ? 'none' : undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
palette,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export type NymPaletteWithExtensionsOptions = Partial<NymPaletteWithExtensions>;
|
||||
/**
|
||||
* Returns the Nym palette for light mode.
|
||||
*/
|
||||
const createLightModePalette = (): PaletteOptions & NymPaletteWithExtensionsOptions => ({
|
||||
export const createLightModePalette = (): PaletteOptions & NymPaletteWithExtensionsOptions => ({
|
||||
nym: {
|
||||
...nymPalette,
|
||||
...nymWalletPallete(lightMode),
|
||||
@@ -45,7 +45,7 @@ const createLightModePalette = (): PaletteOptions & NymPaletteWithExtensionsOpti
|
||||
/**
|
||||
* Returns the Nym palette for dark mode.
|
||||
*/
|
||||
const createDarkModePalette = (): PaletteOptions & NymPaletteWithExtensionsOptions => ({
|
||||
export const createDarkModePalette = (): PaletteOptions & NymPaletteWithExtensionsOptions => ({
|
||||
nym: {
|
||||
...nymPalette,
|
||||
...nymWalletPallete(darkMode),
|
||||
|
||||
@@ -5,17 +5,18 @@
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"peerDependencies": {
|
||||
"@mui/icons-material": ">= 5",
|
||||
"@mui/lab": "^5.0.0-alpha.72",
|
||||
"@mui/material": ">= 5",
|
||||
"@mui/styles": ">= 5",
|
||||
"@mui/system": ">= 5",
|
||||
"@mui/icons-material": ">= 5",
|
||||
"@mui/lab": "^5.0.0-alpha.72",
|
||||
"@nymproject/mui-theme": "1",
|
||||
"react": "17",
|
||||
"react-dom": "17"
|
||||
},
|
||||
"dependencies": {
|
||||
"flat": "^5.0.2"
|
||||
"flat": "^5.0.2",
|
||||
"use-clipboard-copy": "^0.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.5",
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as React from 'react';
|
||||
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import { CopyToClipboard } from './CopyToClipboard';
|
||||
|
||||
export default {
|
||||
title: 'Decorators / Copy to clipboard',
|
||||
component: CopyToClipboard,
|
||||
} as ComponentMeta<typeof CopyToClipboard>;
|
||||
|
||||
const Template: ComponentStory<typeof CopyToClipboard> = (args) => {
|
||||
const { value } = args;
|
||||
return (
|
||||
<Box display="flex" alignContent="center">
|
||||
<CopyToClipboard {...args} />
|
||||
<Typography ml={1}>{value}</Typography>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
tooltip: 'Copy identity key to clipboard',
|
||||
value: '123456',
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
import * as React from 'react';
|
||||
import { useClipboard } from 'use-clipboard-copy';
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||
import DoneIcon from '@mui/icons-material/Done';
|
||||
import { Tooltip } from '@mui/material';
|
||||
import { SxProps } from '@mui/system';
|
||||
|
||||
export const CopyToClipboard: React.FC<{
|
||||
value: string;
|
||||
tooltip?: React.ReactNode;
|
||||
onCopy?: (value: string) => void;
|
||||
sx?: SxProps;
|
||||
}> = ({ value, tooltip, onCopy, sx }) => {
|
||||
const copy = useClipboard();
|
||||
const [showConfirmation, setShowConfirmation] = React.useState<boolean>(false);
|
||||
const handleCopy = () => {
|
||||
setShowConfirmation(true);
|
||||
copy.copy(value);
|
||||
if (onCopy) {
|
||||
onCopy(value);
|
||||
}
|
||||
setTimeout(() => setShowConfirmation(false), 2000);
|
||||
};
|
||||
return (
|
||||
<Tooltip title={tooltip || `Click to copy ${value} to clipboard`}>
|
||||
{showConfirmation ? (
|
||||
<DoneIcon color="success" sx={sx} />
|
||||
) : (
|
||||
<ContentCopyIcon onClick={handleCopy} sx={{ cursor: 'pointer', ...sx }} />
|
||||
)}
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
@@ -1 +1,2 @@
|
||||
export * from './logo';
|
||||
export * from './clipboard/CopyToClipboard';
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"@babel/preset-react": "^7.14.5",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@nymproject/eslint-config-react-typescript": "^1.0.0",
|
||||
"@nymproject/webpack": "^1.0.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
|
||||
"@svgr/webpack": "^6.1.1",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
|
||||
@@ -9,13 +9,6 @@
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "^0.3.0"
|
||||
|
||||
"@babel/code-frame@7.12.11":
|
||||
version "7.12.11"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
|
||||
integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.10.4"
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
|
||||
@@ -306,7 +299,7 @@
|
||||
"@babel/traverse" "^7.17.0"
|
||||
"@babel/types" "^7.17.0"
|
||||
|
||||
"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.7":
|
||||
"@babel/highlight@^7.16.7":
|
||||
version "7.16.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88"
|
||||
integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==
|
||||
@@ -1093,7 +1086,7 @@
|
||||
core-js-pure "^3.20.2"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.8", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.16.7", "@babel/runtime@^7.17.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.8", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.16.7", "@babel/runtime@^7.17.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
||||
version "7.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
|
||||
integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
|
||||
@@ -1548,21 +1541,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
|
||||
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
|
||||
|
||||
"@eslint/eslintrc@^0.4.3":
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
|
||||
integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.1.1"
|
||||
espree "^7.3.0"
|
||||
globals "^13.9.0"
|
||||
ignore "^4.0.6"
|
||||
import-fresh "^3.2.1"
|
||||
js-yaml "^3.13.1"
|
||||
minimatch "^3.0.4"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/eslintrc@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a"
|
||||
@@ -1588,15 +1566,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.8.8.tgz#17cf806485435877fdafce9f3bee6ff68f7f87b6"
|
||||
integrity sha512-meAEDur1IJBfKyTo9yPYAuzjIfrxA7m9Ov+1nxaW/YupsqMeseWifoUjWK03+hz/RJizsVQAaUjVxFEkyu0GWg==
|
||||
|
||||
"@humanwhocodes/config-array@^0.5.0":
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
|
||||
integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==
|
||||
dependencies:
|
||||
"@humanwhocodes/object-schema" "^1.2.0"
|
||||
debug "^4.1.1"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
"@humanwhocodes/config-array@^0.9.2":
|
||||
version "0.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7"
|
||||
@@ -1606,7 +1575,7 @@
|
||||
debug "^4.1.1"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
"@humanwhocodes/object-schema@^1.2.0", "@humanwhocodes/object-schema@^1.2.1":
|
||||
"@humanwhocodes/object-schema@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||
@@ -3249,7 +3218,7 @@
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^11.2.0"
|
||||
|
||||
"@pmmmwh/react-refresh-webpack-plugin@^0.5.0-rc.3", "@pmmmwh/react-refresh-webpack-plugin@^0.5.1", "@pmmmwh/react-refresh-webpack-plugin@^0.5.4":
|
||||
"@pmmmwh/react-refresh-webpack-plugin@^0.5.1", "@pmmmwh/react-refresh-webpack-plugin@^0.5.4":
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.4.tgz#df0d0d855fc527db48aac93c218a0bf4ada41f99"
|
||||
integrity sha512-zZbZeHQDnoTlt2AF+diQT0wsSXpvWiaIOZwBRdltNFhG1+I3ozyaw7U/nBiUwyJ0D+zwdXp0E3bWOl38Ag2BMw==
|
||||
@@ -4822,7 +4791,7 @@
|
||||
jest-matcher-utils "^27.0.0"
|
||||
pretty-format "^27.0.0"
|
||||
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
|
||||
version "7.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
|
||||
integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
|
||||
@@ -4977,7 +4946,7 @@
|
||||
"@types/react" "*"
|
||||
"@types/react-router" "*"
|
||||
|
||||
"@types/react-router@*":
|
||||
"@types/react-router@*", "@types/react-router@^5.1.18":
|
||||
version "5.1.18"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.18.tgz#c8851884b60bc23733500d86c1266e1cfbbd9ef3"
|
||||
integrity sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==
|
||||
@@ -5163,19 +5132,6 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@4.31.0":
|
||||
version "4.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.0.tgz#9c3fa6f44bad789a962426ad951b54695bd3af6b"
|
||||
integrity sha512-iPKZTZNavAlOhfF4gymiSuUkgLne/nh5Oz2/mdiUmuZVD42m9PapnCnzjxuDsnpnbH3wT5s2D8bw6S39TC6GNw==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "4.31.0"
|
||||
"@typescript-eslint/scope-manager" "4.31.0"
|
||||
debug "^4.3.1"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
regexpp "^3.1.0"
|
||||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz#2809052b85911ced9c54a60dac10e515e9114497"
|
||||
@@ -5191,30 +5147,6 @@
|
||||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/experimental-utils@4.31.0":
|
||||
version "4.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.0.tgz#0ef1d5d86c334f983a00f310e43c1ce4c14e054d"
|
||||
integrity sha512-Hld+EQiKLMppgKKkdUsLeVIeEOrwKc2G983NmznY/r5/ZtZCDvIOXnXtwqJIgYz/ymsy7n7RGvMyrzf1WaSQrw==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.7"
|
||||
"@typescript-eslint/scope-manager" "4.31.0"
|
||||
"@typescript-eslint/types" "4.31.0"
|
||||
"@typescript-eslint/typescript-estree" "4.31.0"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
|
||||
"@typescript-eslint/experimental-utils@^4.0.1":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd"
|
||||
integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.7"
|
||||
"@typescript-eslint/scope-manager" "4.33.0"
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
"@typescript-eslint/typescript-estree" "4.33.0"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
|
||||
"@typescript-eslint/experimental-utils@^5.3.0":
|
||||
version "5.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.14.0.tgz#73a455cd975d52830360a5b4131b7c4f8f1ff06f"
|
||||
@@ -5222,16 +5154,6 @@
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "5.14.0"
|
||||
|
||||
"@typescript-eslint/parser@4.31.0":
|
||||
version "4.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.31.0.tgz#87b7cd16b24b9170c77595d8b1363f8047121e05"
|
||||
integrity sha512-oWbzvPh5amMuTmKaf1wp0ySxPt2ZXHnFQBN2Szu1O//7LmOvgaKTCIDNLK2NvzpmVd5A2M/1j/rujBqO37hj3w==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "4.31.0"
|
||||
"@typescript-eslint/types" "4.31.0"
|
||||
"@typescript-eslint/typescript-estree" "4.31.0"
|
||||
debug "^4.3.1"
|
||||
|
||||
"@typescript-eslint/parser@^5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c"
|
||||
@@ -5242,22 +5164,6 @@
|
||||
"@typescript-eslint/typescript-estree" "5.13.0"
|
||||
debug "^4.3.2"
|
||||
|
||||
"@typescript-eslint/scope-manager@4.31.0":
|
||||
version "4.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.31.0.tgz#9be33aed4e9901db753803ba233b70d79a87fc3e"
|
||||
integrity sha512-LJ+xtl34W76JMRLjbaQorhR0hfRAlp3Lscdiz9NeI/8i+q0hdBZ7BsiYieLoYWqy+AnRigaD3hUwPFugSzdocg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.31.0"
|
||||
"@typescript-eslint/visitor-keys" "4.31.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3"
|
||||
integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
"@typescript-eslint/visitor-keys" "4.33.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6"
|
||||
@@ -5283,16 +5189,6 @@
|
||||
debug "^4.3.2"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/types@4.31.0":
|
||||
version "4.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.31.0.tgz#9a7c86fcc1620189567dc4e46cad7efa07ee8dce"
|
||||
integrity sha512-9XR5q9mk7DCXgXLS7REIVs+BaAswfdHhx91XqlJklmqWpTALGjygWVIb/UnLh4NWhfwhR5wNe1yTyCInxVhLqQ==
|
||||
|
||||
"@typescript-eslint/types@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72"
|
||||
integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==
|
||||
|
||||
"@typescript-eslint/types@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5"
|
||||
@@ -5303,32 +5199,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.14.0.tgz#96317cf116cea4befabc0defef371a1013f8ab11"
|
||||
integrity sha512-BR6Y9eE9360LNnW3eEUqAg6HxS9Q35kSIs4rp4vNHRdfg0s+/PgHgskvu5DFTM7G5VKAVjuyaN476LCPrdA7Mw==
|
||||
|
||||
"@typescript-eslint/typescript-estree@4.31.0":
|
||||
version "4.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.0.tgz#4da4cb6274a7ef3b21d53f9e7147cc76f278a078"
|
||||
integrity sha512-QHl2014t3ptg+xpmOSSPn5hm4mY8D4s97ftzyk9BZ8RxYQ3j73XcwuijnJ9cMa6DO4aLXeo8XS3z1omT9LA/Eg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.31.0"
|
||||
"@typescript-eslint/visitor-keys" "4.31.0"
|
||||
debug "^4.3.1"
|
||||
globby "^11.0.3"
|
||||
is-glob "^4.0.1"
|
||||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609"
|
||||
integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
"@typescript-eslint/visitor-keys" "4.33.0"
|
||||
debug "^4.3.1"
|
||||
globby "^11.0.3"
|
||||
is-glob "^4.0.1"
|
||||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141"
|
||||
@@ -5379,22 +5249,6 @@
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@4.31.0":
|
||||
version "4.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.0.tgz#4e87b7761cb4e0e627dc2047021aa693fc76ea2b"
|
||||
integrity sha512-HUcRp2a9I+P21+O21yu3ezv3GEPGjyGiXoEUQwZXjR8UxRApGeLyWH4ZIIUSalE28aG4YsV6GjtaAVB3QKOu0w==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.31.0"
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd"
|
||||
integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd"
|
||||
@@ -5758,7 +5612,7 @@ acorn@^6.4.1:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
|
||||
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
|
||||
|
||||
acorn@^7.1.1, acorn@^7.4.0, acorn@^7.4.1:
|
||||
acorn@^7.1.1, acorn@^7.4.1:
|
||||
version "7.4.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
@@ -5859,7 +5713,7 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@^8.0.0, ajv@^8.0.1, ajv@^8.8.0:
|
||||
ajv@^8.0.0, ajv@^8.8.0:
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d"
|
||||
integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==
|
||||
@@ -5881,11 +5735,6 @@ ansi-colors@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
|
||||
integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
|
||||
|
||||
ansi-colors@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
||||
|
||||
ansi-escapes@^4.2.1:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
|
||||
@@ -6051,7 +5900,7 @@ array-ify@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
|
||||
integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
|
||||
|
||||
array-includes@^3.0.3, array-includes@^3.1.1, array-includes@^3.1.3, array-includes@^3.1.4:
|
||||
array-includes@^3.0.3, array-includes@^3.1.3, array-includes@^3.1.4:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9"
|
||||
integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==
|
||||
@@ -6084,7 +5933,7 @@ array-unique@^0.3.2:
|
||||
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
||||
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
|
||||
|
||||
array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.4, array.prototype.flat@^1.2.5:
|
||||
array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13"
|
||||
integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==
|
||||
@@ -6093,7 +5942,7 @@ array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.4, array.prototype.flat@^
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.19.0"
|
||||
|
||||
array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.4, array.prototype.flatmap@^1.2.5:
|
||||
array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446"
|
||||
integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==
|
||||
@@ -6175,11 +6024,6 @@ ast-types@^0.14.2:
|
||||
dependencies:
|
||||
tslib "^2.0.1"
|
||||
|
||||
astral-regex@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
|
||||
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
|
||||
|
||||
async-each@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
|
||||
@@ -6235,7 +6079,7 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
||||
|
||||
axe-core@^4.0.2, axe-core@^4.3.5:
|
||||
axe-core@^4.3.5:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413"
|
||||
integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==
|
||||
@@ -7230,6 +7074,11 @@ cli-width@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
|
||||
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
|
||||
|
||||
clipboard-copy@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/clipboard-copy/-/clipboard-copy-3.2.0.tgz#3c5b8651d3512dcfad295d77a9eb09e7fac8d5fb"
|
||||
integrity sha512-vooFaGFL6ulEP1liiaWFBmmfuPm3cY3y7T9eB83ZTnYc/oFeAKsq3NcDrOkBC8XaauEE8zHQwI7k0+JSYiVQSQ==
|
||||
|
||||
cliui@^7.0.2:
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
||||
@@ -8156,7 +8005,7 @@ d3-zoom@^2.0.0:
|
||||
d3-selection "2"
|
||||
d3-transition "2"
|
||||
|
||||
damerau-levenshtein@^1.0.6, damerau-levenshtein@^1.0.7:
|
||||
damerau-levenshtein@^1.0.7:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
|
||||
integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
|
||||
@@ -8199,7 +8048,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2:
|
||||
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
|
||||
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
|
||||
@@ -8712,7 +8561,7 @@ emoji-regex@^8.0.0:
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
emoji-regex@^9.0.0, emoji-regex@^9.2.2:
|
||||
emoji-regex@^9.2.2:
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
|
||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||
@@ -8776,13 +8625,6 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.7.0, enhanced-resolve@^5.8.3, enhan
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.2.0"
|
||||
|
||||
enquirer@^2.3.5:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
|
||||
integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
|
||||
dependencies:
|
||||
ansi-colors "^4.1.1"
|
||||
|
||||
entities@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||
@@ -8940,15 +8782,6 @@ escodegen@^2.0.0:
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
eslint-config-airbnb-base@^14.2.1:
|
||||
version "14.2.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e"
|
||||
integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==
|
||||
dependencies:
|
||||
confusing-browser-globals "^1.0.10"
|
||||
object.assign "^4.1.2"
|
||||
object.entries "^1.1.2"
|
||||
|
||||
eslint-config-airbnb-base@^15.0.0:
|
||||
version "15.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236"
|
||||
@@ -8966,15 +8799,6 @@ eslint-config-airbnb-typescript@^16.1.0:
|
||||
dependencies:
|
||||
eslint-config-airbnb-base "^15.0.0"
|
||||
|
||||
eslint-config-airbnb@18.2.1:
|
||||
version "18.2.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz#b7fe2b42f9f8173e825b73c8014b592e449c98d9"
|
||||
integrity sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg==
|
||||
dependencies:
|
||||
eslint-config-airbnb-base "^14.2.1"
|
||||
object.assign "^4.1.2"
|
||||
object.entries "^1.1.2"
|
||||
|
||||
eslint-config-airbnb@^19.0.4:
|
||||
version "19.0.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz#84d4c3490ad70a0ffa571138ebcdea6ab085fdc3"
|
||||
@@ -8984,11 +8808,6 @@ eslint-config-airbnb@^19.0.4:
|
||||
object.assign "^4.1.2"
|
||||
object.entries "^1.1.5"
|
||||
|
||||
eslint-config-prettier@8.3.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a"
|
||||
integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==
|
||||
|
||||
eslint-config-prettier@^8.5.0:
|
||||
version "8.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1"
|
||||
@@ -9002,7 +8821,7 @@ eslint-import-resolver-node@^0.3.2, eslint-import-resolver-node@^0.3.6:
|
||||
debug "^3.2.7"
|
||||
resolve "^1.20.0"
|
||||
|
||||
eslint-import-resolver-root-import@1.0.4, eslint-import-resolver-root-import@^1.0.4:
|
||||
eslint-import-resolver-root-import@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-import-resolver-root-import/-/eslint-import-resolver-root-import-1.0.4.tgz#82991138d8014b5e2283b27622ad1ba21f535609"
|
||||
integrity sha512-c8cUQcELRBe0mnblBZJKEfL+jIUGR8pctK5gdru5N7bBOIve2WZ0R3KoO5GOksXJ4WzZhtcBS2xPaTJYEe4IdQ==
|
||||
@@ -9010,7 +8829,7 @@ eslint-import-resolver-root-import@1.0.4, eslint-import-resolver-root-import@^1.
|
||||
eslint-import-resolver-node "^0.3.2"
|
||||
json5 "^2.1.0"
|
||||
|
||||
eslint-module-utils@^2.6.2, eslint-module-utils@^2.7.2:
|
||||
eslint-module-utils@^2.7.2:
|
||||
version "2.7.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee"
|
||||
integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==
|
||||
@@ -9018,27 +8837,6 @@ eslint-module-utils@^2.6.2, eslint-module-utils@^2.7.2:
|
||||
debug "^3.2.7"
|
||||
find-up "^2.1.0"
|
||||
|
||||
eslint-plugin-import@2.24.2:
|
||||
version "2.24.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz#2c8cd2e341f3885918ee27d18479910ade7bb4da"
|
||||
integrity sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==
|
||||
dependencies:
|
||||
array-includes "^3.1.3"
|
||||
array.prototype.flat "^1.2.4"
|
||||
debug "^2.6.9"
|
||||
doctrine "^2.1.0"
|
||||
eslint-import-resolver-node "^0.3.6"
|
||||
eslint-module-utils "^2.6.2"
|
||||
find-up "^2.0.0"
|
||||
has "^1.0.3"
|
||||
is-core-module "^2.6.0"
|
||||
minimatch "^3.0.4"
|
||||
object.values "^1.1.4"
|
||||
pkg-up "^2.0.0"
|
||||
read-pkg-up "^3.0.0"
|
||||
resolve "^1.20.0"
|
||||
tsconfig-paths "^3.11.0"
|
||||
|
||||
eslint-plugin-import@^2.25.4:
|
||||
version "2.25.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1"
|
||||
@@ -9058,13 +8856,6 @@ eslint-plugin-import@^2.25.4:
|
||||
resolve "^1.20.0"
|
||||
tsconfig-paths "^3.12.0"
|
||||
|
||||
eslint-plugin-jest@^24.4.0:
|
||||
version "24.7.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.7.0.tgz#206ac0833841e59e375170b15f8d0955219c4889"
|
||||
integrity sha512-wUxdF2bAZiYSKBclsUMrYHH6WxiBreNjyDxbRv345TIvPeoCEgPNEn3Sa+ZrSqsf1Dl9SqqSREXMHExlMMu1DA==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "^4.0.1"
|
||||
|
||||
eslint-plugin-jest@^26.1.1:
|
||||
version "26.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.1.1.tgz#7176dd745ef8bca3070263f62cdf112f2dfc9aa1"
|
||||
@@ -9072,23 +8863,6 @@ eslint-plugin-jest@^26.1.1:
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "^5.10.0"
|
||||
|
||||
eslint-plugin-jsx-a11y@6.4.1:
|
||||
version "6.4.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd"
|
||||
integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.11.2"
|
||||
aria-query "^4.2.2"
|
||||
array-includes "^3.1.1"
|
||||
ast-types-flow "^0.0.7"
|
||||
axe-core "^4.0.2"
|
||||
axobject-query "^2.2.0"
|
||||
damerau-levenshtein "^1.0.6"
|
||||
emoji-regex "^9.0.0"
|
||||
has "^1.0.3"
|
||||
jsx-ast-utils "^3.1.0"
|
||||
language-tags "^1.0.5"
|
||||
|
||||
eslint-plugin-jsx-a11y@^6.5.1:
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8"
|
||||
@@ -9107,42 +8881,18 @@ eslint-plugin-jsx-a11y@^6.5.1:
|
||||
language-tags "^1.0.5"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
eslint-plugin-prettier@4.0.0, eslint-plugin-prettier@^4.0.0:
|
||||
eslint-plugin-prettier@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0"
|
||||
integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==
|
||||
dependencies:
|
||||
prettier-linter-helpers "^1.0.0"
|
||||
|
||||
eslint-plugin-react-hooks@4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556"
|
||||
integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==
|
||||
|
||||
eslint-plugin-react-hooks@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172"
|
||||
integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==
|
||||
|
||||
eslint-plugin-react@7.25.1:
|
||||
version "7.25.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.25.1.tgz#9286b7cd9bf917d40309760f403e53016eda8331"
|
||||
integrity sha512-P4j9K1dHoFXxDNP05AtixcJEvIT6ht8FhYKsrkY0MPCPaUMYijhpWwNiRDZVtA8KFuZOkGSeft6QwH8KuVpJug==
|
||||
dependencies:
|
||||
array-includes "^3.1.3"
|
||||
array.prototype.flatmap "^1.2.4"
|
||||
doctrine "^2.1.0"
|
||||
estraverse "^5.2.0"
|
||||
has "^1.0.3"
|
||||
jsx-ast-utils "^2.4.1 || ^3.0.0"
|
||||
minimatch "^3.0.4"
|
||||
object.entries "^1.1.4"
|
||||
object.fromentries "^2.0.4"
|
||||
object.values "^1.1.4"
|
||||
prop-types "^15.7.2"
|
||||
resolve "^2.0.0-next.3"
|
||||
string.prototype.matchall "^4.0.5"
|
||||
|
||||
eslint-plugin-react@^7.29.2:
|
||||
version "7.29.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.2.tgz#2d4da69d30d0a736efd30890dc6826f3e91f3f7c"
|
||||
@@ -9196,13 +8946,6 @@ eslint-scope@^7.1.1:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
|
||||
eslint-utils@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
|
||||
integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
eslint-utils@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
|
||||
@@ -9210,11 +8953,6 @@ eslint-utils@^3.0.0:
|
||||
dependencies:
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
|
||||
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
|
||||
|
||||
eslint-visitor-keys@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
|
||||
@@ -9225,52 +8963,6 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
|
||||
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
||||
|
||||
eslint@7.32.0:
|
||||
version "7.32.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
|
||||
integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "7.12.11"
|
||||
"@eslint/eslintrc" "^0.4.3"
|
||||
"@humanwhocodes/config-array" "^0.5.0"
|
||||
ajv "^6.10.0"
|
||||
chalk "^4.0.0"
|
||||
cross-spawn "^7.0.2"
|
||||
debug "^4.0.1"
|
||||
doctrine "^3.0.0"
|
||||
enquirer "^2.3.5"
|
||||
escape-string-regexp "^4.0.0"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^2.1.0"
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
espree "^7.3.1"
|
||||
esquery "^1.4.0"
|
||||
esutils "^2.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
file-entry-cache "^6.0.1"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
glob-parent "^5.1.2"
|
||||
globals "^13.6.0"
|
||||
ignore "^4.0.6"
|
||||
import-fresh "^3.0.0"
|
||||
imurmurhash "^0.1.4"
|
||||
is-glob "^4.0.0"
|
||||
js-yaml "^3.13.1"
|
||||
json-stable-stringify-without-jsonify "^1.0.1"
|
||||
levn "^0.4.1"
|
||||
lodash.merge "^4.6.2"
|
||||
minimatch "^3.0.4"
|
||||
natural-compare "^1.4.0"
|
||||
optionator "^0.9.1"
|
||||
progress "^2.0.0"
|
||||
regexpp "^3.1.0"
|
||||
semver "^7.2.1"
|
||||
strip-ansi "^6.0.0"
|
||||
strip-json-comments "^3.1.0"
|
||||
table "^6.0.9"
|
||||
text-table "^0.2.0"
|
||||
v8-compile-cache "^2.0.3"
|
||||
|
||||
eslint@^8.10.0:
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d"
|
||||
@@ -9312,15 +9004,6 @@ eslint@^8.10.0:
|
||||
text-table "^0.2.0"
|
||||
v8-compile-cache "^2.0.3"
|
||||
|
||||
espree@^7.3.0, espree@^7.3.1:
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
|
||||
integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
|
||||
dependencies:
|
||||
acorn "^7.4.0"
|
||||
acorn-jsx "^5.3.1"
|
||||
eslint-visitor-keys "^1.3.0"
|
||||
|
||||
espree@^9.3.1:
|
||||
version "9.3.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
|
||||
@@ -9828,6 +9511,11 @@ flat-cache@^3.0.4:
|
||||
flatted "^3.1.0"
|
||||
rimraf "^3.0.2"
|
||||
|
||||
flat@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
|
||||
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
|
||||
|
||||
flatted@^3.1.0:
|
||||
version "3.2.5"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
|
||||
@@ -9877,7 +9565,7 @@ fork-ts-checker-webpack-plugin@^4.1.6:
|
||||
tapable "^1.0.0"
|
||||
worker-rpc "^0.1.0"
|
||||
|
||||
fork-ts-checker-webpack-plugin@^6.0.4, fork-ts-checker-webpack-plugin@^6.3.3:
|
||||
fork-ts-checker-webpack-plugin@^6.0.4:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e"
|
||||
integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==
|
||||
@@ -10326,7 +10014,7 @@ globalthis@^1.0.0, globalthis@^1.0.1:
|
||||
dependencies:
|
||||
define-properties "^1.1.3"
|
||||
|
||||
globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.0.4:
|
||||
globby@^11.0.1, globby@^11.0.2, globby@^11.0.4:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
|
||||
integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
|
||||
@@ -10925,14 +10613,6 @@ import-local@^3.0.2:
|
||||
pkg-dir "^4.2.0"
|
||||
resolve-cwd "^3.0.0"
|
||||
|
||||
imports-loader@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-3.1.1.tgz#3e464d9aad1e303b1b34b658eb8f8aae22f96435"
|
||||
integrity sha512-3QMyGU4RTgxLf0puWkUfT5+7zJvexvB00PI5skDIcxG8O20gZCbQsaRpNBv+cIO6yy/lmlOBwaxc3uH1CV+sww==
|
||||
dependencies:
|
||||
source-map "^0.6.1"
|
||||
strip-comments "^2.0.1"
|
||||
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
@@ -11165,7 +10845,7 @@ is-ci@^2.0.0:
|
||||
dependencies:
|
||||
ci-info "^2.0.0"
|
||||
|
||||
is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.6.0, is-core-module@^2.8.0, is-core-module@^2.8.1:
|
||||
is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.8.0, is-core-module@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
|
||||
integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
|
||||
@@ -12335,7 +12015,7 @@ jss@10.9.0, jss@^10.8.2:
|
||||
is-in-browser "^1.1.3"
|
||||
tiny-warning "^1.0.2"
|
||||
|
||||
"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0, jsx-ast-utils@^3.2.1:
|
||||
"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b"
|
||||
integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==
|
||||
@@ -12651,11 +12331,6 @@ lodash.templatesettings@^4.0.0:
|
||||
dependencies:
|
||||
lodash._reinterpolate "^3.0.0"
|
||||
|
||||
lodash.truncate@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
||||
|
||||
lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
@@ -13776,7 +13451,7 @@ object.assign@^4.1.0, object.assign@^4.1.2:
|
||||
has-symbols "^1.0.1"
|
||||
object-keys "^1.1.1"
|
||||
|
||||
object.entries@^1.1.0, object.entries@^1.1.2, object.entries@^1.1.4, object.entries@^1.1.5:
|
||||
object.entries@^1.1.0, object.entries@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861"
|
||||
integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==
|
||||
@@ -13785,7 +13460,7 @@ object.entries@^1.1.0, object.entries@^1.1.2, object.entries@^1.1.4, object.entr
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.19.1"
|
||||
|
||||
"object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.4, object.fromentries@^2.0.5:
|
||||
"object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251"
|
||||
integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==
|
||||
@@ -13818,7 +13493,7 @@ object.pick@^1.3.0:
|
||||
dependencies:
|
||||
isobject "^3.0.1"
|
||||
|
||||
object.values@^1.1.0, object.values@^1.1.4, object.values@^1.1.5:
|
||||
object.values@^1.1.0, object.values@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac"
|
||||
integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==
|
||||
@@ -14451,13 +14126,6 @@ pkg-dir@^5.0.0:
|
||||
dependencies:
|
||||
find-up "^5.0.0"
|
||||
|
||||
pkg-up@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f"
|
||||
integrity sha1-yBmscoBZpGHKscOImivjxJoATX8=
|
||||
dependencies:
|
||||
find-up "^2.1.0"
|
||||
|
||||
pngjs@^3.0.0, pngjs@^3.2.0, pngjs@^3.3.3:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
|
||||
@@ -14920,11 +14588,6 @@ process@^0.11.10:
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
|
||||
progress@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||
|
||||
promise-inflight@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||
@@ -15296,7 +14959,7 @@ react-element-to-jsx-string@^14.3.4:
|
||||
is-plain-object "5.0.0"
|
||||
react-is "17.0.2"
|
||||
|
||||
react-error-boundary@^3.1.3:
|
||||
react-error-boundary@^3.1.3, react-error-boundary@^3.1.4:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0"
|
||||
integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==
|
||||
@@ -15413,7 +15076,7 @@ react-router-dom@^6.0.0:
|
||||
history "^5.2.0"
|
||||
react-router "6.2.2"
|
||||
|
||||
react-router@5.2.1:
|
||||
react-router@5.2.1, react-router@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d"
|
||||
integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==
|
||||
@@ -15719,7 +15382,7 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1:
|
||||
call-bind "^1.0.2"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
regexpp@^3.1.0, regexpp@^3.2.0:
|
||||
regexpp@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
|
||||
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
|
||||
@@ -16191,7 +15854,7 @@ semver@7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
|
||||
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
||||
|
||||
semver@7.x, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
|
||||
semver@7.x, semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
|
||||
version "7.3.5"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
|
||||
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
|
||||
@@ -16448,15 +16111,6 @@ slash@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
slice-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
|
||||
integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
slide@^1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
|
||||
@@ -16832,7 +16486,7 @@ string-width@^1.0.1:
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.5, string.prototype.matchall@^4.0.6:
|
||||
"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa"
|
||||
integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==
|
||||
@@ -16925,11 +16579,6 @@ strip-bom@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
|
||||
integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
|
||||
|
||||
strip-comments@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b"
|
||||
integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==
|
||||
|
||||
strip-eof@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
||||
@@ -17084,17 +16733,6 @@ synchronous-promise@^2.0.15:
|
||||
resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.15.tgz#07ca1822b9de0001f5ff73595f3d08c4f720eb8e"
|
||||
integrity sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg==
|
||||
|
||||
table@^6.0.9:
|
||||
version "6.8.0"
|
||||
resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca"
|
||||
integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==
|
||||
dependencies:
|
||||
ajv "^8.0.1"
|
||||
lodash.truncate "^4.4.2"
|
||||
slice-ansi "^4.0.0"
|
||||
string-width "^4.2.3"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
tapable@^1.0.0, tapable@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
|
||||
@@ -17505,7 +17143,7 @@ ts-pnp@^1.1.6:
|
||||
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
|
||||
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
|
||||
|
||||
tsconfig-paths-webpack-plugin@^3.5.1, tsconfig-paths-webpack-plugin@^3.5.2:
|
||||
tsconfig-paths-webpack-plugin@^3.5.2:
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz#01aafff59130c04a8c4ebc96a3045c43c376449a"
|
||||
integrity sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==
|
||||
@@ -17514,20 +17152,20 @@ tsconfig-paths-webpack-plugin@^3.5.1, tsconfig-paths-webpack-plugin@^3.5.2:
|
||||
enhanced-resolve "^5.7.0"
|
||||
tsconfig-paths "^3.9.0"
|
||||
|
||||
tsconfig-paths@^3.11.0, tsconfig-paths@^3.9.0:
|
||||
version "3.13.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7"
|
||||
integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw==
|
||||
tsconfig-paths@^3.12.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b"
|
||||
integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==
|
||||
dependencies:
|
||||
"@types/json5" "^0.0.29"
|
||||
json5 "^1.0.1"
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tsconfig-paths@^3.12.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b"
|
||||
integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==
|
||||
tsconfig-paths@^3.9.0:
|
||||
version "3.13.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7"
|
||||
integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw==
|
||||
dependencies:
|
||||
"@types/json5" "^0.0.29"
|
||||
json5 "^1.0.1"
|
||||
@@ -17642,7 +17280,7 @@ typedarray@^0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^4.4.2, typescript@^4.6.2:
|
||||
typescript@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
|
||||
integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
|
||||
@@ -17876,6 +17514,13 @@ url@^0.11.0:
|
||||
punycode "1.3.2"
|
||||
querystring "0.2.0"
|
||||
|
||||
use-clipboard-copy@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/use-clipboard-copy/-/use-clipboard-copy-0.2.0.tgz#e1f31f2b21e369bc79b5d7b358e2c8aece6ef264"
|
||||
integrity sha512-f0PMMwZ2/Hh9/54L12capx4s6ASdd6edNJxg2OcqWVNM8BPvtOSmNFIN1Dg/q//fPp8MpUZceHfr7cnWOS0RxA==
|
||||
dependencies:
|
||||
clipboard-copy "^3.0.0"
|
||||
|
||||
use-composed-ref@^1.0.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.2.1.tgz#9bdcb5ccd894289105da2325e1210079f56bf849"
|
||||
@@ -18197,7 +17842,7 @@ webpack-dev-middleware@^5.3.1:
|
||||
range-parser "^1.2.1"
|
||||
schema-utils "^4.0.0"
|
||||
|
||||
webpack-dev-server@^4.1.0, webpack-dev-server@^4.5.0:
|
||||
webpack-dev-server@^4.5.0:
|
||||
version "4.7.4"
|
||||
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945"
|
||||
integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==
|
||||
@@ -18233,7 +17878,7 @@ webpack-dev-server@^4.1.0, webpack-dev-server@^4.5.0:
|
||||
webpack-dev-middleware "^5.3.1"
|
||||
ws "^8.4.2"
|
||||
|
||||
webpack-favicons@^1.0.7, webpack-favicons@^1.3.8:
|
||||
webpack-favicons@^1.3.8:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/webpack-favicons/-/webpack-favicons-1.3.8.tgz#cc986bf8f4cd7629af44a726ca142e14c66e7be5"
|
||||
integrity sha512-c40JTAUOorQSle2X1p5eRBpNl/zWw4rqR5EvCvLGZqMaXHUtJM/waCLgz0H4Pg1nXvvqV/LoYoqSvoAI0WiD0g==
|
||||
@@ -18325,36 +17970,6 @@ webpack@4:
|
||||
watchpack "^1.7.4"
|
||||
webpack-sources "^1.4.1"
|
||||
|
||||
webpack@^5.52.0, webpack@^5.9.0:
|
||||
version "5.70.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.70.0.tgz#3461e6287a72b5e6e2f4872700bc8de0d7500e6d"
|
||||
integrity sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.3"
|
||||
"@types/estree" "^0.0.51"
|
||||
"@webassemblyjs/ast" "1.11.1"
|
||||
"@webassemblyjs/wasm-edit" "1.11.1"
|
||||
"@webassemblyjs/wasm-parser" "1.11.1"
|
||||
acorn "^8.4.1"
|
||||
acorn-import-assertions "^1.7.6"
|
||||
browserslist "^4.14.5"
|
||||
chrome-trace-event "^1.0.2"
|
||||
enhanced-resolve "^5.9.2"
|
||||
es-module-lexer "^0.9.0"
|
||||
eslint-scope "5.1.1"
|
||||
events "^3.2.0"
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.2.9"
|
||||
json-parse-better-errors "^1.0.2"
|
||||
loader-runner "^4.2.0"
|
||||
mime-types "^2.1.27"
|
||||
neo-async "^2.6.2"
|
||||
schema-utils "^3.1.0"
|
||||
tapable "^2.1.1"
|
||||
terser-webpack-plugin "^5.1.3"
|
||||
watchpack "^2.3.1"
|
||||
webpack-sources "^3.2.3"
|
||||
|
||||
webpack@^5.64.3:
|
||||
version "5.69.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5"
|
||||
@@ -18385,6 +18000,36 @@ webpack@^5.64.3:
|
||||
watchpack "^2.3.1"
|
||||
webpack-sources "^3.2.3"
|
||||
|
||||
webpack@^5.9.0:
|
||||
version "5.70.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.70.0.tgz#3461e6287a72b5e6e2f4872700bc8de0d7500e6d"
|
||||
integrity sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.3"
|
||||
"@types/estree" "^0.0.51"
|
||||
"@webassemblyjs/ast" "1.11.1"
|
||||
"@webassemblyjs/wasm-edit" "1.11.1"
|
||||
"@webassemblyjs/wasm-parser" "1.11.1"
|
||||
acorn "^8.4.1"
|
||||
acorn-import-assertions "^1.7.6"
|
||||
browserslist "^4.14.5"
|
||||
chrome-trace-event "^1.0.2"
|
||||
enhanced-resolve "^5.9.2"
|
||||
es-module-lexer "^0.9.0"
|
||||
eslint-scope "5.1.1"
|
||||
events "^3.2.0"
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.2.9"
|
||||
json-parse-better-errors "^1.0.2"
|
||||
loader-runner "^4.2.0"
|
||||
mime-types "^2.1.27"
|
||||
neo-async "^2.6.2"
|
||||
schema-utils "^3.1.0"
|
||||
tapable "^2.1.1"
|
||||
terser-webpack-plugin "^5.1.3"
|
||||
watchpack "^2.3.1"
|
||||
webpack-sources "^3.2.3"
|
||||
|
||||
websocket-driver@>=0.5.1, websocket-driver@^0.7.4:
|
||||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
|
||||
@@ -18643,15 +18288,7 @@ yallist@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml-loader@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/yaml-loader/-/yaml-loader-0.6.0.tgz#fe1c48b9f4803dace55a59a1474e790ba6ab1b48"
|
||||
integrity sha512-1bNiLelumURyj+zvVHOv8Y3dpCri0F2S+DCcmps0pA1zWRLjS+FhZQg4o3aUUDYESh73+pKZNI18bj7stpReow==
|
||||
dependencies:
|
||||
loader-utils "^1.4.0"
|
||||
yaml "^1.8.3"
|
||||
|
||||
yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2, yaml@^1.8.3:
|
||||
yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
|
||||
Reference in New Issue
Block a user