106 - migrate mainnet stats to monorepo (#107)
* Initial commit of generated mainnet-stats directory * Migration partly complete * Migration complete * Vega logo now in ui toolkit * Specified a port that stops conflicts with other e2e tests * Extra config for swapping to port that stops conflicts with other e2e tests. Also file name case change * Adding the Cypress project ID to allow recording * fix test * Mainnet stats manager moved into library * Mainnet stats project now importing manager element from lib * Block Explorer has mainnet stats on home route * Styling tweak to stop mainnet stats tables trying to match heights * Spacing alignment tweaks * Changing header text and tests to align with other branches * Correct header test for mainnet-stats app * Correct h3 test for mainnet-stats app * Fix linting issue * fix casing issue for CI * Corrected mistake in merge Co-authored-by: Dexter <dexter.edwards93@gmail.com>
This commit is contained in:
parent
d3f5410747
commit
05d53bbf4c
@ -54,7 +54,7 @@ export default class BasePage {
|
||||
validateSearchDisplayed() {
|
||||
cy.getByTestId(this.blockExplorerHeader).should(
|
||||
'have.text',
|
||||
'Vega Block Explorer'
|
||||
'Vega Explorer'
|
||||
);
|
||||
cy.getByTestId(this.searchField).should('be.visible');
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { StatsManager } from '@vegaprotocol/mainnet-stats-manager';
|
||||
|
||||
const Home = () => {
|
||||
return (
|
||||
<section>
|
||||
<h1>Home page content</h1>
|
||||
<StatsManager className="mt-12 grid grid-cols-1 lg:grid-cols-2 lg:gap-16" />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
10
apps/stats-mainnet-e2e/.eslintrc.json
Normal file
10
apps/stats-mainnet-e2e/.eslintrc.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": ["plugin:cypress/recommended", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
14
apps/stats-mainnet-e2e/cypress.json
Normal file
14
apps/stats-mainnet-e2e/cypress.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3010",
|
||||
"projectId": "et4snf",
|
||||
"fileServerFolder": ".",
|
||||
"fixturesFolder": "./src/fixtures",
|
||||
"integrationFolder": "./src/integration",
|
||||
"modifyObstructiveCode": false,
|
||||
"supportFile": "./src/support/index.ts",
|
||||
"pluginsFile": false,
|
||||
"video": true,
|
||||
"videosFolder": "../../dist/cypress/apps/stats-mainnet-e2e/videos",
|
||||
"screenshotsFolder": "../../dist/cypress/apps/stats-mainnet-e2e/screenshots",
|
||||
"chromeWebSecurity": false
|
||||
}
|
28
apps/stats-mainnet-e2e/project.json
Normal file
28
apps/stats-mainnet-e2e/project.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"root": "apps/stats-mainnet-e2e",
|
||||
"sourceRoot": "apps/stats-mainnet-e2e/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"e2e": {
|
||||
"executor": "@nrwl/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/stats-mainnet-e2e/cypress.json",
|
||||
"devServerTarget": "stats-mainnet:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "stats-mainnet:serve:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/stats-mainnet-e2e/**/*.{js,ts}"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"implicitDependencies": ["stats-mainnet"]
|
||||
}
|
4
apps/stats-mainnet-e2e/src/fixtures/example.json
Normal file
4
apps/stats-mainnet-e2e/src/fixtures/example.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io"
|
||||
}
|
7
apps/stats-mainnet-e2e/src/integration/app.spec.ts
Normal file
7
apps/stats-mainnet-e2e/src/integration/app.spec.ts
Normal file
@ -0,0 +1,7 @@
|
||||
describe('stats-mainnet', () => {
|
||||
beforeEach(() => cy.visit('/'));
|
||||
|
||||
it('should display header', () => {
|
||||
cy.get('h3').should('have.text', '/ Mainnet');
|
||||
});
|
||||
});
|
33
apps/stats-mainnet-e2e/src/support/commands.ts
Normal file
33
apps/stats-mainnet-e2e/src/support/commands.ts
Normal file
@ -0,0 +1,33 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
declare namespace Cypress {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface Chainable<Subject> {
|
||||
login(email: string, password: string): void;
|
||||
}
|
||||
}
|
||||
//
|
||||
// -- This is a parent command --
|
||||
Cypress.Commands.add('login', (email, password) => {
|
||||
console.log('Custom command example: Login', email, password);
|
||||
});
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
17
apps/stats-mainnet-e2e/src/support/index.ts
Normal file
17
apps/stats-mainnet-e2e/src/support/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
10
apps/stats-mainnet-e2e/tsconfig.json
Normal file
10
apps/stats-mainnet-e2e/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"sourceMap": false,
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"allowJs": true,
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.js"]
|
||||
}
|
11
apps/stats-mainnet/.babelrc
Normal file
11
apps/stats-mainnet/.babelrc
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nrwl/react/babel",
|
||||
{
|
||||
"runtime": "automatic"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
16
apps/stats-mainnet/.browserslistrc
Normal file
16
apps/stats-mainnet/.browserslistrc
Normal file
@ -0,0 +1,16 @@
|
||||
# This file is used by:
|
||||
# 1. autoprefixer to adjust CSS to support the below specified browsers
|
||||
# 2. babel preset-env to adjust included polyfills
|
||||
#
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
#
|
||||
# If you need to support different browsers in production, you may tweak the list below.
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major version
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
18
apps/stats-mainnet/.eslintrc.json
Normal file
18
apps/stats-mainnet/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
10
apps/stats-mainnet/jest.config.js
Normal file
10
apps/stats-mainnet/jest.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
displayName: 'stats-mainnet',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest',
|
||||
'^.+\\.[tj]sx?$': 'babel-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/apps/stats-mainnet',
|
||||
};
|
10
apps/stats-mainnet/postcss.config.js
Normal file
10
apps/stats-mainnet/postcss.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
const { join } = require('path');
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {
|
||||
config: join(__dirname, 'tailwind.config.js'),
|
||||
},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
74
apps/stats-mainnet/project.json
Normal file
74
apps/stats-mainnet/project.json
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"root": "apps/stats-mainnet",
|
||||
"sourceRoot": "apps/stats-mainnet/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/web:webpack",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
"compiler": "babel",
|
||||
"outputPath": "dist/apps/stats-mainnet",
|
||||
"index": "apps/stats-mainnet/src/index.html",
|
||||
"baseHref": "/",
|
||||
"main": "apps/stats-mainnet/src/main.tsx",
|
||||
"polyfills": "apps/stats-mainnet/src/polyfills.ts",
|
||||
"tsConfig": "apps/stats-mainnet/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/stats-mainnet/src/assets/favicon.ico",
|
||||
"apps/stats-mainnet/src/assets"
|
||||
],
|
||||
"styles": ["apps/stats-mainnet/src/styles/styles.css"],
|
||||
"scripts": [],
|
||||
"webpackConfig": "@nrwl/react/plugins/webpack"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/stats-mainnet/src/environments/environment.ts",
|
||||
"with": "apps/stats-mainnet/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "@nrwl/web:dev-server",
|
||||
"options": {
|
||||
"port": 3010,
|
||||
"buildTarget": "stats-mainnet:build",
|
||||
"hmr": true
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "stats-mainnet:build:production",
|
||||
"hmr": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/stats-mainnet/**/*.{ts,tsx,js,jsx}"]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"outputs": ["coverage/apps/stats-mainnet"],
|
||||
"options": {
|
||||
"jestConfig": "apps/stats-mainnet/jest.config.js",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
24
apps/stats-mainnet/src/app.tsx
Normal file
24
apps/stats-mainnet/src/app.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Header } from './components/header';
|
||||
import { StatsManager } from '@vegaprotocol/mainnet-stats-manager';
|
||||
|
||||
function App() {
|
||||
const [darkMode, setDarkMode] = useState<boolean>(
|
||||
document.documentElement.classList.contains('dark-mode-preferred')
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-screen min-h-screen grid pb-24 ${
|
||||
darkMode ? 'bg-black text-white-80' : 'bg-white text-black-95'
|
||||
}`}
|
||||
>
|
||||
<div className="layout-grid w-screen justify-self-center">
|
||||
<Header darkMode={darkMode} setDarkMode={setDarkMode} />
|
||||
<StatsManager className="max-w-3xl px-24" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
BIN
apps/stats-mainnet/src/assets/apple-touch-icon.png
Normal file
BIN
apps/stats-mainnet/src/assets/apple-touch-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
apps/stats-mainnet/src/assets/favicon.ico
Normal file
BIN
apps/stats-mainnet/src/assets/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
BIN
apps/stats-mainnet/src/assets/logo.png
Normal file
BIN
apps/stats-mainnet/src/assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 547 B |
BIN
apps/stats-mainnet/src/assets/logo192.png
Normal file
BIN
apps/stats-mainnet/src/assets/logo192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
20
apps/stats-mainnet/src/assets/manifest.json
Normal file
20
apps/stats-mainnet/src/assets/manifest.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"short_name": "Mainnet Stats",
|
||||
"name": "Vega Mainnet statistics",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
3
apps/stats-mainnet/src/assets/robots.txt
Normal file
3
apps/stats-mainnet/src/assets/robots.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
32
apps/stats-mainnet/src/components/header/header.tsx
Normal file
32
apps/stats-mainnet/src/components/header/header.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { VegaLogo } from '@vegaprotocol/ui-toolkit';
|
||||
import { LightModeToggle, DarkModeToggle } from '../images';
|
||||
import { VegaBackgroundVideo } from '../videos';
|
||||
import { DarkModeState } from '../../config/types';
|
||||
|
||||
export const Header = ({ darkMode, setDarkMode }: DarkModeState) => {
|
||||
return (
|
||||
<header className="relative overflow-hidden py-8 mb-40 md:mb-64">
|
||||
<VegaBackgroundVideo />
|
||||
|
||||
<div
|
||||
className={`relative flex justify-center px-8 ${
|
||||
darkMode ? 'bg-black' : 'bg-white'
|
||||
}`}
|
||||
>
|
||||
<div className="w-full max-w-3xl p-20 flex items-center justify-between">
|
||||
<VegaLogo />
|
||||
|
||||
<button
|
||||
onClick={() => setDarkMode(!darkMode)}
|
||||
aria-label="Switch theme color"
|
||||
className={`transition-colors rounded-full cursor-pointer ${
|
||||
darkMode ? 'hover:bg-neutral-900' : 'hover:bg-neutral-200'
|
||||
}`}
|
||||
>
|
||||
{darkMode ? <LightModeToggle /> : <DarkModeToggle />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
1
apps/stats-mainnet/src/components/header/index.ts
Normal file
1
apps/stats-mainnet/src/components/header/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { Header } from './header';
|
@ -0,0 +1,18 @@
|
||||
export const DarkModeToggle = () => {
|
||||
return (
|
||||
<svg width="45" height="45">
|
||||
<g>
|
||||
<path
|
||||
d="M22.5 27.79a5.29 5.29 0 1 0 0-10.58 5.29 5.29 0 0 0 0 10.58Z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
<path
|
||||
d="M15.01 22.5H10M35 22.5h-5.01M22.5 29.99V35M22.5 10v5.01M17.21 27.79l-3.55 3.55M31.34 13.66l-3.55 3.55M27.79 27.79l3.55 3.55M13.66 13.66l3.55 3.55"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.3"
|
||||
strokeMiterlimit="10"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
2
apps/stats-mainnet/src/components/images/index.ts
Normal file
2
apps/stats-mainnet/src/components/images/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export { DarkModeToggle } from './dark-mode-toggle';
|
||||
export { LightModeToggle } from './light-mode-toggle';
|
@ -0,0 +1,10 @@
|
||||
export const LightModeToggle = () => {
|
||||
return (
|
||||
<svg width="45" height="45">
|
||||
<path
|
||||
d="M28.75 11.69A12.39 12.39 0 0 0 22.5 10a12.5 12.5 0 1 0 0 25c2.196 0 4.353-.583 6.25-1.69A12.46 12.46 0 0 0 35 22.5a12.46 12.46 0 0 0-6.25-10.81Zm-6.25 22a11.21 11.21 0 0 1-11.2-11.2 11.21 11.21 0 0 1 11.2-11.2c1.246 0 2.484.209 3.66.62a13.861 13.861 0 0 0-5 10.58 13.861 13.861 0 0 0 5 10.58 11.078 11.078 0 0 1-3.66.63v-.01Z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
};
|
1
apps/stats-mainnet/src/components/videos/index.ts
Normal file
1
apps/stats-mainnet/src/components/videos/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { VegaBackgroundVideo } from './vega-background-video';
|
@ -0,0 +1,16 @@
|
||||
export const VegaBackgroundVideo = () => {
|
||||
return (
|
||||
<video
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
className="absolute left-0 top-0 w-full h-auto"
|
||||
>
|
||||
<source
|
||||
src="https://d33wubrfki0l68.cloudfront.net/2500bc5ef1b96927e0220eeb2bef0b22b87bcda1/3e0d3/static/moshed-aa65f0933af9abe9afb5e5663c9b3f68.mp4"
|
||||
type="video/mp4"
|
||||
/>
|
||||
</video>
|
||||
);
|
||||
};
|
4
apps/stats-mainnet/src/config/types.ts
Normal file
4
apps/stats-mainnet/src/config/types.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface DarkModeState {
|
||||
darkMode: boolean;
|
||||
setDarkMode: (arg0: boolean) => void;
|
||||
}
|
52
apps/stats-mainnet/src/index.html
Normal file
52
apps/stats-mainnet/src/index.html
Normal file
@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="assets/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Health check for Vega's mainnet" />
|
||||
<link rel="apple-touch-icon" href="assets/apple-touch-icon.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="assets/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>Vega Mainnet Stats</title>
|
||||
<script>
|
||||
// Set dark mode preference indicator here to avoid FOUC
|
||||
if (
|
||||
localStorage.theme === 'dark' ||
|
||||
(!('theme' in localStorage) &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
document.documentElement.classList.add('dark-mode-preferred');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark-mode-preferred');
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
17
apps/stats-mainnet/src/main.tsx
Normal file
17
apps/stats-mainnet/src/main.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './styles/styles.css';
|
||||
import App from './app';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
7
apps/stats-mainnet/src/polyfills.ts
Normal file
7
apps/stats-mainnet/src/polyfills.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Polyfill stable language features. These imports will be optimized by `@babel/preset-env`.
|
||||
*
|
||||
* See: https://github.com/zloirock/core-js#babel
|
||||
*/
|
||||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
1
apps/stats-mainnet/src/react-app-env.d.ts
vendored
Normal file
1
apps/stats-mainnet/src/react-app-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="react-scripts" />
|
15
apps/stats-mainnet/src/reportWebVitals.ts
Normal file
15
apps/stats-mainnet/src/reportWebVitals.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { ReportHandler } from 'web-vitals';
|
||||
|
||||
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
5
apps/stats-mainnet/src/setupTests.ts
Normal file
5
apps/stats-mainnet/src/setupTests.ts
Normal file
@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
BIN
apps/stats-mainnet/src/styles/AlphaLyrae-Medium.woff
Normal file
BIN
apps/stats-mainnet/src/styles/AlphaLyrae-Medium.woff
Normal file
Binary file not shown.
39
apps/stats-mainnet/src/styles/styles.css
Normal file
39
apps/stats-mainnet/src/styles/styles.css
Normal file
@ -0,0 +1,39 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
|
||||
@font-face {
|
||||
font-family: 'AlphaLyrae-Medium';
|
||||
src: url('./AlphaLyrae-Medium.woff');
|
||||
}
|
||||
|
||||
.layout-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: repeat(2, auto) 1fr;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.stats-grid {
|
||||
grid-template-columns: 18rem 1fr;
|
||||
grid-column-gap: 1.25rem;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.promoted-stats {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.promoted-stats {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@tailwind utilities;
|
12
apps/stats-mainnet/tailwind.config.js
Normal file
12
apps/stats-mainnet/tailwind.config.js
Normal file
@ -0,0 +1,12 @@
|
||||
const { join } = require('path');
|
||||
const { createGlobPatternsForDependencies } = require('@nrwl/next/tailwind');
|
||||
const theme = require('../../libs/tailwindcss-config/src/theme');
|
||||
|
||||
module.exports = {
|
||||
content: [
|
||||
join(__dirname, 'src/**/*.{js,ts,jsx,tsx}'),
|
||||
...createGlobPatternsForDependencies(__dirname),
|
||||
],
|
||||
theme,
|
||||
plugins: [],
|
||||
};
|
22
apps/stats-mainnet/tsconfig.app.json
Normal file
22
apps/stats-mainnet/tsconfig.app.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": [
|
||||
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
|
||||
"../../node_modules/@nrwl/react/typings/image.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.test.jsx"
|
||||
],
|
||||
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
|
||||
}
|
25
apps/stats-mainnet/tsconfig.json
Normal file
25
apps/stats-mainnet/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
23
apps/stats-mainnet/tsconfig.spec.json
Normal file
23
apps/stats-mainnet/tsconfig.spec.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.jsx",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.d.ts"
|
||||
],
|
||||
"files": [
|
||||
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
|
||||
"../../node_modules/@nrwl/react/typings/image.d.ts"
|
||||
]
|
||||
}
|
12
libs/mainnet-stats-manager/.babelrc
Normal file
12
libs/mainnet-stats-manager/.babelrc
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nrwl/react/babel",
|
||||
{
|
||||
"runtime": "automatic",
|
||||
"useBuiltIns": "usage"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
18
libs/mainnet-stats-manager/.eslintrc.json
Normal file
18
libs/mainnet-stats-manager/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
7
libs/mainnet-stats-manager/README.md
Normal file
7
libs/mainnet-stats-manager/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# mainnet-stats-manager
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test mainnet-stats-manager` to execute the unit tests via [Jest](https://jestjs.io).
|
9
libs/mainnet-stats-manager/jest.config.js
Normal file
9
libs/mainnet-stats-manager/jest.config.js
Normal file
@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
displayName: 'mainnet-stats-manager',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\.[tj]sx?$': 'babel-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/libs/mainnet-stats-manager',
|
||||
};
|
4
libs/mainnet-stats-manager/package.json
Normal file
4
libs/mainnet-stats-manager/package.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "@vegaprotocol/mainnet-stats-manager",
|
||||
"version": "0.0.1"
|
||||
}
|
43
libs/mainnet-stats-manager/project.json
Normal file
43
libs/mainnet-stats-manager/project.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"root": "libs/mainnet-stats-manager",
|
||||
"sourceRoot": "libs/mainnet-stats-manager/src",
|
||||
"projectType": "library",
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/web:rollup",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/libs/mainnet-stats-manager",
|
||||
"tsConfig": "libs/mainnet-stats-manager/tsconfig.lib.json",
|
||||
"project": "libs/mainnet-stats-manager/package.json",
|
||||
"entryFile": "libs/mainnet-stats-manager/src/index.ts",
|
||||
"external": ["react/jsx-runtime"],
|
||||
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
|
||||
"compiler": "babel",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "libs/mainnet-stats-manager/README.md",
|
||||
"input": ".",
|
||||
"output": "."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["libs/mainnet-stats-manager/**/*.{ts,tsx,js,jsx}"]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"outputs": ["coverage/libs/mainnet-stats-manager"],
|
||||
"options": {
|
||||
"jestConfig": "libs/mainnet-stats-manager/jest.config.js",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { value, goodThreshold } from '../../config/types';
|
||||
|
||||
interface GoodThresholdIndicatorProps {
|
||||
goodThreshold: goodThreshold | undefined;
|
||||
value: value;
|
||||
}
|
||||
|
||||
export const GoodThresholdIndicator = ({
|
||||
goodThreshold,
|
||||
value,
|
||||
}: GoodThresholdIndicatorProps) => {
|
||||
return (
|
||||
<div
|
||||
className={`inline-block w-8 h-8 mb-[0.15rem] mr-8 rounded ${
|
||||
(goodThreshold &&
|
||||
(goodThreshold(value) ? 'bg-intent-success' : 'bg-intent-danger')) ||
|
||||
'bg-current'
|
||||
}`}
|
||||
/>
|
||||
);
|
||||
};
|
@ -0,0 +1 @@
|
||||
export { GoodThresholdIndicator } from './good-threshold-indicator';
|
@ -0,0 +1 @@
|
||||
export { PromotedStatsItem } from './promoted-stats-item';
|
@ -0,0 +1,26 @@
|
||||
import { Tooltip } from '../tooltip';
|
||||
import { StatFields } from '../../config/types';
|
||||
import { defaultFieldFormatter } from '../table-row';
|
||||
import { GoodThresholdIndicator } from '../good-threshold-indicator';
|
||||
|
||||
export const PromotedStatsItem = ({
|
||||
title,
|
||||
formatter,
|
||||
goodThreshold,
|
||||
value,
|
||||
description,
|
||||
}: StatFields) => {
|
||||
return (
|
||||
<Tooltip description={description}>
|
||||
<div className="px-24 py-16 pr-64 border items-center">
|
||||
<div className="uppercase text-[0.9375rem]">
|
||||
<GoodThresholdIndicator goodThreshold={goodThreshold} value={value} />
|
||||
<span>{title}</span>
|
||||
</div>
|
||||
<div className="mt-4 text-h4 leading-none">
|
||||
{formatter ? formatter(value) : defaultFieldFormatter(value)}
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
@ -0,0 +1 @@
|
||||
export { PromotedStats } from './promoted-stats';
|
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
|
||||
interface PromotedStatsProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const PromotedStats = ({ children }: PromotedStatsProps) => {
|
||||
return (
|
||||
<div className="grid promoted-stats content-start gap-4 mb-24">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1 @@
|
||||
export { StatsManager } from './stats-manager';
|
@ -0,0 +1,120 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { statsFields } from '../../config/stats-fields';
|
||||
import {
|
||||
Stats as IStats,
|
||||
StructuredStats as IStructuredStats,
|
||||
} from '../../config/types';
|
||||
import { Table } from '../table';
|
||||
import { TableRow } from '../table-row';
|
||||
import { PromotedStats } from '../promoted-stats';
|
||||
import { PromotedStatsItem } from '../promoted-stats-item';
|
||||
|
||||
interface statsManagerProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const StatsManager = ({ className }: statsManagerProps) => {
|
||||
const [data, setData] = useState<IStructuredStats | null>(null);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
async function getStats() {
|
||||
try {
|
||||
const [res1, res2] = await Promise.all([
|
||||
fetch('https://api.token.vega.xyz/statistics'),
|
||||
fetch('https://api.token.vega.xyz/nodes-data'),
|
||||
]);
|
||||
const [{ statistics }, { nodeData }] = await Promise.all([
|
||||
res1.json(),
|
||||
res2.json(),
|
||||
]);
|
||||
const returned = { ...nodeData, ...statistics };
|
||||
|
||||
if (!statistics || !nodeData) {
|
||||
throw new Error('Failed to get data from endpoints');
|
||||
}
|
||||
|
||||
// Loop through the stats fields config, grabbing values from the fetched
|
||||
// data and building a set of promoted and standard table entries.
|
||||
const structured = Object.entries(statsFields).reduce(
|
||||
(acc, [key, value]) => {
|
||||
const statKey = key as keyof IStats;
|
||||
const statData = returned[statKey];
|
||||
|
||||
value.forEach((x) => {
|
||||
const stat = {
|
||||
...x,
|
||||
value: statData,
|
||||
};
|
||||
|
||||
stat.promoted ? acc.promoted.push(stat) : acc.table.push(stat);
|
||||
});
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ promoted: [], table: [] } as IStructuredStats
|
||||
);
|
||||
|
||||
setData(structured);
|
||||
setError(null);
|
||||
} catch (e) {
|
||||
setData(null);
|
||||
setError(e as Error);
|
||||
}
|
||||
}
|
||||
|
||||
const interval = setInterval(getStats, 1000);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const classes = classnames(
|
||||
className,
|
||||
'stats-grid w-full self-start justify-self-center'
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<h3 className="font-alpha uppercase text-h3 pb-16 col-span-full">
|
||||
{(error && `/ ${error}`) || (data ? '/ Mainnet' : '/ Connecting...')}
|
||||
</h3>
|
||||
|
||||
{data?.promoted ? (
|
||||
<PromotedStats>
|
||||
{data.promoted.map((stat, i) => {
|
||||
return (
|
||||
<PromotedStatsItem
|
||||
title={stat.title}
|
||||
value={stat.value}
|
||||
formatter={stat.formatter}
|
||||
goodThreshold={stat.goodThreshold}
|
||||
description={stat.description}
|
||||
key={i}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</PromotedStats>
|
||||
) : null}
|
||||
|
||||
<Table>
|
||||
{data?.table
|
||||
? data.table.map((stat, i) => {
|
||||
return (
|
||||
<TableRow
|
||||
title={stat.title}
|
||||
value={stat.value}
|
||||
formatter={stat.formatter}
|
||||
goodThreshold={stat.goodThreshold}
|
||||
description={stat.description}
|
||||
key={i}
|
||||
/>
|
||||
);
|
||||
})
|
||||
: null}
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1 @@
|
||||
export { TableRow, defaultFieldFormatter } from './table-row';
|
@ -0,0 +1,28 @@
|
||||
import { Tooltip } from '../tooltip';
|
||||
import { StatFields } from '../../config/types';
|
||||
import { GoodThresholdIndicator } from '../good-threshold-indicator';
|
||||
|
||||
export const defaultFieldFormatter = (field: unknown) =>
|
||||
field === undefined ? 'no data' : field;
|
||||
|
||||
export const TableRow = ({
|
||||
title,
|
||||
formatter,
|
||||
goodThreshold,
|
||||
value,
|
||||
description,
|
||||
}: StatFields) => {
|
||||
return (
|
||||
<Tooltip description={description}>
|
||||
<tr className="border">
|
||||
<td className="py-4 px-8">{title}</td>
|
||||
<td className="py-4 px-8 text-right">
|
||||
{formatter ? formatter(value) : defaultFieldFormatter(value)}
|
||||
</td>
|
||||
<td className="py-4 px-8">
|
||||
<GoodThresholdIndicator goodThreshold={goodThreshold} value={value} />
|
||||
</td>
|
||||
</tr>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
1
libs/mainnet-stats-manager/src/components/table/index.ts
Normal file
1
libs/mainnet-stats-manager/src/components/table/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { Table } from './table';
|
13
libs/mainnet-stats-manager/src/components/table/table.tsx
Normal file
13
libs/mainnet-stats-manager/src/components/table/table.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
|
||||
interface TableProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Table = ({ children }: TableProps) => {
|
||||
return (
|
||||
<table>
|
||||
<tbody>{children}</tbody>
|
||||
</table>
|
||||
);
|
||||
};
|
@ -0,0 +1 @@
|
||||
export { Tooltip } from './tooltip';
|
@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Provider,
|
||||
Root,
|
||||
Trigger,
|
||||
Content,
|
||||
Arrow,
|
||||
} from '@radix-ui/react-tooltip';
|
||||
|
||||
interface TooltipProps {
|
||||
children: React.ReactElement;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
// Conditionally rendered tooltip if description content is provided.
|
||||
export const Tooltip = ({ children, description }: TooltipProps) =>
|
||||
description ? (
|
||||
<Provider delayDuration={200} skipDelayDuration={100}>
|
||||
<Root>
|
||||
<Trigger asChild>{children}</Trigger>
|
||||
<Content align={'start'} alignOffset={5}>
|
||||
<Arrow
|
||||
width={10}
|
||||
height={5}
|
||||
offset={10}
|
||||
className="fill-vega-green"
|
||||
/>
|
||||
<div className="px-12 py-8 bg-vega-green text-black rounded-sm max-w-sm">
|
||||
{description}
|
||||
</div>
|
||||
</Content>
|
||||
</Root>
|
||||
</Provider>
|
||||
) : (
|
||||
children
|
||||
);
|
174
libs/mainnet-stats-manager/src/config/stats-fields.ts
Normal file
174
libs/mainnet-stats-manager/src/config/stats-fields.ts
Normal file
@ -0,0 +1,174 @@
|
||||
import { Stats as IStats, StatFields as IStatFields } from './types';
|
||||
|
||||
// Stats fields config. Keys will correspond to graphql queries when used, and values
|
||||
// contain the associated data and methods we need to render. A single query
|
||||
// can be rendered in multiple ways (see 'upTime').
|
||||
export const statsFields: { [key in keyof IStats]: IStatFields[] } = {
|
||||
status: [
|
||||
{
|
||||
title: 'Status',
|
||||
formatter: (status: string) => {
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
|
||||
const i = status.lastIndexOf('_');
|
||||
if (i === -1) {
|
||||
return status;
|
||||
} else {
|
||||
return status.substr(i + 1);
|
||||
}
|
||||
},
|
||||
goodThreshold: (status: string) =>
|
||||
status === 'CONNECTED' || status === 'CHAIN_STATUS_CONNECTED',
|
||||
promoted: true,
|
||||
description:
|
||||
'Status is either connected, replaying, unspecified or disconnected',
|
||||
},
|
||||
],
|
||||
blockHeight: [
|
||||
{
|
||||
title: 'Height',
|
||||
goodThreshold: (height: number) => height >= 60,
|
||||
promoted: true,
|
||||
description: 'Block height',
|
||||
},
|
||||
],
|
||||
totalNodes: [
|
||||
{
|
||||
title: 'Total nodes',
|
||||
description: 'The total number of nodes registered on the network',
|
||||
},
|
||||
],
|
||||
validatingNodes: [
|
||||
{
|
||||
title: 'Validating nodes',
|
||||
promoted: true,
|
||||
description: 'Nodes participating in consensus',
|
||||
},
|
||||
],
|
||||
inactiveNodes: [
|
||||
{
|
||||
title: 'Inactive nodes',
|
||||
goodThreshold: (totalInactive: number) => totalInactive < 1,
|
||||
description: 'Nodes that are registered but not validating',
|
||||
},
|
||||
],
|
||||
stakedTotal: [
|
||||
{
|
||||
title: 'Total staked',
|
||||
formatter: (total: string) =>
|
||||
total.length > 18 &&
|
||||
parseInt(total.substring(0, total.length - 18)).toLocaleString('en-US'),
|
||||
description: 'Sum of VEGA associated with a Vega key',
|
||||
},
|
||||
],
|
||||
backlogLength: [
|
||||
{
|
||||
title: 'Backlog',
|
||||
goodThreshold: (length: number, blockDuration: number) => {
|
||||
return (
|
||||
length < 1000 || (length >= 1000 && blockDuration / 1000000000 <= 1)
|
||||
);
|
||||
},
|
||||
description: 'Number of transactions waiting to be processed',
|
||||
},
|
||||
],
|
||||
tradesPerSecond: [
|
||||
{
|
||||
title: 'Trades / second',
|
||||
goodThreshold: (trades: number) => trades >= 2,
|
||||
description: 'Number of trades processed in the last second',
|
||||
},
|
||||
],
|
||||
averageOrdersPerBlock: [
|
||||
{
|
||||
title: 'Orders / block',
|
||||
goodThreshold: (orders: number) => orders >= 2,
|
||||
description:
|
||||
'Number of new orders processed in the last block. All pegged orders and liquidity provisions count as a single order',
|
||||
},
|
||||
],
|
||||
ordersPerSecond: [
|
||||
{
|
||||
title: 'Orders / second',
|
||||
goodThreshold: (orders: number) => orders >= 2,
|
||||
description:
|
||||
'Number of orders processed in the last second. All pegged orders and liquidity provisions count as a single order',
|
||||
},
|
||||
],
|
||||
txPerBlock: [
|
||||
{
|
||||
title: 'Transactions / block',
|
||||
goodThreshold: (tx: number) => tx > 2,
|
||||
description: 'Number of transactions processed in the last block',
|
||||
},
|
||||
],
|
||||
blockDuration: [
|
||||
{
|
||||
title: 'Block time',
|
||||
formatter: (duration: number) => (duration / 1000000000).toFixed(3),
|
||||
goodThreshold: (blockDuration: number) =>
|
||||
blockDuration > 0 && blockDuration <= 2000000000,
|
||||
description: 'Seconds between the two most recent blocks',
|
||||
},
|
||||
],
|
||||
vegaTime: [
|
||||
{
|
||||
title: 'Time',
|
||||
formatter: (time: Date) => new Date(time).toLocaleTimeString(),
|
||||
goodThreshold: (time: Date) => {
|
||||
const diff = new Date().getTime() - new Date(time).getTime();
|
||||
return diff > 0 && diff < 5000;
|
||||
},
|
||||
description: 'The time on the blockchain',
|
||||
},
|
||||
],
|
||||
appVersion: [
|
||||
{
|
||||
title: 'App',
|
||||
description: 'Vega node software version on this node',
|
||||
},
|
||||
],
|
||||
chainVersion: [
|
||||
{
|
||||
title: 'Tendermint',
|
||||
description: 'Tendermint software version on this node',
|
||||
},
|
||||
],
|
||||
uptime: [
|
||||
{
|
||||
title: 'Uptime',
|
||||
formatter: (t: string) => {
|
||||
if (!t) {
|
||||
return;
|
||||
}
|
||||
const secSinceStart =
|
||||
(new Date().getTime() - new Date(t).getTime()) / 1000;
|
||||
const days = Math.floor(secSinceStart / 60 / 60 / 24);
|
||||
const hours = Math.floor((secSinceStart / 60 / 60) % 24);
|
||||
const mins = Math.floor((secSinceStart / 60) % 60);
|
||||
const secs = Math.floor(secSinceStart % 60);
|
||||
return `${days}d ${hours}h ${mins}m ${secs}s`;
|
||||
},
|
||||
promoted: true,
|
||||
description: 'Time since genesis',
|
||||
},
|
||||
{
|
||||
title: 'Up since',
|
||||
formatter: (t: string) => {
|
||||
if (!t) {
|
||||
return;
|
||||
}
|
||||
return `${new Date(t).toLocaleString().replace(',', ' ')}`;
|
||||
},
|
||||
description: 'Genesis',
|
||||
},
|
||||
],
|
||||
chainId: [
|
||||
{
|
||||
title: 'Chain ID',
|
||||
description: 'Identifier',
|
||||
},
|
||||
],
|
||||
};
|
36
libs/mainnet-stats-manager/src/config/types.ts
Normal file
36
libs/mainnet-stats-manager/src/config/types.ts
Normal file
@ -0,0 +1,36 @@
|
||||
export interface Stats {
|
||||
blockHeight: string;
|
||||
totalNodes: string;
|
||||
validatingNodes: string;
|
||||
inactiveNodes: string;
|
||||
stakedTotal: string;
|
||||
backlogLength: string;
|
||||
tradesPerSecond: string;
|
||||
averageOrdersPerBlock: string;
|
||||
ordersPerSecond: string;
|
||||
txPerBlock: string;
|
||||
blockDuration: string;
|
||||
status: string;
|
||||
vegaTime: string;
|
||||
appVersion: string;
|
||||
chainVersion: string;
|
||||
uptime: string;
|
||||
chainId: string;
|
||||
}
|
||||
|
||||
export type value = any;
|
||||
export type goodThreshold = (...args: value[]) => boolean;
|
||||
|
||||
export interface StatFields {
|
||||
title: string;
|
||||
goodThreshold?: goodThreshold;
|
||||
formatter?: (arg0: value) => any;
|
||||
promoted?: boolean;
|
||||
value?: value;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface StructuredStats {
|
||||
promoted: StatFields[];
|
||||
table: StatFields[];
|
||||
}
|
1
libs/mainnet-stats-manager/src/index.ts
Normal file
1
libs/mainnet-stats-manager/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { StatsManager } from './components/stats-manager';
|
25
libs/mainnet-stats-manager/tsconfig.json
Normal file
25
libs/mainnet-stats-manager/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
22
libs/mainnet-stats-manager/tsconfig.lib.json
Normal file
22
libs/mainnet-stats-manager/tsconfig.lib.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": [
|
||||
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
|
||||
"../../node_modules/@nrwl/react/typings/image.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.test.jsx"
|
||||
],
|
||||
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
|
||||
}
|
19
libs/mainnet-stats-manager/tsconfig.spec.json
Normal file
19
libs/mainnet-stats-manager/tsconfig.spec.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.jsx",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
@ -2,7 +2,9 @@ const defaultTheme = require('tailwindcss/defaultTheme');
|
||||
|
||||
module.exports = {
|
||||
screens: {
|
||||
sm: '500px',
|
||||
xs: '500px',
|
||||
sm: '640px',
|
||||
md: '768px',
|
||||
lg: '960px',
|
||||
},
|
||||
colors: {
|
||||
@ -63,7 +65,9 @@ module.exports = {
|
||||
24: '1.5rem',
|
||||
28: '1.75rem',
|
||||
32: '2rem',
|
||||
40: '2.5rem',
|
||||
44: '2.75rem',
|
||||
64: '4rem',
|
||||
},
|
||||
opacity: {
|
||||
0: '0',
|
||||
|
1
libs/ui-toolkit/src/components/vega-logo/index.ts
Normal file
1
libs/ui-toolkit/src/components/vega-logo/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './vega-logo';
|
11
libs/ui-toolkit/src/components/vega-logo/lozenge.stories.tsx
Normal file
11
libs/ui-toolkit/src/components/vega-logo/lozenge.stories.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import { Story, Meta } from '@storybook/react';
|
||||
import { VegaLogo } from './vega-logo';
|
||||
|
||||
export default {
|
||||
component: VegaLogo,
|
||||
title: 'Vega logo',
|
||||
} as Meta;
|
||||
|
||||
const Template: Story = () => <VegaLogo />;
|
||||
|
||||
export const Default = Template.bind({});
|
10
libs/ui-toolkit/src/components/vega-logo/vega-logo.spec.tsx
Normal file
10
libs/ui-toolkit/src/components/vega-logo/vega-logo.spec.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
import { VegaLogo } from './vega-logo';
|
||||
|
||||
describe('Vega logo', () => {
|
||||
it('should render successfully', () => {
|
||||
const { baseElement } = render(<VegaLogo />);
|
||||
expect(baseElement).toBeTruthy();
|
||||
});
|
||||
});
|
16
libs/ui-toolkit/src/components/vega-logo/vega-logo.tsx
Normal file
16
libs/ui-toolkit/src/components/vega-logo/vega-logo.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
export const VegaLogo = () => {
|
||||
return (
|
||||
<svg
|
||||
aria-label="Vega logo"
|
||||
width="111"
|
||||
height="24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M10.371 20.794 17.183.02h3.42l-8.436 23.965H8.471L0 .02h3.48l6.891 20.774ZM34.994 13.019v8.249h13.382v2.716H31.782V.019h16.3v2.715H34.994v7.577h11.658v2.708H34.994ZM61.25 2.92h2.88v18.195h-2.88V2.92ZM75.653 0v2.92H64.129V0h11.525ZM64.129 24v-2.885h11.525V24H64.129Zm14.405-2.885h-2.88v-5.77h-5.762v-2.89h8.642v8.66Zm0-18.195v2.884h-2.88V2.92h2.88ZM110.71 23.984h-3.354l-1.763-4.826h-12.03L91.8 23.984h-3.279L97.807.019h3.626l9.277 23.965ZM99.528 2.904l-4.949 13.544h10.002L99.597 2.903h-.07Z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
};
|
@ -17,6 +17,7 @@ export { Splash } from './components/splash';
|
||||
export { TextArea } from './components/text-area';
|
||||
export { ThemeSwitcher } from './components/theme-switcher';
|
||||
export { Dialog } from './components/dialog/dialog';
|
||||
export { VegaLogo } from './components/vega-logo';
|
||||
|
||||
// Utils
|
||||
export * from './utils/intent';
|
||||
|
@ -19,6 +19,7 @@
|
||||
"@nrwl/next": "13.8.1",
|
||||
"@radix-ui/react-dialog": "^0.1.5",
|
||||
"@radix-ui/react-tabs": "^0.1.5",
|
||||
"@radix-ui/react-tooltip": "^0.1.7",
|
||||
"@sentry/react": "^6.18.1",
|
||||
"@sentry/tracing": "^6.18.1",
|
||||
"@types/uuid": "^8.3.4",
|
||||
@ -51,7 +52,8 @@
|
||||
"sha3": "^2.1.4",
|
||||
"tailwindcss": "^3.0.23",
|
||||
"tslib": "^2.0.0",
|
||||
"uuid": "^8.3.2"
|
||||
"uuid": "^8.3.2",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.12.13",
|
||||
|
@ -17,6 +17,9 @@
|
||||
"paths": {
|
||||
"@vegaprotocol/deal-ticket": ["libs/deal-ticket/src/index.ts"],
|
||||
"@vegaprotocol/graphql": ["libs/graphql/src/index.ts"],
|
||||
"@vegaprotocol/mainnet-stats-manager": [
|
||||
"libs/mainnet-stats-manager/src/index.ts"
|
||||
],
|
||||
"@vegaprotocol/market-list": ["libs/market-list/src/index.ts"],
|
||||
"@vegaprotocol/react-helpers": ["libs/react-helpers/src/index.ts"],
|
||||
"@vegaprotocol/tailwindcss-config": [
|
||||
|
@ -5,8 +5,11 @@
|
||||
"explorer": "apps/explorer",
|
||||
"explorer-e2e": "apps/explorer-e2e",
|
||||
"graphql": "libs/graphql",
|
||||
"mainnet-stats-manager": "libs/mainnet-stats-manager",
|
||||
"market-list": "libs/market-list",
|
||||
"react-helpers": "libs/react-helpers",
|
||||
"stats-mainnet": "apps/stats-mainnet",
|
||||
"stats-mainnet-e2e": "apps/stats-mainnet-e2e",
|
||||
"tailwindcss-config": "libs/tailwindcss-config",
|
||||
"trading": "apps/trading",
|
||||
"trading-e2e": "apps/trading-e2e",
|
||||
|
96
yarn.lock
96
yarn.lock
@ -3199,6 +3199,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9"
|
||||
integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==
|
||||
|
||||
"@radix-ui/popper@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/popper/-/popper-0.1.0.tgz#c387a38f31b7799e1ea0d2bb1ca0c91c2931b063"
|
||||
integrity sha512-uzYeElL3w7SeNMuQpXiFlBhTT+JyaNMCwDfjKkrzugEcYrf5n52PHqncNdQPUtR42hJh8V9FsqyEDbDxkeNjJQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
csstype "^3.0.4"
|
||||
|
||||
"@radix-ui/primitive@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-0.1.0.tgz#6206b97d379994f0d1929809db035733b337e543"
|
||||
@ -3206,6 +3214,14 @@
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
|
||||
"@radix-ui/react-arrow@0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-0.1.4.tgz#a871448a418cd3507d83840fdd47558cb961672b"
|
||||
integrity sha512-BB6XzAb7Ml7+wwpFdYVtZpK1BlMgqyafSQNGzhIpSZ4uXvXOHPlR5GP8M449JkeQzgQjv9Mp1AsJxFC0KuOtuA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-primitive" "0.1.4"
|
||||
|
||||
"@radix-ui/react-collection@0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-0.1.4.tgz#734061ffd5bb93e88889d49b87391a73a63824c9"
|
||||
@ -3290,6 +3306,21 @@
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-use-layout-effect" "0.1.0"
|
||||
|
||||
"@radix-ui/react-popper@0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-0.1.4.tgz#dfc055dcd7dfae6a2eff7a70d333141d15a5d029"
|
||||
integrity sha512-18gDYof97t8UQa7zwklG1Dr8jIdj3u+rVOQLzPi9f5i1YQak/pVGkaqw8aY+iDUknKKuZniTk/7jbAJUYlKyOw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/popper" "0.1.0"
|
||||
"@radix-ui/react-arrow" "0.1.4"
|
||||
"@radix-ui/react-compose-refs" "0.1.0"
|
||||
"@radix-ui/react-context" "0.1.1"
|
||||
"@radix-ui/react-primitive" "0.1.4"
|
||||
"@radix-ui/react-use-rect" "0.1.1"
|
||||
"@radix-ui/react-use-size" "0.1.1"
|
||||
"@radix-ui/rect" "0.1.1"
|
||||
|
||||
"@radix-ui/react-portal@0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-0.1.4.tgz#17bdce3d7f1a9a0b35cb5e935ab8bc562441a7d2"
|
||||
@ -3352,6 +3383,27 @@
|
||||
"@radix-ui/react-roving-focus" "0.1.5"
|
||||
"@radix-ui/react-use-controllable-state" "0.1.0"
|
||||
|
||||
"@radix-ui/react-tooltip@^0.1.7":
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-0.1.7.tgz#6f8c00d6e489565d14abf209ce0fb8853c8c8ee3"
|
||||
integrity sha512-eiBUsVOHenZ0JR16tl970bB0DafJBz6mFgSGfIGIVpflFj0LIsIDiLMsYyvYdx1KwwsIUDTEZtxcPm/sWjPzqA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/primitive" "0.1.0"
|
||||
"@radix-ui/react-compose-refs" "0.1.0"
|
||||
"@radix-ui/react-context" "0.1.1"
|
||||
"@radix-ui/react-id" "0.1.5"
|
||||
"@radix-ui/react-popper" "0.1.4"
|
||||
"@radix-ui/react-portal" "0.1.4"
|
||||
"@radix-ui/react-presence" "0.1.2"
|
||||
"@radix-ui/react-primitive" "0.1.4"
|
||||
"@radix-ui/react-slot" "0.1.2"
|
||||
"@radix-ui/react-use-controllable-state" "0.1.0"
|
||||
"@radix-ui/react-use-escape-keydown" "0.1.0"
|
||||
"@radix-ui/react-use-previous" "0.1.1"
|
||||
"@radix-ui/react-use-rect" "0.1.1"
|
||||
"@radix-ui/react-visually-hidden" "0.1.4"
|
||||
|
||||
"@radix-ui/react-use-body-pointer-events@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.1.1.tgz#63e7fd81ca7ffd30841deb584cd2b7f460df2597"
|
||||
@ -3390,6 +3442,43 @@
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
|
||||
"@radix-ui/react-use-previous@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-0.1.1.tgz#0226017f72267200f6e832a7103760e96a6db5d0"
|
||||
integrity sha512-O/ZgrDBr11dR8rhO59ED8s5zIXBRFi8MiS+CmFGfi7MJYdLbfqVOmQU90Ghf87aifEgWe6380LA69KBneaShAg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
|
||||
"@radix-ui/react-use-rect@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-0.1.1.tgz#6c15384beee59c086e75b89a7e66f3d2e583a856"
|
||||
integrity sha512-kHNNXAsP3/PeszEmM/nxBBS9Jbo93sO+xuMTcRfwzXsmxT5gDXQzAiKbZQ0EecCPtJIzqvr7dlaQi/aP1PKYqQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/rect" "0.1.1"
|
||||
|
||||
"@radix-ui/react-use-size@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-0.1.1.tgz#f6b75272a5d41c3089ca78c8a2e48e5f204ef90f"
|
||||
integrity sha512-pTgWM5qKBu6C7kfKxrKPoBI2zZYZmp2cSXzpUiGM3qEBQlMLtYhaY2JXdXUCxz+XmD1YEjc8oRwvyfsD4AG4WA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
|
||||
"@radix-ui/react-visually-hidden@0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-0.1.4.tgz#6c75eae34fb5d084b503506fbfc05587ced05f03"
|
||||
integrity sha512-K/q6AEEzqeeEq/T0NPChvBqnwlp8Tl4NnQdrI/y8IOY7BRR+Ug0PEsVk6g48HJ7cA1//COugdxXXVVK/m0X1mA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-primitive" "0.1.4"
|
||||
|
||||
"@radix-ui/rect@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-0.1.1.tgz#95b5ba51f469bea6b1b841e2d427e17e37d38419"
|
||||
integrity sha512-g3hnE/UcOg7REdewduRPAK88EPuLZtaq7sA9ouu8S+YEtnyFRI16jgv6GZYe3VMoQLL1T171ebmEPtDjyxWLzw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
|
||||
"@rollup/plugin-babel@^5.3.0":
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
|
||||
@ -8961,7 +9050,7 @@ csstype@^2.5.7:
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda"
|
||||
integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
|
||||
|
||||
csstype@^3.0.2:
|
||||
csstype@^3.0.2, csstype@^3.0.4:
|
||||
version "3.0.11"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33"
|
||||
integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==
|
||||
@ -19675,6 +19764,11 @@ web-namespaces@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec"
|
||||
integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==
|
||||
|
||||
web-vitals@^2.1.4:
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.4.tgz#76563175a475a5e835264d373704f9dde718290c"
|
||||
integrity sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
|
Loading…
Reference in New Issue
Block a user