diff --git a/main/background.ts b/main/background.ts index e97a73b..a87de78 100644 --- a/main/background.ts +++ b/main/background.ts @@ -18,6 +18,14 @@ let mainWindow: BrowserWindow; (async () => { await app.whenReady(); + // session.defaultSession.webRequest.onHeadersReceived((details, callback) => { + // callback({ + // responseHeaders: { + // ...details.responseHeaders, + // "Content-Security-Policy": ["script-src 'self' localhost:8888"], + // }, + // }); + // }); mainWindow = createWindow("main", { width: 1000, diff --git a/main/config.ts b/main/config.ts new file mode 100644 index 0000000..0c06d76 --- /dev/null +++ b/main/config.ts @@ -0,0 +1,40 @@ +import Store from "electron-store"; +import { ArweaveMinerUiConfig, ArweaveNodeConfig } from "../types/config"; + +const schema = { + nodes: { + type: "array" as const, + items: { + type: "object" as const, + properties: { + name: { + type: "string" as const, + }, + host: { + type: "string" as const, + }, + port: { + type: "number" as const, + }, + protocol: { + type: "string" as const, + }, + }, + required: ["name", "host", "port", "protocol"], + }, + }, +}; + +const store = new Store({ schema }); + +export const configHandler = { + configGetNodes: () => { + console.log(store); + return store.get("nodes") || []; + }, + configAppendNode: (node: ArweaveNodeConfig) => { + const currentNodes = store.get("nodes", []); + const newNodes = [...currentNodes, node]; + store.set("nodes", newNodes); + }, +}; diff --git a/main/helpers/create-window.ts b/main/helpers/create-window.ts index c686dfd..445bd63 100644 --- a/main/helpers/create-window.ts +++ b/main/helpers/create-window.ts @@ -79,8 +79,10 @@ export const createWindow = ( ...state, ...options, webPreferences: { - nodeIntegration: false, + nodeIntegration: true, + nodeIntegrationInWorker: true, contextIsolation: true, + sandbox: false, ...options.webPreferences, }, }); diff --git a/main/preload.ts b/main/preload.ts index fd0535c..e09254f 100644 --- a/main/preload.ts +++ b/main/preload.ts @@ -1,4 +1,5 @@ import { contextBridge, ipcRenderer, IpcRendererEvent } from "electron"; +import { configHandler } from "./config"; import { SetMetricsStateActionPayload } from "../types/metrics"; ipcRenderer.on("metricsPush", (_event, msg) => { @@ -26,6 +27,7 @@ const handler = { ipcRenderer.removeListener(channel, subscription); }; }, + ...configHandler, }; contextBridge.exposeInMainWorld("ipc", handler); diff --git a/package-lock.json b/package-lock.json index 5b6ab06..040b08d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,35 +11,38 @@ "license": "MIT", "dependencies": { "@reduxjs/toolkit": "^1.9.7", + "ajv": "^8.12.0", "arweave": "^1.14.4", - "electron-serve": "^1.1.0", + "electron-serve": "^1.2.0", "electron-store": "^8.1.0", "filesize": "^10.1.0", "next-redux-wrapper": "^8.1.0", "parse-prometheus-text-format": "^1.1.1", + "ramda": "^0.29.1", "react-redux": "^8.1.3", "react-ui-scrollspy": "^2.3.0" }, "devDependencies": { - "@types/react": "^18.2.31", - "@types/react-dom": "^18.2.15", - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", + "@types/ramda": "^0.29.9", + "@types/react": "^18.2.38", + "@types/react-dom": "^18.2.16", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", "autoprefixer": "^10.4.16", - "electron": "^26.2.2", + "electron": "^27.1.0", "electron-builder": "^24.6.4", - "eslint": "^8.52.0", + "eslint": "^8.54.0", "eslint-plugin-react": "^7.33.2", "husky": "^8.0.3", - "lint-staged": "^15.0.2", + "lint-staged": "^15.1.0", "next": "^12.3.4", "nextron": "^8.12.0", "postcss": "^8.4.31", - "prettier": "^3.0.3", + "prettier": "^3.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "tailwindcss": "^3.3.5", - "typescript": "^5.2.2" + "typescript": "^5.3.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -1987,6 +1990,37 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/@develar/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@develar/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@develar/schema-utils/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/@electron/asar": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.7.tgz", @@ -2266,9 +2300,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -2288,6 +2322,22 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2313,6 +2363,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2338,9 +2394,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2945,10 +3001,19 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==" }, + "node_modules/@types/ramda": { + "version": "0.29.9", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.9.tgz", + "integrity": "sha512-X3yEG6tQCWBcUAql+RPC/O1Hm9BSU+MXu2wJnCETuAgUlrEDwTA1kIOdEEE4YXDtf0zfQLHa9CCE7WYp9kqPIQ==", + "dev": true, + "dependencies": { + "types-ramda": "^0.29.6" + } + }, "node_modules/@types/react": { - "version": "18.2.31", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.31.tgz", - "integrity": "sha512-c2UnPv548q+5DFh03y8lEDeMfDwBn9G3dRwfkrxQMo/dOtRHUUO57k6pHvBIfH/VF4Nh+98mZ5aaSe+2echD5g==", + "version": "18.2.38", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.38.tgz", + "integrity": "sha512-cBBXHzuPtQK6wNthuVMV6IjHAFkdl/FOPFIlkd81/Cd1+IqkHu/A+w4g43kaQQoYHik/ruaQBDL72HyCy1vuMw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -2956,9 +3021,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.15", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.15.tgz", - "integrity": "sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==", + "version": "18.2.16", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.16.tgz", + "integrity": "sha512-766c37araZ9vxtYs25gvY2wNdFWsT2ZiUvOd0zMhTaoGj6B911N8CKQWgXXJoPMLF3J82thpRqQA7Rf3rBwyJw==", "devOptional": true, "dependencies": { "@types/react": "*" @@ -2979,9 +3044,9 @@ "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==" }, "node_modules/@types/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/use-sync-external-store": { @@ -3007,16 +3072,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.0.tgz", - "integrity": "sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/type-utils": "6.9.0", - "@typescript-eslint/utils": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -3057,15 +3122,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", - "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4" }, "engines": { @@ -3085,13 +3150,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3102,13 +3167,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.0.tgz", - "integrity": "sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/utils": "6.9.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -3129,9 +3194,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3142,13 +3207,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3184,17 +3249,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.0.tgz", - "integrity": "sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" }, "engines": { @@ -3224,12 +3289,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3462,14 +3527,13 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -3493,35 +3557,6 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/ansi-escapes": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", @@ -4594,26 +4629,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/conf/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/conf/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/conf/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -4983,6 +4998,30 @@ "node": ">=8" } }, + "node_modules/dmg-license/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/dmg-license/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "optional": true + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5046,9 +5085,9 @@ } }, "node_modules/electron": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-26.4.2.tgz", - "integrity": "sha512-BOfQUOIvsq5NnssWOMqcZnA5M0ull620wvQoJq3WhXN1wJAsWu+cdjHvREyxnHbArPkV+F+x3YAi5Dt+UKoqhw==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-27.1.0.tgz", + "integrity": "sha512-XPdJiO475QJ8cx59/goWNNWnlV0vab+Ut3occymos7VDxkHV5mFrlW6tcGi+M3bW6gBfwpJocWMng8tw542vww==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -5175,9 +5214,15 @@ } }, "node_modules/electron-serve": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/electron-serve/-/electron-serve-1.1.0.tgz", - "integrity": "sha512-tQJBCbXKoKCfkBC143QCqnEtT1s8dNE2V+b/82NF6lxnGO/2Q3a3GSLHtKl3iEDQgdzTf9pH7p418xq2rXbz1Q==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/electron-serve/-/electron-serve-1.2.0.tgz", + "integrity": "sha512-zJG3wisMrDn2G/gnjrhyB074COvly1FnS0U7Edm8bfXLB8MYX7UtwR9/y2LkFreYjzQHm9nEbAfgCmF+9M9LHQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/electron-store": { "version": "8.1.0", @@ -5389,15 +5434,15 @@ } }, "node_modules/eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -5558,6 +5603,22 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5624,6 +5685,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -7246,10 +7313,9 @@ "dev": true }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json-schema-typed": { "version": "7.0.3", @@ -7358,9 +7424,9 @@ "dev": true }, "node_modules/lint-staged": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.0.2.tgz", - "integrity": "sha512-vnEy7pFTHyVuDmCAIFKR5QDO8XLVlPFQQyujQ/STOxe40ICWqJ6knS2wSJ/ffX/Lw0rz83luRDh+ET7toN+rOw==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.1.0.tgz", + "integrity": "sha512-ZPKXWHVlL7uwVpy8OZ7YQjYDAuO5X4kMh0XgZvPNxLcCCngd0PO5jKQyy3+s4TL2EnHoIXIzP1422f/l3nZKMw==", "dev": true, "dependencies": { "chalk": "5.3.0", @@ -7372,7 +7438,7 @@ "micromatch": "4.0.5", "pidtree": "0.6.0", "string-argv": "0.3.2", - "yaml": "2.3.3" + "yaml": "2.3.4" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -8824,9 +8890,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -8921,6 +8987,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -9433,22 +9508,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/schema-utils/node_modules/ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", @@ -9461,12 +9520,6 @@ "ajv": "^8.8.2" } }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -10160,6 +10213,37 @@ } } }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -10280,6 +10364,12 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, + "node_modules/ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true + }, "node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -10401,10 +10491,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/types-ramda": { + "version": "0.29.6", + "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.6.tgz", + "integrity": "sha512-VJoOk1uYNh9ZguGd3eZvqkdhD4hTGtnjRBUx5Zc0U9ftmnCgiWcSj/lsahzKunbiwRje1MxxNkEy1UdcXRCpYw==", + "dev": true, + "dependencies": { + "ts-toolbelt": "^9.6.0" + } + }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -10633,6 +10732,37 @@ "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/webpack/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -10795,9 +10925,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" diff --git a/package.json b/package.json index e67dcc4..31c34f1 100644 --- a/package.json +++ b/package.json @@ -34,34 +34,37 @@ }, "dependencies": { "@reduxjs/toolkit": "^1.9.7", + "ajv": "^8.12.0", "arweave": "^1.14.4", - "electron-serve": "^1.1.0", + "electron-serve": "^1.2.0", "electron-store": "^8.1.0", "filesize": "^10.1.0", "next-redux-wrapper": "^8.1.0", "parse-prometheus-text-format": "^1.1.1", + "ramda": "^0.29.1", "react-redux": "^8.1.3", "react-ui-scrollspy": "^2.3.0" }, "devDependencies": { - "@types/react": "^18.2.31", - "@types/react-dom": "^18.2.15", - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", + "@types/ramda": "^0.29.9", + "@types/react": "^18.2.38", + "@types/react-dom": "^18.2.16", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", "autoprefixer": "^10.4.16", - "electron": "^26.2.2", + "electron": "^27.1.0", "electron-builder": "^24.6.4", - "eslint": "^8.52.0", + "eslint": "^8.54.0", "eslint-plugin-react": "^7.33.2", "husky": "^8.0.3", - "lint-staged": "^15.0.2", + "lint-staged": "^15.1.0", "next": "^12.3.4", "nextron": "^8.12.0", "postcss": "^8.4.31", - "prettier": "^3.0.3", + "prettier": "^3.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "tailwindcss": "^3.3.5", - "typescript": "^5.2.2" + "typescript": "^5.3.2" } } diff --git a/renderer/components/Charts/DataRelated.tsx b/renderer/components/Charts/DataRelated.tsx index 75ee217..ee1f09a 100644 --- a/renderer/components/Charts/DataRelated.tsx +++ b/renderer/components/Charts/DataRelated.tsx @@ -1,12 +1,16 @@ import { BottomArrow, TopArrow } from "./Arrows"; -interface Props { +interface DataRelatedChartProps { weaveSize: number; storageAvailable: number; dataPacked: number; } -export default function DataRelatedChart({ weaveSize, storageAvailable, dataPacked }: Props) { +export default function DataRelatedChart({ + weaveSize, + storageAvailable, + dataPacked, +}: DataRelatedChartProps) { // NOTE maybe this component should pick all stuff from storage directly return (
diff --git a/renderer/components/DataRelated.tsx b/renderer/components/DataRelated.tsx index 2308543..a653b99 100644 --- a/renderer/components/DataRelated.tsx +++ b/renderer/components/DataRelated.tsx @@ -1,8 +1,12 @@ +import React from "react"; +import { filesize } from "filesize/dist/filesize.esm.js"; import DataRelatedChart from "./Charts/DataRelated"; import { ASSET } from "./Asset"; -import { useDataPacked, useStorageAvailable, useWeaveSize } from "../store/metricsSliceHooks"; -import { filesize } from "filesize/dist/filesize.esm.js"; -import React from "react"; +import { + useDataPacked, + useStorageAvailable, + useWeaveSize, +} from "../store/metricsSlice/metricsSliceHooks"; export default function DataRelated() { const { dataPacked } = useDataPacked(); diff --git a/renderer/components/Navbar.tsx b/renderer/components/Navbar.tsx index d65538a..643911f 100644 --- a/renderer/components/Navbar.tsx +++ b/renderer/components/Navbar.tsx @@ -1,7 +1,12 @@ +import React from "react"; import Link from "next/link"; import { useRouter } from "next/router"; -import WalletButton from "./WalletButton"; +import { useAppDispatch } from "../store"; +import { AddMiner } from "./add-miner/add-miner"; import { ASSET } from "./Asset"; +import { getNodes } from "../store/configSlice/configSlice"; +import { useConfigNodes } from "../store/configSlice/configSliceHooks"; +import { useEffect } from "react"; interface NavLink { href: string; @@ -11,6 +16,14 @@ interface NavLink { export default function Navbar() { const router = useRouter(); + const dispatch = useAppDispatch(); + const nodes = useConfigNodes(); + + useEffect(() => { + dispatch(getNodes()); + }, [dispatch]); + + console.log({ nodes }); const links: NavLink[] = [ { @@ -67,8 +80,7 @@ export default function Navbar() {
- - + ); } diff --git a/renderer/components/add-miner/add-miner-modal.tsx b/renderer/components/add-miner/add-miner-modal.tsx new file mode 100644 index 0000000..f479b9c --- /dev/null +++ b/renderer/components/add-miner/add-miner-modal.tsx @@ -0,0 +1,95 @@ +import React from "react"; + +interface AddMinerModalProps { + nameValue: string; + hostnameValue: string; + portValue: number; + protocolValue: string; + onClose: () => void; + onAddMiner: () => void; + onNameChange: (event: React.ChangeEvent) => void; + onHostnameChange: (event: React.ChangeEvent) => void; + onPortChange: (event: React.ChangeEvent) => void; + onProtocolChange: (event: React.ChangeEvent) => void; +} + +export function AddMinerModal({ + nameValue, + hostnameValue, + portValue, + protocolValue, + onClose, + onAddMiner, + onNameChange, + onHostnameChange, + onPortChange, + onProtocolChange, +}: AddMinerModalProps) { + return ( +
+
+
+
+ {/* Modal Content */} +
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+
+
+
+ ); +} diff --git a/renderer/components/add-miner/add-miner.tsx b/renderer/components/add-miner/add-miner.tsx new file mode 100644 index 0000000..46f6924 --- /dev/null +++ b/renderer/components/add-miner/add-miner.tsx @@ -0,0 +1,39 @@ +import { AddMinerButton } from "./add-miner-button"; +import { AddMinerModal } from "./add-miner-modal"; +import { useAddMiner } from "./use-add-miner"; + +export function AddMiner({ withButton }: { withButton?: boolean }) { + const { + isModalOpen, + newMinerName, + newMinerHost, + newMinerPort, + newMinerProtocol, + handleAddMiner, + handleNewMinerNameChange, + handleNewMinerHostChange, + handleNewMinerPortChange, + handleNewMinerProtocolChange, + setIsModalOpen, + } = useAddMiner(); + + return ( + <> + {withButton && setIsModalOpen(true)} />} + {isModalOpen && ( + setIsModalOpen(false)} + onAddMiner={handleAddMiner} + nameValue={newMinerName} + hostnameValue={newMinerHost} + portValue={newMinerPort} + protocolValue={newMinerProtocol} + onNameChange={handleNewMinerNameChange} + onHostnameChange={handleNewMinerHostChange} + onPortChange={handleNewMinerPortChange} + onProtocolChange={handleNewMinerProtocolChange} + /> + )} + + ); +} diff --git a/renderer/components/add-miner/use-add-miner.ts b/renderer/components/add-miner/use-add-miner.ts new file mode 100644 index 0000000..758ca51 --- /dev/null +++ b/renderer/components/add-miner/use-add-miner.ts @@ -0,0 +1,61 @@ +import React, { useCallback, useState } from "react"; +import { useDispatch } from "react-redux"; +import { appendNode } from "../../store/configSlice/configSlice"; +import { ArweaveNodeConfig } from "../../../types/config"; + +export const useAddMiner = () => { + const dispatch = useDispatch(); + const [isModalOpen, setIsModalOpen] = useState(false); + const [newMinerName, setNewMinerName] = useState(""); + const [newMinerHost, setNewMinerHost] = useState(""); + const [newMinerPort, setNewMinerPort] = useState(1984); + const [newMinerProtocol, setNewMinerProtocol] = useState("http"); + + const newMinerData: ArweaveNodeConfig = { + name: newMinerName, + host: newMinerHost, + port: newMinerPort, + protocol: newMinerProtocol, + }; + + const handleAddMiner = useCallback(() => { + dispatch(appendNode(newMinerData)); + setIsModalOpen(false); + }, [dispatch, newMinerData, setIsModalOpen]); + + const handleNewMinerNameChange = useCallback( + (event: React.ChangeEvent) => setNewMinerName(event.currentTarget.value), + [setNewMinerName], + ); + + const handleNewMinerHostChange = useCallback( + (event: React.ChangeEvent) => setNewMinerHost(event.currentTarget.value), + [setNewMinerHost], + ); + + const handleNewMinerPortChange = useCallback( + (event: React.ChangeEvent) => + !Number.isNaN(event.currentTarget.value) && + setNewMinerPort(Number(event.currentTarget.value)), + [setNewMinerPort], + ); + + const handleNewMinerProtocolChange = useCallback( + (event: React.ChangeEvent) => setNewMinerProtocol(event.currentTarget.value), + [setNewMinerProtocol], + ); + + return { + isModalOpen, + newMinerName, + newMinerHost, + newMinerPort, + newMinerProtocol, + handleAddMiner, + handleNewMinerNameChange, + handleNewMinerHostChange, + handleNewMinerPortChange, + handleNewMinerProtocolChange, + setIsModalOpen, + }; +}; diff --git a/renderer/layouts/MainLayout.tsx b/renderer/layouts/MainLayout.tsx index 0603491..58af74d 100644 --- a/renderer/layouts/MainLayout.tsx +++ b/renderer/layouts/MainLayout.tsx @@ -1,10 +1,11 @@ +import React from "react"; import Navbar from "../components/Navbar"; -interface Props { - children: React.ReactNode | React.ReactNodeArray; +interface MainLayoutProps { + children: React.ReactNode; } -export default function MainLayout({ children }: Props) { +export function MainLayout({ children }: MainLayoutProps) { return (
diff --git a/renderer/layouts/index.tsx b/renderer/layouts/index.tsx deleted file mode 100644 index 4bea620..0000000 --- a/renderer/layouts/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default as MainLayout } from "./MainLayout"; diff --git a/renderer/pages/_app.tsx b/renderer/pages/_app.tsx index a315aba..138b025 100644 --- a/renderer/pages/_app.tsx +++ b/renderer/pages/_app.tsx @@ -1,9 +1,13 @@ import { AppProps } from "next/app"; -import "../styles/globals.css"; +import { Provider } from "react-redux"; import { wrapper } from "../store"; +import "../styles/globals.css"; -function MyApp({ Component, pageProps }: AppProps) { - return ; +export default function ArweaveMinerUi({ Component, ...rest }: AppProps) { + const { store, props } = wrapper.useWrappedStore(rest); + return ( + + + + ); } - -export default wrapper.withRedux(MyApp); diff --git a/renderer/pages/dashboard.tsx b/renderer/pages/dashboard.tsx index 04c7c40..aa14e04 100644 --- a/renderer/pages/dashboard.tsx +++ b/renderer/pages/dashboard.tsx @@ -1,9 +1,9 @@ import React, { useCallback, useEffect, useState } from "react"; import { useDispatch } from "react-redux"; import ScrollSpy from "react-ui-scrollspy"; -import { useEarnings, useHashRate } from "../store/metricsSliceHooks"; -import { MainLayout } from "../layouts"; -import { setMetricsState } from "../store/metricsSlice"; +import { MainLayout } from "../layouts/MainLayout"; +import { useEarnings, useHashRate } from "../store/metricsSlice/metricsSliceHooks"; +import { setMetricsState } from "../store/metricsSlice/metricsSlice"; import { SetMetricsStateActionPayload } from "../../types/metrics"; import DataRelated from "../components/DataRelated"; diff --git a/renderer/pages/home.tsx b/renderer/pages/home.tsx index bedb18d..892b7dc 100644 --- a/renderer/pages/home.tsx +++ b/renderer/pages/home.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { MainLayout } from "../layouts"; +import { MainLayout } from "../layouts/MainLayout"; import { useRouter } from "next/router"; import { useSelector } from "react-redux"; -import { selectMinorState } from "../store/metricsSlice"; +import { selectMinorState } from "../store/metricsSlice/metricsSlice"; export default function HomePage() { const router = useRouter(); diff --git a/renderer/store/configSlice/configSlice.ts b/renderer/store/configSlice/configSlice.ts new file mode 100644 index 0000000..155cbc9 --- /dev/null +++ b/renderer/store/configSlice/configSlice.ts @@ -0,0 +1,31 @@ +import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; +import type { PayloadAction } from "@reduxjs/toolkit"; +import { ArweaveMinerUiConfig, ArweaveNodeConfig } from "../../../types/config"; + +interface ConfigState { + nodes: ArweaveMinerUiConfig["nodes"]; +} + +const initialState = { nodes: [] } as ConfigState; + +export const configSlice = createSlice({ + name: "config", + initialState, + reducers: { + setNodes(state, action: PayloadAction) { + state.nodes = action.payload; + }, + appendNode(state, action: PayloadAction) { + window.ipc.configAppendNode(action.payload); + state.nodes.push(action.payload); + }, + }, +}); + +export const getNodes = createAsyncThunk("config/getNodes", async (_, { dispatch }) => { + const answer = window.ipc.configGetNodes(); + dispatch(configSlice.actions.setNodes(answer)); +}); + +export const { appendNode } = configSlice.actions; +export default configSlice.reducer; diff --git a/renderer/store/configSlice/configSliceHooks.ts b/renderer/store/configSlice/configSliceHooks.ts new file mode 100644 index 0000000..3beda4d --- /dev/null +++ b/renderer/store/configSlice/configSliceHooks.ts @@ -0,0 +1,7 @@ +import { useSelector } from "react-redux"; +import { equals } from "ramda"; +import { selectNodesFromConfig } from "./configSliceSelectors"; + +export const useConfigNodes = () => { + return useSelector(selectNodesFromConfig, equals); +}; diff --git a/renderer/store/configSlice/configSliceSelectors.ts b/renderer/store/configSlice/configSliceSelectors.ts new file mode 100644 index 0000000..b714454 --- /dev/null +++ b/renderer/store/configSlice/configSliceSelectors.ts @@ -0,0 +1,3 @@ +import { AppState } from "../index"; + +export const selectNodesFromConfig = (state: AppState) => state.config.nodes; diff --git a/renderer/store/index.ts b/renderer/store/index.ts index 156ad38..ec56c45 100644 --- a/renderer/store/index.ts +++ b/renderer/store/index.ts @@ -1,23 +1,32 @@ -import { configureStore, ThunkAction, Action } from "@reduxjs/toolkit"; +import { Action, AnyAction, ThunkAction, ThunkDispatch, configureStore } from "@reduxjs/toolkit"; +import { useDispatch } from "react-redux"; +import thunkMiddleware from "redux-thunk"; import { createWrapper } from "next-redux-wrapper"; -import { metricsSlice } from "./metricsSlice"; +import { metricsSlice } from "./metricsSlice/metricsSlice"; +import { configSlice } from "./configSlice/configSlice"; export const makeStore = () => { return configureStore({ reducer: { + [configSlice.name]: configSlice.reducer, [metricsSlice.name]: metricsSlice.reducer, }, devTools: true, + middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(thunkMiddleware), }); }; export type AppStore = ReturnType; export type AppState = ReturnType; +export type AppThunkDispatch = ThunkDispatch; export type AppThunk = ThunkAction< ReturnType, AppState, unknown, Action >; +export type AppDispatch = AppStore["dispatch"]; + +export const useAppDispatch = () => useDispatch(); export const wrapper = createWrapper(makeStore); diff --git a/renderer/store/metricsSlice.ts b/renderer/store/metricsSlice/metricsSlice.ts similarity index 89% rename from renderer/store/metricsSlice.ts rename to renderer/store/metricsSlice/metricsSlice.ts index 23cbd08..53480c6 100644 --- a/renderer/store/metricsSlice.ts +++ b/renderer/store/metricsSlice/metricsSlice.ts @@ -1,7 +1,7 @@ import { createSlice } from "@reduxjs/toolkit"; import { HYDRATE } from "next-redux-wrapper"; -import { SetMetricsStateActionPayload } from "../../types/metrics"; -import { AppState } from "./index"; +import { SetMetricsStateActionPayload } from "../../../types/metrics"; +import { AppState } from "../index"; // Type for our state export interface MetricsSliceReducerState { @@ -51,13 +51,12 @@ export const metricsSlice = createSlice({ }, }, - extraReducers: { - [HYDRATE]: (state, action) => { + extraReducers: (builder) => { + builder.addCase(HYDRATE, (state) => { return { ...state, - ...action.payload, }; - }, + }); }, }); diff --git a/renderer/store/metricsSliceHooks.ts b/renderer/store/metricsSlice/metricsSliceHooks.ts similarity index 97% rename from renderer/store/metricsSliceHooks.ts rename to renderer/store/metricsSlice/metricsSliceHooks.ts index 691d0d4..94a585f 100644 --- a/renderer/store/metricsSliceHooks.ts +++ b/renderer/store/metricsSlice/metricsSliceHooks.ts @@ -6,7 +6,7 @@ import { selectDataUnpacked, selectStorageAvailable, selectWeaveSize, -} from "./selectors"; +} from "./metricsSliceSelectors"; export const useHashRate = () => { return useSelector(selectHashRate, (prev, current) => { diff --git a/renderer/store/selectors.ts b/renderer/store/metricsSlice/metricsSliceSelectors.ts similarity index 94% rename from renderer/store/selectors.ts rename to renderer/store/metricsSlice/metricsSliceSelectors.ts index 259c4b0..19dbb19 100644 --- a/renderer/store/selectors.ts +++ b/renderer/store/metricsSlice/metricsSliceSelectors.ts @@ -1,4 +1,4 @@ -import { AppState } from "./index"; +import { AppState } from "../index"; export const selectHashRate = (state: AppState) => ({ hashRate: state.metrics.hashRate, diff --git a/types/config.ts b/types/config.ts new file mode 100644 index 0000000..cc8c18b --- /dev/null +++ b/types/config.ts @@ -0,0 +1,10 @@ +export interface ArweaveNodeConfig { + name: string; + host: string; + port: number; + protocol: string; +} + +export interface ArweaveMinerUiConfig { + nodes: ArweaveNodeConfig[]; +}