diff --git a/eslint.config.mjs b/eslint.config.mjs index f7d4dbc9..023706fd 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -17,6 +17,7 @@ const compat = new FlatCompat({ export default [...fixupConfigRules( compat.extends("react-app", "airbnb", "plugin:jsx-a11y/recommended", "prettier"), ), { + // root: true, plugins: { "jsx-a11y": fixupPluginRules(jsxA11Y), prettier @@ -40,7 +41,7 @@ export default [...fixupConfigRules( "no-underscore-dangle": ["warn", { allow: ["_kmq", "_kmk"], }], - + "no-unsafe-optional-chaining": 0, "jsx-a11y/label-has-associated-control": 0, "react/jsx-no-bind": 0, diff --git a/package.json b/package.json index 433670f6..952bb360 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "harperdb-studio", - "version": "4.5.6", + "version": "4.5.7", "description": "A UI for HarperDB", "deploymentUrl": "studio.harperdb.io", "private": true, @@ -10,9 +10,9 @@ "start": "HTTPS=true SSL_CRT_FILE=./.cert/cert.pem SSL_KEY_FILE=./.cert/key.pem react-scripts start", "start:local": "REACT_APP_LOCALSTUDIO=true HTTPS=true SSL_CRT_FILE=./.cert/cert.pem SSL_KEY_FILE=./.cert/key.pem react-scripts start", "docker": "HTTPS=false react-scripts start", - "build:stage": "GENERATE_SOURCEMAP=false PUBLIC_URL=https://dbjxbnqel2bw9.cloudfront.net react-scripts build", - "build:prod": "GENERATE_SOURCEMAP=false PUBLIC_URL=https://ds5zz9rfvzuta.cloudfront.net react-scripts build", - "build:local": "BUILD_PATH=./build-local GENERATE_SOURCEMAP=false REACT_APP_LOCALSTUDIO=true react-scripts build", + "build:stage": "DISABLE_ESLINT_PLUGIN=true GENERATE_SOURCEMAP=false PUBLIC_URL=https://dbjxbnqel2bw9.cloudfront.net react-scripts build", + "build:prod": "DISABLE_ESLINT_PLUGIN=true GENERATE_SOURCEMAP=false PUBLIC_URL=https://ds5zz9rfvzuta.cloudfront.net react-scripts build", + "build:local": "DISABLE_ESLINT_PLUGIN=true BUILD_PATH=./build-local GENERATE_SOURCEMAP=false REACT_APP_LOCALSTUDIO=true react-scripts build", "lint-dev": "eslint --fix src && npx stylelint --fix \"src/**/*.scss\"", "lint-prod": "eslint --fix src" }, diff --git a/src/components/instance/functions/manage/applicationsEditor/EditorMenu.js b/src/components/instance/functions/manage/applicationsEditor/EditorMenu.js index 452e9232..757f4e55 100644 --- a/src/components/instance/functions/manage/applicationsEditor/EditorMenu.js +++ b/src/components/instance/functions/manage/applicationsEditor/EditorMenu.js @@ -52,10 +52,10 @@ export default function EditorMenu({ children }) { {children.map( (child) => child && ( -
  • +
  • {child}
  • - ), + ) )} ); diff --git a/src/components/instance/functions/manage/applicationsEditor/FileMenu.js b/src/components/instance/functions/manage/applicationsEditor/FileMenu.js index b55a8489..25d5afe8 100644 --- a/src/components/instance/functions/manage/applicationsEditor/FileMenu.js +++ b/src/components/instance/functions/manage/applicationsEditor/FileMenu.js @@ -51,10 +51,10 @@ function FileMenu({ children }) { {children.map( (child) => child && ( -
  • +
  • {child}
  • - ), + ) )} ); diff --git a/src/components/instances/index.js b/src/components/instances/index.js index f815feea..2ce6a3bc 100644 --- a/src/components/instances/index.js +++ b/src/components/instances/index.js @@ -1,9 +1,8 @@ -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useCallback } from 'react'; import { Row } from 'reactstrap'; import { useParams, useNavigate } from 'react-router-dom'; import { useStoreState } from 'pullstate'; import { useAlert } from 'react-alert'; -import useAsyncEffect from 'use-async-effect'; import useInterval from 'use-interval'; import config from '../../config'; @@ -43,6 +42,7 @@ function InstancesIndex() { useEffect(() => { refreshInstances(); + // eslint-disable-next-line }, [auth, customer_id, products, regions, subscriptions]); useEffect(() => { @@ -52,7 +52,7 @@ function InstancesIndex() { alert.error('You have been removed from this organization'); navigate('/'); } - }, [action, alert, isOrgUser]); + }, [action, alert, isOrgUser, navigate]); useEffect(() => { if (auth && customer_id) { diff --git a/src/components/instances/list/CardFront.js b/src/components/instances/list/CardFront.js index c4d9f302..37a64fda 100644 --- a/src/components/instances/list/CardFront.js +++ b/src/components/instances/list/CardFront.js @@ -104,16 +104,12 @@ function CardFront({ compute_stack_id, instance_id, url, status, instance_name, setProcessing(true); const registrationResult = await handleInstanceRegistration({ - auth, - customer_id, instanceAuth, url, is_local, is_ssl, cloud_provider, instance_id, - compute_stack_id, - compute, instance_name, status: instanceData.status, }); diff --git a/src/functions/api/instance/getComponents.js b/src/functions/api/instance/getComponents.js index cfd7461f..4b248ea9 100644 --- a/src/functions/api/instance/getComponents.js +++ b/src/functions/api/instance/getComponents.js @@ -9,7 +9,7 @@ function addMetadata(fileTree, path, rootDir, readOnly = false) { if (path === rootDir) { fileTree.path = rootDir; - fileTree.key = crypto.randomUUID(); + fileTree.key = crypto.randomUUID?.() ?? Math.random().toString().slice(2); } for (const entry of fileTree.entries) { @@ -24,7 +24,7 @@ function addMetadata(fileTree, path, rootDir, readOnly = false) { const [, project] = newPath.split('/'); entry.project = project; entry.path = newPath; - entry.key = crypto.randomUUID(); + entry.key = crypto.randomUUID?.() ?? Math.random().toString().slice(2); entry.readOnly = readOnly || !!entry.package; addMetadata(entry, newPath, rootDir, entry.readOnly); diff --git a/src/functions/api/instance/updateSystemInfo.js b/src/functions/api/instance/updateSystemInfo.js index 8e418180..7987a43e 100644 --- a/src/functions/api/instance/updateSystemInfo.js +++ b/src/functions/api/instance/updateSystemInfo.js @@ -4,18 +4,15 @@ import instanceState from '../../state/instanceState'; const B2GB1000 = 1000000000; // for mac disk and transfer const B2GB1024 = 1073741824; // for non-mac disk -export default async ({ auth, url, signal, refresh, is_local, cachedSystemInfo, skip=[] }) => { - +export default async ({ auth, url, signal, refresh, is_local, cachedSystemInfo, skip = [] }) => { // skip attributes added because network and disk currently expensive instance ops // provides more fine-grained control over which items are cached. - const systemAttributes = ['network','disk','cpu','memory','system']; + const systemAttributes = ['network', 'disk', 'cpu', 'memory', 'system']; const result = await queryInstance({ operation: { operation: 'system_information', - attributes: skip?.length ? - systemAttributes.filter(attr => !skip.includes(attr)) : - systemAttributes, + attributes: skip?.length ? systemAttributes.filter((attr) => !skip.includes(attr)) : systemAttributes, }, auth, url, @@ -52,76 +49,56 @@ export default async ({ auth, url, signal, refresh, is_local, cachedSystemInfo, }); } - // MEMORY - const totalMemory = skip.includes('memory') ? - parseFloat(cachedSystemInfo.totalMemory) : - result.memory.total / B2GB1024; - const usedMemory = skip.includes('memory') ? - parseFloat(cachedSystemInfo.usedMemory) : - result.memory.active / B2GB1024; - const freeMemory = skip.includes('memory') ? - parseFloat(cachedSystemInfo.freeMemory) : - result.memory.available / B2GB1024; - const memoryStatus = skip.includes('memory') ? - cachedSystemInfo.memoryStatus : - freeMemory / totalMemory < 0.1 ? - 'danger' : - freeMemory / totalMemory < 0.25 ? 'warning' : 'success'; + const totalMemory = skip.includes('memory') ? parseFloat(cachedSystemInfo.totalMemory) : result.memory.total / B2GB1024; + const usedMemory = skip.includes('memory') ? parseFloat(cachedSystemInfo.usedMemory) : result.memory.active / B2GB1024; + const freeMemory = skip.includes('memory') ? parseFloat(cachedSystemInfo.freeMemory) : result.memory.available / B2GB1024; + const memoryStatus = skip.includes('memory') + ? cachedSystemInfo.memoryStatus + : freeMemory / totalMemory < 0.1 + ? 'danger' + : freeMemory / totalMemory < 0.25 + ? 'warning' + : 'success'; // DISK - const totalDisk = skip.includes('disk') ? - parseFloat(cachedSystemInfo.totalDisk) : - result.system.platform === 'darwin' ? - result.disk.size[0].size / B2GB1000 : - !is_local ? - result.disk.size.find((disk) => disk.mount === '/home/ubuntu/hdb').size / B2GB1024 : - result.disk.size[0].size / B2GB1024; - - const usedDisk = skip.includes('disk') ? - parseFloat(cachedSystemInfo.usedDisk) : - result.system.platform === 'darwin' ? - result.disk.size.reduce((a, b) => a + b.used, 0) / B2GB1000 : - !is_local ? - result.disk.size.find((disk) => disk.mount === '/home/ubuntu/hdb').used / B2GB1024 : - result.disk.size.reduce((a, b) => a + b.used, 0) / B2GB1024; - - const freeDisk = skip.includes('disk') ? - parseFloat(cachedSystemInfo.freeDisk) : - totalDisk - usedDisk; - - const diskStatus = skip.includes('disk') ? - cachedSystemInfo.diskStatus : - freeDisk / totalDisk < 0.1 ? - 'danger' : freeDisk / totalDisk < 0.25 ? - 'warning' : 'success'; + const totalDisk = skip.includes('disk') + ? parseFloat(cachedSystemInfo.totalDisk) + : result.system.platform === 'darwin' + ? result.disk?.size?.[0].size / B2GB1000 + : !is_local + ? result.disk?.size?.find((disk) => disk.mount === '/home/ubuntu/hdb').size / B2GB1024 + : result.disk?.size?.[0].size / B2GB1024; + + const usedDisk = skip.includes('disk') + ? parseFloat(cachedSystemInfo.usedDisk) + : result.system.platform === 'darwin' + ? result.disk?.size?.reduce((a, b) => a + b.used, 0) / B2GB1000 + : !is_local + ? result.disk?.size?.find((disk) => disk.mount === '/home/ubuntu/hdb').used / B2GB1024 + : result.disk?.size?.reduce((a, b) => a + b.used, 0) / B2GB1024; + + const freeDisk = skip.includes('disk') ? parseFloat(cachedSystemInfo.freeDisk) : totalDisk - usedDisk; + + const diskStatus = skip.includes('disk') ? cachedSystemInfo.diskStatus : freeDisk / totalDisk < 0.1 ? 'danger' : freeDisk / totalDisk < 0.25 ? 'warning' : 'success'; // CPU - const cpuInfo = skip.includes('cpu') ? - cachedSystemInfo.cpuInfo : `${result.cpu.manufacturer} ${result.cpu.brand}`; - const cpuCores = skip.includes('cpu') ? - cachedSystemInfo.cpuCores : `${result.cpu.physicalCores} physical / ${result.cpu.cores} virtual`; - const cpuLoad = skip.includes('cpu') ? - parseFloat(cachedSystemInfo.cpuLoad) : result.cpu.current_load.currentLoad || result.cpu.current_load.currentload || 0; - const cpuStatus = skip.includes('cpu') ? - cachedSystemInfo.cpuStatus : - cpuLoad > 90 ? - 'danger' : cpuLoad > 75 ? - 'warning' : 'success'; + const cpuInfo = skip.includes('cpu') ? cachedSystemInfo.cpuInfo : `${result.cpu.manufacturer} ${result.cpu.brand}`; + const cpuCores = skip.includes('cpu') ? cachedSystemInfo.cpuCores : `${result.cpu.physicalCores} physical / ${result.cpu.cores} virtual`; + const cpuLoad = skip.includes('cpu') ? parseFloat(cachedSystemInfo.cpuLoad) : result.cpu.current_load.currentLoad || result.cpu.current_load.currentload || 0; + const cpuStatus = skip.includes('cpu') ? cachedSystemInfo.cpuStatus : cpuLoad > 90 ? 'danger' : cpuLoad > 75 ? 'warning' : 'success'; // NETWORK - const networkTransferred = skip.includes('network') ? - parseFloat(cachedSystemInfo.networkTransferred) : - result.network.stats.reduce((a, b) => a + b.tx_bytes, 0) / B2GB1000; - const networkReceived = skip.includes('network') ? - parseFloat(cachedSystemInfo.networkReceived) : - result.network.stats.reduce((a, b) => a + b.rx_bytes, 0) / B2GB1000; - const networkLatency = skip.includes('network') ? - parseFloat(cachedSystemInfo.networkLatency) : - result.network.latency.ms; - const networkLatencyStatus = skip.includes('network') ? - parseFloat(cachedSystemInfo.networkLatencyStatus) : - networkLatency > 1000 ? 'danger' : networkLatency > 500 ? 'warning' : 'success'; + const networkTransferred = skip.includes('network') ? parseFloat(cachedSystemInfo.networkTransferred) : result.network.stats.reduce((a, b) => a + b.tx_bytes, 0) / B2GB1000; + const networkReceived = skip.includes('network') ? parseFloat(cachedSystemInfo.networkReceived) : result.network.stats.reduce((a, b) => a + b.rx_bytes, 0) / B2GB1000; + const networkLatency = skip.includes('network') ? parseFloat(cachedSystemInfo.networkLatency) : result.network.latency.ms; + const networkLatencyStatus = skip.includes('network') + ? parseFloat(cachedSystemInfo.networkLatencyStatus) + : networkLatency > 1000 + ? 'danger' + : networkLatency > 500 + ? 'warning' + : 'success'; const systemInfo = { totalMemory: totalMemory?.toFixed(2), @@ -145,5 +122,4 @@ export default async ({ auth, url, signal, refresh, is_local, cachedSystemInfo, return instanceState.update((s) => { s.systemInfo = systemInfo; }); - }; diff --git a/src/functions/instances/handleInstanceRegistration.js b/src/functions/instances/handleInstanceRegistration.js index 1ece7934..ddc55a03 100644 --- a/src/functions/instances/handleInstanceRegistration.js +++ b/src/functions/instances/handleInstanceRegistration.js @@ -1,7 +1,7 @@ import registrationInfo from '../api/instance/registrationInfo'; import handleCloudInstanceUsernameChange from './handleCloudInstanceUsernameChange'; -export default async ({ auth, customer_id, instanceAuth, url, is_local, is_ssl, cloud_provider, instance_id, compute_stack_id, compute, status }) => { +export default async ({ instanceAuth, url, is_local, is_ssl, cloud_provider, instance_id, status }) => { try { let registration = await registrationInfo({ auth: instanceAuth, url });