From 629ccb57b94c6358a15e8a390e61913ff138ff25 Mon Sep 17 00:00:00 2001 From: Daniel Velazco Date: Thu, 30 Apr 2026 09:17:40 -0500 Subject: [PATCH 1/2] update scripts, add parser library --- .eslintrc | 4 +- package-lock.json | 271 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 5 +- 3 files changed, 276 insertions(+), 4 deletions(-) diff --git a/.eslintrc b/.eslintrc index 75aea9d..73d3275 100644 --- a/.eslintrc +++ b/.eslintrc @@ -7,8 +7,10 @@ }, "extends": [ "eslint:recommended", - "plugin:react/recommended" + "plugin:react/recommended", + "plugin:react/jsx-runtime" ], + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaFeatures": { "jsx": true diff --git a/package-lock.json b/package-lock.json index 3adac73..2df29eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "@types/jest": "^29.5.12", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@typescript-eslint/parser": "^8.53.0", "babel-loader": "^9.1.3", "css-loader": "^6.8.1", "eslint": "^8.57.0", @@ -3907,6 +3908,213 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript-eslint/parser": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.1.tgz", + "integrity": "sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.1.tgz", + "integrity": "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.59.1", + "@typescript-eslint/types": "^8.59.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.1.tgz", + "integrity": "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.1.tgz", + "integrity": "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz", + "integrity": "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.1.tgz", + "integrity": "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.59.1", + "@typescript-eslint/tsconfig-utils": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz", + "integrity": "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -12849,6 +13057,54 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -12935,6 +13191,19 @@ "tslib": "2" } }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/ts-jest": { "version": "29.4.9", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", @@ -13260,7 +13529,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 1c7bdf8..fd8006a 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "author": "Autodesk Inc.", "main": "index.tsx", "scripts": { - "lint:check": "eslint src/ tests/", - "lint:fix": "eslint src/ tests/ --fix", + "lint:check": "eslint \"src/**/*.{js,jsx,ts,tsx}\" \"tests/**/*.{js,jsx,ts,tsx}\"", + "lint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx}\" \"tests/**/*.{js,jsx,ts,tsx}\" --fix", "test:unit": "jest tests/unit", "test:e2e": "playwright test tests/e2e", "test": "npm run test:unit && npm run test:e2e", @@ -53,6 +53,7 @@ "@testing-library/dom": "^10.3.0", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^15.0.6", + "@typescript-eslint/parser": "^8.53.0", "@types/jest": "^29.5.12", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", From 685e66565d7b03aba546d3bfddf7fe32bf9c1893 Mon Sep 17 00:00:00 2001 From: Daniel Velazco Date: Thu, 30 Apr 2026 11:32:45 -0500 Subject: [PATCH 2/2] fix lint issues based on its config --- .eslintrc | 17 +- package-lock.json | 103 +++++++ package.json | 2 + playwright.config.js | 2 +- src/App.tsx | 4 +- src/components/Common/Arrow.tsx | 82 +++--- src/components/Common/CardItem.tsx | 44 +-- src/components/Common/Tooltip.tsx | 82 +++--- src/components/LayoutContainer.tsx | 5 +- src/components/Learning/Carousel.tsx | 48 ++-- src/components/Learning/GuideGridItem.tsx | 27 +- src/components/Learning/ModalItem.tsx | 28 +- src/components/Learning/PageLearning.tsx | 153 +++++----- src/components/Learning/VideoCarouselItem.tsx | 87 +++--- src/components/MainContent.tsx | 45 ++- .../Recent/CustomAuthorCellRenderer.tsx | 8 +- .../Recent/CustomLocationCellRenderer.tsx | 12 +- .../Recent/CustomNameCellRenderer.tsx | 14 +- src/components/Recent/GraphGridItem.tsx | 51 ++-- src/components/Recent/GraphTable.tsx | 107 +++---- src/components/Recent/PageRecent.tsx | 242 ++++++++-------- .../Samples/CustomSampleFirstCellRenderer.tsx | 7 +- src/components/Samples/PageSamples.tsx | 269 +++++++++--------- src/components/Samples/SamplesGrid.tsx | 88 +++--- src/components/Samples/SamplesGridItem.tsx | 28 +- src/components/Samples/SamplesTable.tsx | 29 +- src/components/SettingsContext.tsx | 26 +- src/components/Sidebar/CustomDropDown.tsx | 145 +++++----- src/components/Sidebar/Sidebar.tsx | 134 ++++----- src/functions/placeholder.ts | 16 +- src/functions/utility.ts | 1 + src/index.tsx | 6 +- tests/unit/App.test.tsx | 4 +- tests/unit/LayoutContainer.test.tsx | 32 ++- tests/unit/Learning/PageLearning.test.tsx | 16 +- .../Recent/CustomNameCellRenderer.test.tsx | 4 +- tests/unit/Recent/GraphTable.test.tsx | 8 +- tests/unit/Recent/PageRecent.test.tsx | 31 +- .../CustomSampleFirstCellRenderer.test.tsx | 2 +- tests/unit/Samples/PageSamples.test.tsx | 24 +- tests/unit/Samples/SamplesGrid.test.tsx | 5 +- tests/unit/SettingsContext.test.tsx | 11 +- tests/unit/utility.test.ts | 12 +- tsconfig.json | 3 +- types/index.d.ts | 1 + 45 files changed, 1126 insertions(+), 939 deletions(-) diff --git a/.eslintrc b/.eslintrc index 73d3275..07c69e5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -8,7 +8,9 @@ "extends": [ "eslint:recommended", "plugin:react/recommended", - "plugin:react/jsx-runtime" + "plugin:react/jsx-runtime", + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended" ], "parser": "@typescript-eslint/parser", "parserOptions": { @@ -18,7 +20,7 @@ "ecmaVersion": "latest", "sourceType": "module" }, - "plugins": ["react"], + "plugins": ["react", "@typescript-eslint", "react-hooks"], "settings": { "react": { "version": "detect" @@ -29,6 +31,17 @@ "quotes": ["error", "single"], "semi": ["error", "always"] }, + "overrides": [ + { + "files": ["**/*.ts", "**/*.tsx"], + "rules": { + "no-undef": "off", + "react/prop-types": "off", + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "error" + } + } + ], "globals": { "page": true, "browser": true, diff --git a/package-lock.json b/package-lock.json index 2df29eb..8ec49e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,11 +27,13 @@ "@types/jest": "^29.5.12", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^8.53.0", "@typescript-eslint/parser": "^8.53.0", "babel-loader": "^9.1.3", "css-loader": "^6.8.1", "eslint": "^8.57.0", "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-hooks": "^4.6.2", "html-webpack-plugin": "^5.5.4", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", @@ -3908,6 +3910,45 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.1.tgz", + "integrity": "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/type-utils": "8.59.1", + "@typescript-eslint/utils": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.59.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/@typescript-eslint/parser": { "version": "8.59.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.1.tgz", @@ -3990,6 +4031,31 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.1.tgz", + "integrity": "sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/utils": "8.59.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/@typescript-eslint/types": { "version": "8.59.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz", @@ -4084,6 +4150,30 @@ "node": ">=10" } }, + "node_modules/@typescript-eslint/utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.1.tgz", + "integrity": "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/@typescript-eslint/visitor-keys": { "version": "8.59.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz", @@ -6693,6 +6783,19 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", diff --git a/package.json b/package.json index fd8006a..85a5cc8 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "@testing-library/dom": "^10.3.0", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^15.0.6", + "@typescript-eslint/eslint-plugin": "^8.53.0", "@typescript-eslint/parser": "^8.53.0", "@types/jest": "^29.5.12", "@types/react": "^18.3.3", @@ -61,6 +62,7 @@ "css-loader": "^6.8.1", "eslint": "^8.57.0", "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-hooks": "^4.6.2", "html-webpack-plugin": "^5.5.4", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", diff --git a/playwright.config.js b/playwright.config.js index 2735d59..b30cf2c 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -30,7 +30,7 @@ const config = { /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, + workers: process.env.CI ? 1 : 2, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI ? 'github' : [['list'], ['html']], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ diff --git a/src/App.tsx b/src/App.tsx index 05d7a56..0582fd5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,7 +6,7 @@ import { LayoutContainer } from './components/LayoutContainer'; import { SettingsProvider } from './components/SettingsContext'; const App = () => { - const [locale, setLocale] = useState("en"); + const [locale, setLocale] = useState('en'); // Function to get messages based on locale const messages = getMessagesForLocale(locale); @@ -29,6 +29,6 @@ const App = () => { ); -} +}; export default App; diff --git a/src/components/Common/Arrow.tsx b/src/components/Common/Arrow.tsx index 1dba35f..200a380 100644 --- a/src/components/Common/Arrow.tsx +++ b/src/components/Common/Arrow.tsx @@ -1,51 +1,53 @@ import styles from './Arrow.module.css'; export const ClosedArrow = ({ isOpen, direction, color }: Arrow) => { - let arrowClasses = [styles.closedArrow]; // Start with an array of classes - if (isOpen) arrowClasses.push(styles.open); - if (direction === 'left') arrowClasses.push(styles.left); - if (direction === 'right') arrowClasses.push(styles.right); + // eslint-disable-next-line prefer-const + let arrowClasses = [styles.closedArrow]; // Start with an array of classes + if (isOpen) arrowClasses.push(styles.open); + if (direction === 'left') arrowClasses.push(styles.left); + if (direction === 'right') arrowClasses.push(styles.right); - // Join the classes with a space to form the className string - const arrowClassString = arrowClasses.join(' '); + // Join the classes with a space to form the className string + const arrowClassString = arrowClasses.join(' '); - return ( - - - - ); + return ( + + + + ); }; export const OpenArrow = ({ isOpen, direction, color }: Arrow) => { - let arrowClasses = [styles.openArrow]; // Start with an array of classes - if (isOpen) arrowClasses.push(styles.open); - if (direction === 'left') arrowClasses.push(styles.left); - if (direction === 'right') arrowClasses.push(styles.right); + // eslint-disable-next-line prefer-const + let arrowClasses = [styles.openArrow]; // Start with an array of classes + if (isOpen) arrowClasses.push(styles.open); + if (direction === 'left') arrowClasses.push(styles.left); + if (direction === 'right') arrowClasses.push(styles.right); - // Join the classes with a space to form the className string - const arrowClassString = arrowClasses.join(' '); + // Join the classes with a space to form the className string + const arrowClassString = arrowClasses.join(' '); - return ( - - - - ); + return ( + + + + ); }; \ No newline at end of file diff --git a/src/components/Common/CardItem.tsx b/src/components/Common/CardItem.tsx index 21f7bce..8fbfa8b 100644 --- a/src/components/Common/CardItem.tsx +++ b/src/components/Common/CardItem.tsx @@ -2,27 +2,27 @@ import { Tooltip } from './Tooltip'; import styles from './CardItems.module.css'; export const CardItem = ({ imageSrc, onClick, tooltipContent, titleText, subtitleText }: CardItem) => { - return ( -
- -
- -
- {tooltipContent - ? - -
-

{titleText}

-

{subtitleText}

-
-
- : -
-

{titleText}

-

{subtitleText}

-
- } -
+ return ( + + ); }; \ No newline at end of file diff --git a/src/components/Common/Tooltip.tsx b/src/components/Common/Tooltip.tsx index 68aec0a..63422a3 100644 --- a/src/components/Common/Tooltip.tsx +++ b/src/components/Common/Tooltip.tsx @@ -2,50 +2,50 @@ import { useState, useRef, useEffect, CSSProperties } from 'react'; import Portal from './Portal'; // Import your Portal component export const Tooltip = ({ children, content, verticalOffset = 12 }: Tooltip) => { - const [show, setShow] = useState(false); - const [position, setPosition] = useState({}); - const tooltipRef = useRef(null); - const contentRef = useRef(null); // Ref for the tooltip content + const [show, setShow] = useState(false); + const [position, setPosition] = useState({}); + const tooltipRef = useRef(null); + const contentRef = useRef(null); // Ref for the tooltip content - useEffect(() => { - if (tooltipRef.current && contentRef.current && show) { - const targetRect = tooltipRef.current.getBoundingClientRect(); - const tooltipRect = contentRef.current.getBoundingClientRect(); + useEffect(() => { + if (tooltipRef.current && contentRef.current && show) { + const targetRect = tooltipRef.current.getBoundingClientRect(); + const tooltipRect = contentRef.current.getBoundingClientRect(); - let left = targetRect.left + window.scrollX + (targetRect.width / 2); // Center align - const top = targetRect.bottom + window.scrollY + verticalOffset; + let left = targetRect.left + window.scrollX + (targetRect.width / 2); // Center align + const top = targetRect.bottom + window.scrollY + verticalOffset; - // Check if the tooltip is going off the right side of the screen - if (left + tooltipRect.width > window.innerWidth) { - left = window.innerWidth - tooltipRect.width / 2 - 10; // Adjust to keep it on screen - } - // Check if the tooltip is going off the left side of the screen - if (left - tooltipRect.width / 2 < 0) { - left += 10; // Adjust to keep it on screen - } + // Check if the tooltip is going off the right side of the screen + if (left + tooltipRect.width > window.innerWidth) { + left = window.innerWidth - tooltipRect.width / 2 - 10; // Adjust to keep it on screen + } + // Check if the tooltip is going off the left side of the screen + if (left - tooltipRect.width / 2 < 0) { + left += 10; // Adjust to keep it on screen + } - setPosition({ - top: top, - left: left, - position: 'absolute' - }); - } - }, [show, content, verticalOffset]); // Added 'content' to dependencies array + setPosition({ + top: top, + left: left, + position: 'absolute' + }); + } + }, [show, content, verticalOffset]); // Added 'content' to dependencies array - return ( - setShow(true)} - onMouseLeave={() => setShow(false)} - ref={tooltipRef}> - {children} - {show && ( - -
-
-
{content}
-
- - )} - - ); + return ( + setShow(true)} + onMouseLeave={() => setShow(false)} + ref={tooltipRef}> + {children} + {show && ( + +
+
+
{content}
+
+ + )} + + ); }; \ No newline at end of file diff --git a/src/components/LayoutContainer.tsx b/src/components/LayoutContainer.tsx index 7209fd5..72c8489 100644 --- a/src/components/LayoutContainer.tsx +++ b/src/components/LayoutContainer.tsx @@ -5,6 +5,7 @@ import SplitPane from 'react-split-pane'; import { useSettings } from './SettingsContext'; import { saveHomePageSettings } from '../functions/utility'; +// eslint-disable-next-line @typescript-eslint/no-unused-vars export const LayoutContainer = ({ id }: { id?: string }) => { const defaultMinSize = 250; const defaultMaxSize = 500; @@ -44,6 +45,7 @@ export const LayoutContainer = ({ id }: { id?: string }) => { if (sideBarWidth !== null && settings) { saveHomePageSettings({ ...settings, sideBarWidth: sideBarWidth.toString() }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [sideBarWidth]); const setHomePageSettings = (settingsJson: string) => { @@ -52,7 +54,7 @@ export const LayoutContainer = ({ id }: { id?: string }) => { const settingsObject = JSON.parse(settingsJson); updateSettings(settingsObject); } else { - console.log(`Received null or empty settings`); + console.log('Received null or empty settings'); } } catch (exception) { console.log(`Failed to set the HomePage settings with the following error ${exception}`); @@ -68,6 +70,7 @@ export const LayoutContainer = ({ id }: { id?: string }) => { delete window.setShowStartPageChanged; delete window.setHomePageSettings; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isDisabled, settings]); const parseOrDefault = (value: string | undefined, defaultValue: number) => { diff --git a/src/components/Learning/Carousel.tsx b/src/components/Learning/Carousel.tsx index e56e34b..b1518eb 100644 --- a/src/components/Learning/Carousel.tsx +++ b/src/components/Learning/Carousel.tsx @@ -3,32 +3,32 @@ import { OpenArrow } from '../Common/Arrow'; import styles from './Carousel.module.css'; export const Carousel = ({ children }: {children: ReactNode}) => { - const [currentIndex, setCurrentIndex] = useState(0); - const itemsPerPage = 4; - const totalItems = React.Children.count(children); - const maxIndex = totalItems - itemsPerPage + const [currentIndex, setCurrentIndex] = useState(0); + const itemsPerPage = 4; + const totalItems = React.Children.count(children); + const maxIndex = totalItems - itemsPerPage; - const goLeft = () => { - setCurrentIndex(currentIndex === 0 ? maxIndex : currentIndex - 1); - }; + const goLeft = () => { + setCurrentIndex(currentIndex === 0 ? maxIndex : currentIndex - 1); + }; - const goRight = () => { - setCurrentIndex(currentIndex === maxIndex ? 0 : currentIndex + 1); - } + const goRight = () => { + setCurrentIndex(currentIndex === maxIndex ? 0 : currentIndex + 1); + }; - return ( -
- -
-
- {children} -
-
- + return ( +
+ +
+
+ {children}
- ); +
+ +
+ ); }; diff --git a/src/components/Learning/GuideGridItem.tsx b/src/components/Learning/GuideGridItem.tsx index aa47dda..7001c33 100644 --- a/src/components/Learning/GuideGridItem.tsx +++ b/src/components/Learning/GuideGridItem.tsx @@ -2,18 +2,19 @@ import { img } from '../../assets/home'; import { startGuidedTour } from '../../functions/utility'; import { CardItem } from '../Common/CardItem'; +// eslint-disable-next-line @typescript-eslint/no-unused-vars export const GuideGridItem = ({ id, Name, Description, Type, Thumbnail }: Guide) => { - const triggerStartGuidedTourCommand = () => { - startGuidedTour(Type); - }; + const triggerStartGuidedTourCommand = () => { + startGuidedTour(Type); + }; - return ( - - ); -} \ No newline at end of file + return ( + + ); +}; \ No newline at end of file diff --git a/src/components/Learning/ModalItem.tsx b/src/components/Learning/ModalItem.tsx index 2c31179..c6c8eeb 100644 --- a/src/components/Learning/ModalItem.tsx +++ b/src/components/Learning/ModalItem.tsx @@ -2,22 +2,22 @@ import ReactDOM from 'react-dom'; import styles from './ModalItem.module.css'; const ModalItem = ({ isOpen, onClose, children }: ModalItem) => { - if (!isOpen) return null; + if (!isOpen) return null; - return ReactDOM.createPortal( - <> -
-
-
- {children} -
- -
- , + return ReactDOM.createPortal( + <> +
+
+
+ {children} +
+ +
+ , document.getElementById('modal-root') as HTMLElement// Ensure you have a div with this id in your index.html - ); + ); }; export default ModalItem; \ No newline at end of file diff --git a/src/components/Learning/PageLearning.tsx b/src/components/Learning/PageLearning.tsx index 12c8ecd..76b7c32 100644 --- a/src/components/Learning/PageLearning.tsx +++ b/src/components/Learning/PageLearning.tsx @@ -1,89 +1,92 @@ import { useState, useEffect } from 'react'; import { VideoCarouselItem } from './VideoCarouselItem'; -import { Carousel } from "./Carousel"; -import { GuideGridItem } from "./GuideGridItem"; +import { Carousel } from './Carousel'; +import { GuideGridItem } from './GuideGridItem'; import { FormattedMessage } from 'react-intl'; export function LearningPage(){ - // Set a placeholder for the guides, and videos which will be used differently during dev and prod - let initialGuides: Guide[] = []; - let initialVideos: VideoCarouselItem[] = []; + // Set a placeholder for the guides, and videos which will be used differently during dev and prod + let initialGuides: Guide[] = []; + let initialVideos: VideoCarouselItem[] = []; - // If we are under development, we will load the graphs from the local asset folder - if (process.env.NODE_ENV === 'development') { - initialGuides = require('../../assets/learning').guides; - initialVideos = require('../../assets/learning').videos; - } + // If we are under development, we will load the graphs from the local asset folder + if (process.env.NODE_ENV === 'development') { + // eslint-disable-next-line @typescript-eslint/no-require-imports + initialGuides = require('../../assets/learning').guides; + // eslint-disable-next-line @typescript-eslint/no-require-imports + initialVideos = require('../../assets/learning').videos; + } - const [guides, setGuides] = useState(initialGuides); - const [videos, setVideos] = useState(initialVideos); + const [guides, setGuides] = useState(initialGuides); + const [videos, setVideos] = useState(initialVideos); - // A method exposed to the backend used to set the interactive guides data coming from Dynamo - const receiveInteractiveGuidesDataFromDotNet = (jsonData: any) => { - try { - // jsonData is already an object, so no need to parse it - const data = jsonData; - setGuides(data); - } catch (error) { - console.error('Error processing guides data:', error); - } - }; + // A method exposed to the backend used to set the interactive guides data coming from Dynamo + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const receiveInteractiveGuidesDataFromDotNet = (jsonData: any) => { + try { + // jsonData is already an object, so no need to parse it + const data = jsonData; + setGuides(data); + } catch (error) { + console.error('Error processing guides data:', error); + } + }; - // A method exposed to the backend used to set the training video data coming from Dynamo - const receiveTrainingVideoDataFromDotNet = (jsonData) => { - try { - // jsonData is already an object, so no need to parse it - const data = jsonData; - setVideos(data); - } catch (error) { - console.error('Error processing videos data:', error); - } - }; + // A method exposed to the backend used to set the training video data coming from Dynamo + const receiveTrainingVideoDataFromDotNet = (jsonData) => { + try { + // jsonData is already an object, so no need to parse it + const data = jsonData; + setVideos(data); + } catch (error) { + console.error('Error processing videos data:', error); + } + }; - useEffect(() => { - // If we are under production, we will override the graphs with the actual data sent from Dynamo - if (process.env.NODE_ENV !== 'development') { - window.receiveInteractiveGuidesDataFromDotNet = receiveInteractiveGuidesDataFromDotNet; - window.receiveTrainingVideoDataFromDotNet = receiveTrainingVideoDataFromDotNet; - } + useEffect(() => { + // If we are under production, we will override the graphs with the actual data sent from Dynamo + if (process.env.NODE_ENV !== 'development') { + window.receiveInteractiveGuidesDataFromDotNet = receiveInteractiveGuidesDataFromDotNet; + window.receiveTrainingVideoDataFromDotNet = receiveTrainingVideoDataFromDotNet; + } - // Cleanup function (optional) - return () => { - if (process.env.NODE_ENV !== 'development') { - delete window.receiveInteractiveGuidesDataFromDotNet; - delete window.receiveTrainingVideoDataFromDotNet; - } - }; - }, []); + // Cleanup function (optional) + return () => { + if (process.env.NODE_ENV !== 'development') { + delete window.receiveInteractiveGuidesDataFromDotNet; + delete window.receiveTrainingVideoDataFromDotNet; + } + }; + }, []); - return( -
-
-

-
-
-
-

-
-
- {guides.map(guide => ( - - ))} -
-
-
-
-
-

-
- - {videos.map(video => ( -
- -
- ))} -
-
+ return( +
+
+

+
+
+
+

- ) +
+ {guides.map(guide => ( + + ))} +
+
+
+
+
+

+
+ + {videos.map(video => ( +
+ +
+ ))} +
+
+
+ ); } \ No newline at end of file diff --git a/src/components/Learning/VideoCarouselItem.tsx b/src/components/Learning/VideoCarouselItem.tsx index 9420fbd..4981516 100644 --- a/src/components/Learning/VideoCarouselItem.tsx +++ b/src/components/Learning/VideoCarouselItem.tsx @@ -3,51 +3,52 @@ import ModalItem from './ModalItem'; // Import your Modal component import { Tooltip } from '../Common/Tooltip'; import styles from './VideoCarouselItem.module.css'; +// eslint-disable-next-line @typescript-eslint/no-unused-vars export function VideoCarouselItem({ id, title, videoId, description }: VideoCarouselItem) { - const [isModalOpen, setIsModalOpen] = useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); - const youtubeEmbedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1`; // Added autoplay query parameter - const tooltip =
- {title} -

- {description} -
; + const youtubeEmbedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1`; // Added autoplay query parameter + const tooltip =
+ {title} +

+ {description} +
; - const handleVideoClick = () => { - setIsModalOpen(true); // Open the modal on click - }; + const handleVideoClick = () => { + setIsModalOpen(true); // Open the modal on click + }; - return ( -
-
- { !isModalOpen &&
} - -
- setIsModalOpen(false)}> - - -
-

{title}

- -

- {description} -

-
-
-
- ); + return ( +
+
+ { !isModalOpen &&
} + +
+ setIsModalOpen(false)}> + + +
+

{title}

+ +

+ {description} +

+
+
+
+ ); } \ No newline at end of file diff --git a/src/components/MainContent.tsx b/src/components/MainContent.tsx index a38c327..08c6d8d 100644 --- a/src/components/MainContent.tsx +++ b/src/components/MainContent.tsx @@ -1,4 +1,3 @@ -import { useState, useEffect } from 'react'; import { RecentPage } from './Recent/PageRecent'; import { SamplesPage } from './Samples/PageSamples'; import { LearningPage } from './Learning/PageLearning'; @@ -6,26 +5,26 @@ import { FormattedMessage } from 'react-intl'; export const MainContent = ({ selectedSidebarItem, settings, isDisabled, setIsDisabled }: MainContentProps) => { - return ( - <> -
- {isDisabled && ( -
-
-
-
- )} + return ( + <> +
+ {isDisabled && ( +
+
+
+
+ )} -
- -
-
- -
-
- -
-
- - ) -} \ No newline at end of file +
+ +
+
+ +
+
+ +
+
+ + ); +}; \ No newline at end of file diff --git a/src/components/Recent/CustomAuthorCellRenderer.tsx b/src/components/Recent/CustomAuthorCellRenderer.tsx index bca2a98..9c3f5f8 100644 --- a/src/components/Recent/CustomAuthorCellRenderer.tsx +++ b/src/components/Recent/CustomAuthorCellRenderer.tsx @@ -14,11 +14,11 @@ export const CustomAuthorCellRenderer = ({ value }: CellParams) => { const isOldFormat = value === intl.formatMessage({ id: 'recent.item.old.format' }); return ( -
-

{value}

- {isOldFormat && +
+

{value}

+ {isOldFormat && }> - + }
); diff --git a/src/components/Recent/CustomLocationCellRenderer.tsx b/src/components/Recent/CustomLocationCellRenderer.tsx index 8364c0d..32bb15a 100644 --- a/src/components/Recent/CustomLocationCellRenderer.tsx +++ b/src/components/Recent/CustomLocationCellRenderer.tsx @@ -8,12 +8,12 @@ import styles from './CustomCellRenderer.module.css'; export const CustomLocationCellRenderer = ({ value }: CellParams) => { return ( -
-
- - {value} - -
+
+
+ + {value} + +
); }; diff --git a/src/components/Recent/CustomNameCellRenderer.tsx b/src/components/Recent/CustomNameCellRenderer.tsx index 8544b8e..09919e6 100644 --- a/src/components/Recent/CustomNameCellRenderer.tsx +++ b/src/components/Recent/CustomNameCellRenderer.tsx @@ -17,18 +17,18 @@ export const CustomNameCellRenderer = ({ value, row }: CellParams) => { const imgSrc = hasCustomThumbnail ? thumbnail : getPlaceholderImage(row.original.ContextData); const description = row.original.Description; return ( -
+
-
- {description - ? {value} - : value - } -
+
+ {description + ? {value} + : value + } +
); }; diff --git a/src/components/Recent/GraphGridItem.tsx b/src/components/Recent/GraphGridItem.tsx index 4557003..75fcea7 100644 --- a/src/components/Recent/GraphGridItem.tsx +++ b/src/components/Recent/GraphGridItem.tsx @@ -3,33 +3,34 @@ import { openFile } from '../../functions/utility'; import { CardItem } from '../Common/CardItem'; import { img } from '../../assets/home'; +// eslint-disable-next-line @typescript-eslint/no-unused-vars export const GraphGridItem = ({ id, Caption, ContextData, Description, DateModified, Thumbnail, setIsDisabled }: GraphItem) => { - const handleClick = (e:MouseEvent) => { - // freezes the UI - setIsDisabled(true); + const handleClick = (e:MouseEvent) => { + // freezes the UI + setIsDisabled(true); - e.preventDefault(); - openFile(ContextData); - }; + e.preventDefault(); + openFile(ContextData); + }; - // Use placeholder if Thumbnail is empty, null, undefined, or the default img - const thumbnail = Thumbnail; - const hasCustomThumbnail = thumbnail && thumbnail !== img && thumbnail.trim() !== ''; - const imageSrc = hasCustomThumbnail ? thumbnail : getPlaceholderImage(ContextData); + // Use placeholder if Thumbnail is empty, null, undefined, or the default img + const thumbnail = Thumbnail; + const hasCustomThumbnail = thumbnail && thumbnail !== img && thumbnail.trim() !== ''; + const imageSrc = hasCustomThumbnail ? thumbnail : getPlaceholderImage(ContextData); - return ( - -
{Caption}
-
{ContextData}
-
{Description}
- - } - titleText={Caption} - subtitleText={DateModified} - /> - ); + return ( + +
{Caption}
+
{ContextData}
+
{Description}
+ + } + titleText={Caption} + subtitleText={DateModified} + /> + ); }; \ No newline at end of file diff --git a/src/components/Recent/GraphTable.tsx b/src/components/Recent/GraphTable.tsx index bff0b17..5517996 100644 --- a/src/components/Recent/GraphTable.tsx +++ b/src/components/Recent/GraphTable.tsx @@ -1,11 +1,12 @@ -import React from "react"; -import { useTable, useFlexLayout, useResizeColumns } from "react-table"; +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, react/jsx-key */ +import React from 'react'; +import { useTable, useFlexLayout, useResizeColumns } from 'react-table'; import styles from '../Common/Table.module.css'; export const GraphTable = ({ columns, data, onRowClick }: GraphTable) => { const defaultColumn = React.useMemo( () => ({ - size: "auto", // Width of the column + size: 'auto', // Width of the column minWidth: 50, maxWidth: 300, resizable: true, // Make all columns resizable @@ -19,15 +20,15 @@ export const GraphTable = ({ columns, data, onRowClick }: GraphTable) => { rows, prepareRow, resetResizing - } = useTable( - { - columns, - data, - defaultColumn - }, - useFlexLayout, - useResizeColumns - ); + } = useTable( + { + columns, + data, + defaultColumn + }, + useFlexLayout, + useResizeColumns + ); const handleRowClick = (row:Row) => { // Call the passed onRowClick function with row information @@ -37,48 +38,48 @@ export const GraphTable = ({ columns, data, onRowClick }: GraphTable) => { }; return ( -
-
- - - {console.log(headerGroups)} - {headerGroups.map((headerGroup) => ( - - {headerGroup.headers.map((column: any, columnIndex: number) => ( - - ))} - - ))} - - - {rows.map((row: Row) => { - prepareRow(row); - return ( - handleRowClick(row), - style: { cursor: "pointer" }, - })} - > - {row.cells.map((cell: Cell) => { - return ; - })} +
+
+
- {column.render("Header")} - {/* Add resizer div for all columns except the last one */} - {columnIndex < headerGroup.headers.length - 1 && ( -
event.stopPropagation()} - /> - )} -
{cell.render("Cell")}
+ + {console.log(headerGroups)} + {headerGroups.map((headerGroup) => ( + + {headerGroup.headers.map((column: any, columnIndex: number) => ( + + ))} - ); - })} - -
+ {column.render('Header')} + {/* Add resizer div for all columns except the last one */} + {columnIndex < headerGroup.headers.length - 1 && ( +
event.stopPropagation()} + /> + )} +
+ ))} + + + {rows.map((row: Row) => { + prepareRow(row); + return ( + handleRowClick(row), + style: { cursor: 'pointer' }, + })} + > + {row.cells.map((cell: Cell) => { + return {cell.render('Cell')}; + })} + + ); + })} + + +
-
); }; diff --git a/src/components/Recent/PageRecent.tsx b/src/components/Recent/PageRecent.tsx index 7b141ea..57ef6a7 100644 --- a/src/components/Recent/PageRecent.tsx +++ b/src/components/Recent/PageRecent.tsx @@ -1,9 +1,9 @@ -import React from "react"; +import React from 'react'; import { useState, useEffect } from 'react'; import { GraphGridItem } from './GraphGridItem'; import { CustomNameCellRenderer } from './CustomNameCellRenderer'; import { CustomLocationCellRenderer } from './CustomLocationCellRenderer'; -import { CustomAuthorCellRenderer } from "./CustomAuthorCellRenderer"; +import { CustomAuthorCellRenderer } from './CustomAuthorCellRenderer'; import { GraphTable } from './GraphTable'; import { GridViewIcon, ListViewIcon } from '../Common/CustomIcons'; import { openFile, saveHomePageSettings } from '../../functions/utility'; @@ -12,134 +12,136 @@ import { Tooltip } from '../Common/Tooltip'; import { useSettings } from '../SettingsContext'; export const RecentPage = ({ setIsDisabled, recentPageViewMode }: RecentPage) => { - const { settings, updateSettings } = useSettings(); - const [viewMode, setViewMode] = useState(recentPageViewMode); - const [initialized, setInitialized] = useState(false); + const { settings, updateSettings } = useSettings(); + const [viewMode, setViewMode] = useState(recentPageViewMode); + const [initialized, setInitialized] = useState(false); - // Set a placeholder for the graphs which will be used differently during dev and prod - let initialGraphs = []; + // Set a placeholder for the graphs which will be used differently during dev and prod + let initialGraphs = []; - // If we are under development, we will load the graphs from the local asset folder - if (process.env.NODE_ENV === 'development') { - initialGraphs = require('../../assets/home').graphs; - } + // If we are under development, we will load the graphs from the local asset folder + if (process.env.NODE_ENV === 'development') { + // eslint-disable-next-line @typescript-eslint/no-require-imports + initialGraphs = require('../../assets/home').graphs; + } - const [graphs, setGraphs] = useState(initialGraphs); + const [graphs, setGraphs] = useState(initialGraphs); - // A method exposed to the backend used to set the graph data coming from Dynamo - const receiveGraphDataFromDotNet = (jsonData) => { - try { - // jsonData is already an object, so no need to parse it - const data = jsonData; - setGraphs(data); - } catch (error) { - console.error('Error processing data:', error); - } - }; + // A method exposed to the backend used to set the graph data coming from Dynamo + const receiveGraphDataFromDotNet = (jsonData) => { + try { + // jsonData is already an object, so no need to parse it + const data = jsonData; + setGraphs(data); + } catch (error) { + console.error('Error processing data:', error); + } + }; - useEffect(() => { - // If we are under production, we will override the graphs with the actual data sent from Dynamo - if (process.env.NODE_ENV !== 'development') { - window.receiveGraphDataFromDotNet = receiveGraphDataFromDotNet; - } + useEffect(() => { + // If we are under production, we will override the graphs with the actual data sent from Dynamo + if (process.env.NODE_ENV !== 'development') { + window.receiveGraphDataFromDotNet = receiveGraphDataFromDotNet; + } - // Cleanup function (optional) - return () => { - if (process.env.NODE_ENV !== 'development') { - delete window.receiveGraphDataFromDotNet; - } - }; - }, []); + // Cleanup function (optional) + return () => { + if (process.env.NODE_ENV !== 'development') { + delete window.receiveGraphDataFromDotNet; + } + }; + }, []); - useEffect(() => { - // Set the viewMode based on the HomePage preferences - setViewMode(recentPageViewMode); - }, [recentPageViewMode]); + useEffect(() => { + // Set the viewMode based on the HomePage preferences + setViewMode(recentPageViewMode); + }, [recentPageViewMode]); - useEffect(() => { - if (initialized || recentPageViewMode !== viewMode) { - setInitialized(true); - updateSettings({ recentPageViewMode: viewMode }); + useEffect(() => { + if (initialized || recentPageViewMode !== viewMode) { + setInitialized(true); + updateSettings({ recentPageViewMode: viewMode }); - // Send settings to Dynamo to save - saveHomePageSettings({ ...settings, recentPageViewMode: viewMode }); - } - }, [viewMode]); + // Send settings to Dynamo to save + saveHomePageSettings({ ...settings, recentPageViewMode: viewMode }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [viewMode]); - // This variable defins the table structure displaying the graphs - const columns: Column[] = React.useMemo(() => [ - { - Header: 'Title', - accessor: 'Caption', - width: 300, - resizable: true, - Cell: CustomNameCellRenderer, - }, - { - Header: 'Author', - accessor: 'Author', - resizable: true, - Cell: CustomAuthorCellRenderer, - }, - { - Header: 'Date Modified', - accessor: 'DateModified', - resizable: true, - }, - { - Header: 'Location', - accessor: 'ContextData', - resizable: true, - Cell: CustomLocationCellRenderer, - } - ], []); + // This variable defins the table structure displaying the graphs + const columns: Column[] = React.useMemo(() => [ + { + Header: 'Title', + accessor: 'Caption', + width: 300, + resizable: true, + Cell: CustomNameCellRenderer, + }, + { + Header: 'Author', + accessor: 'Author', + resizable: true, + Cell: CustomAuthorCellRenderer, + }, + { + Header: 'Date Modified', + accessor: 'DateModified', + resizable: true, + }, + { + Header: 'Location', + accessor: 'ContextData', + resizable: true, + Cell: CustomLocationCellRenderer, + } + ], []); - // Handles mouse click over each row - const handleRowClick = (row: Row) => { - // freezes the UI - setIsDisabled(true); + // Handles mouse click over each row + const handleRowClick = (row: Row) => { + // freezes the UI + setIsDisabled(true); - const contextData = row.original.ContextData; - openFile(contextData); - }; + const contextData = row.original.ContextData; + openFile(contextData); + }; - return( -
-
-

-
-
- - -
-
- {viewMode === 'list' && ( - - )} - {viewMode === 'grid' && ( -
- {graphs.map(graph => ( - - ))} -
- )} -
-
- ) -} \ No newline at end of file + return( +
+
+

+
+
+ + +
+
+ {viewMode === 'list' && ( + + )} + {viewMode === 'grid' && ( +
+ {graphs.map(graph => ( + + ))} +
+ )} +
+
+ ); +}; \ No newline at end of file diff --git a/src/components/Samples/CustomSampleFirstCellRenderer.tsx b/src/components/Samples/CustomSampleFirstCellRenderer.tsx index d67765e..8c32c79 100644 --- a/src/components/Samples/CustomSampleFirstCellRenderer.tsx +++ b/src/components/Samples/CustomSampleFirstCellRenderer.tsx @@ -9,6 +9,7 @@ export const CustomSampleFirstCellRenderer = ({ value, row, rows, rowIndex, coll const isChildRow = row.original.parentId !== null; const depth = row.original.depth || 0; const indent = (depth - 1) * 20; // Adjust the indent as needed + // eslint-disable-next-line @typescript-eslint/no-unused-vars const arrowIndent = (depth) * 20; // Adjust the indent as needed const isParentRow = row.original.isParent; @@ -79,13 +80,13 @@ export const CustomSampleFirstCellRenderer = ({ value, row, rows, rowIndex, coll justifyContent: 'center', marginRight: '10px' }} - > + > {/* cell content */} -
{value}
+
{value}
); } @@ -101,7 +102,7 @@ export const CustomSampleFirstCellRenderer = ({ value, row, rows, rowIndex, coll justifyContent: 'center', marginRight: '10px' }} - > + > diff --git a/src/components/Samples/PageSamples.tsx b/src/components/Samples/PageSamples.tsx index 990276a..cbd8fff 100644 --- a/src/components/Samples/PageSamples.tsx +++ b/src/components/Samples/PageSamples.tsx @@ -1,10 +1,10 @@ -import React from "react"; +import React from 'react'; import { useState, useEffect } from 'react'; import { SamplesTable } from './SamplesTable'; import { FormattedMessage } from 'react-intl'; import { GridViewIcon, ListViewIcon } from '../Common/CustomIcons'; import { Tooltip } from '../Common/Tooltip'; -import { CustomSampleFirstCellRenderer } from "./CustomSampleFirstCellRenderer"; +import { CustomSampleFirstCellRenderer } from './CustomSampleFirstCellRenderer'; import { SamplesGrid } from './SamplesGrid'; import { openFile, showSamplesCommand, saveHomePageSettings } from '../../functions/utility'; import { useSettings } from '../SettingsContext'; @@ -12,149 +12,154 @@ import { CustomDropdown } from '../Sidebar/CustomDropDown'; import styles from './PageSamples.module.css'; export const SamplesPage = ({ samplesViewMode }) => { - const { settings, updateSettings } = useSettings(); - const [viewMode, setViewMode] = useState(samplesViewMode); - const [collapsedRows, setCollapsedRows] = useState({}); - const [initialized, setInitialized] = useState(false); + const { settings, updateSettings } = useSettings(); + const [viewMode, setViewMode] = useState(samplesViewMode); + const [collapsedRows, setCollapsedRows] = useState({}); + const [initialized, setInitialized] = useState(false); - // Set a placeholder for the graphs which will be used differently during dev and prod - let initialSamples = []; + // Set a placeholder for the graphs which will be used differently during dev and prod + let initialSamples = []; - // If we are under development, we will load the graphs from the local asset folder - if (process.env.NODE_ENV === 'development') { - initialSamples = require('../../assets/samples').samples; - } + // If we are under development, we will load the graphs from the local asset folder + if (process.env.NODE_ENV === 'development') { + // eslint-disable-next-line @typescript-eslint/no-require-imports + initialSamples = require('../../assets/samples').samples; + } - const [samples, setSamples] = useState(initialSamples); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const [samples, setSamples] = useState(initialSamples); - // A method exposed to the backend used to set the samples data coming from Dynamo - const receiveSamplesDataFromDotNet = (jsonData: any) => { - try { - // jsonData is already an object, so no need to parse it - const data = jsonData; - setSamples(data); - } catch (error) { - console.error('Error processing data:', error); - } - }; + // A method exposed to the backend used to set the samples data coming from Dynamo + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const receiveSamplesDataFromDotNet = (jsonData: any) => { + try { + // jsonData is already an object, so no need to parse it + const data = jsonData; + setSamples(data); + } catch (error) { + console.error('Error processing data:', error); + } + }; - const handleCollapsedRowsChange = (newCollapsedRows: CollapsedRow) => { - setCollapsedRows(newCollapsedRows); - }; + const handleCollapsedRowsChange = (newCollapsedRows: CollapsedRow) => { + setCollapsedRows(newCollapsedRows); + }; - useEffect(() => { - // If we are under production, we will override the graphs with the actual data sent from Dynamo - if (process.env.NODE_ENV !== 'development') { - window.receiveSamplesDataFromDotNet = receiveSamplesDataFromDotNet; - } + useEffect(() => { + // If we are under production, we will override the graphs with the actual data sent from Dynamo + if (process.env.NODE_ENV !== 'development') { + window.receiveSamplesDataFromDotNet = receiveSamplesDataFromDotNet; + } - // Cleanup function (optional) - return () => { - if (process.env.NODE_ENV !== 'development') { - delete window.receiveSamplesDataFromDotNet; - } - }; - }, []); + // Cleanup function (optional) + return () => { + if (process.env.NODE_ENV !== 'development') { + delete window.receiveSamplesDataFromDotNet; + } + }; + }, []); - useEffect(() => { - // Set the viewMode based on the HomePage preferences - setViewMode(samplesViewMode); - }, [samplesViewMode]); + useEffect(() => { + // Set the viewMode based on the HomePage preferences + setViewMode(samplesViewMode); + }, [samplesViewMode]); - useEffect(() => { - if (initialized || samplesViewMode !== viewMode) { - setInitialized(true); - updateSettings({ samplesViewMode: viewMode }); + useEffect(() => { + if (initialized || samplesViewMode !== viewMode) { + setInitialized(true); + updateSettings({ samplesViewMode: viewMode }); - // Send settings to Dynamo to save - saveHomePageSettings({ ...settings, samplesViewMode: viewMode }); - } - }, [viewMode]); + // Send settings to Dynamo to save + saveHomePageSettings({ ...settings, samplesViewMode: viewMode }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [viewMode]); - // This variable defins the table structure displaying the graphs - const columns = React.useMemo(() => [ - { - Header: 'Title', - accessor: 'FileName', - width: 120, - resizable: true, - Cell: ({ cell, row, rows, rowIndex }) => - CustomSampleFirstCellRenderer({ - ...cell, - row, - rows, - rowIndex: row.index, - collapsedRows - }) - }, - { - Header: 'Description', - accessor: 'FilePath', - resizable: true, - } - ], [collapsedRows]); + // This variable defins the table structure displaying the graphs + const columns = React.useMemo(() => [ + { + Header: 'Title', + accessor: 'FileName', + width: 120, + resizable: true, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + Cell: ({ cell, row, rows, rowIndex }) => + CustomSampleFirstCellRenderer({ + ...cell, + row, + rows, + rowIndex: row.index, + collapsedRows + }) + }, + { + Header: 'Description', + accessor: 'FilePath', + resizable: true, + } + ], [collapsedRows]); - // Handles mouse click over each row - const handleRowClick = (row:Row) => { - openFile(row.FilePath); - }; + // Handles mouse click over each row + const handleRowClick = (row:Row) => { + openFile(row.FilePath); + }; - // Handles show samples link click - const handleShowSamplesClick = (value: ShowSamplesCommand) => { - showSamplesCommand(value); - } + // Handles show samples link click + const handleShowSamplesClick = (value: ShowSamplesCommand) => { + showSamplesCommand(value); + }; - return ( -
-
-

-
-
- - -
- } - onSelectionChange={handleShowSamplesClick} - options={[ - { label: , value: 'open-graphs' }, - { label: , value: 'open-datasets' } - ]} - className={styles.wideDropdown} - showDivider={false} - wholeButtonActionable={true} - disableArrowHoverShadow={true} - /> -
-
-
- {viewMode === 'list' && ( - - )} - {viewMode === 'grid' && ( -
- -
- )} -
+ return ( +
+
+

+
+
+ + +
+ } + onSelectionChange={handleShowSamplesClick} + options={[ + { label: , value: 'open-graphs' }, + { label: , value: 'open-datasets' } + ]} + className={styles.wideDropdown} + showDivider={false} + wholeButtonActionable={true} + disableArrowHoverShadow={true} + />
- ) -} \ No newline at end of file +
+
+ {viewMode === 'list' && ( + + )} + {viewMode === 'grid' && ( +
+ +
+ )} +
+
+ ); +}; \ No newline at end of file diff --git a/src/components/Samples/SamplesGrid.tsx b/src/components/Samples/SamplesGrid.tsx index 185a384..e1dffe0 100644 --- a/src/components/Samples/SamplesGrid.tsx +++ b/src/components/Samples/SamplesGrid.tsx @@ -1,52 +1,52 @@ -import { SamplesGridItem } from "./SamplesGridItem"; +import { SamplesGridItem } from './SamplesGridItem'; import styles from './SamplesGrid.module.css'; const renderSample = (sample: Samples, keyPrefix: string | number) => { - if (sample.Children && sample.Children.length > 0) { - // Separate the children into leaf nodes and nested nodes - const leafNodes = sample.Children.filter(child => !child.Children || child.Children.length === 0); - const nestedNodes = sample.Children.filter(child => child.Children && child.Children.length > 0); + if (sample.Children && sample.Children.length > 0) { + // Separate the children into leaf nodes and nested nodes + const leafNodes = sample.Children.filter(child => !child.Children || child.Children.length === 0); + const nestedNodes = sample.Children.filter(child => child.Children && child.Children.length > 0); - return ( -
-
-

{sample.FileName}

-
-
- {leafNodes.map((child: Samples, index: number) => ( - - ))} -
- {nestedNodes.map((nested, nestedIndex) => renderSample(nested, nested.FileName || nestedIndex))} -
- ); - } else { - // Render a SamplesGridItem for leaf nodes - return ( -
-
- -
-
- ); - } -}; - -export const SamplesGrid = ({ data }:{ data: Samples[]}) => { - const rootChildren = data[0]?.Children || []; return ( -
- {rootChildren.map((sample: Samples, index) => renderSample(sample, sample.FileName || index))} +
+
+

{sample.FileName}

+
+
+ {leafNodes.map((child: Samples, index: number) => ( + + ))} +
+ {nestedNodes.map((nested, nestedIndex) => renderSample(nested, nested.FileName || nestedIndex))} +
+ ); + } else { + // Render a SamplesGridItem for leaf nodes + return ( +
+
+
+
); + } +}; + +export const SamplesGrid = ({ data }:{ data: Samples[]}) => { + const rootChildren = data[0]?.Children || []; + return ( +
+ {rootChildren.map((sample: Samples, index) => renderSample(sample, sample.FileName || index))} +
+ ); }; \ No newline at end of file diff --git a/src/components/Samples/SamplesGridItem.tsx b/src/components/Samples/SamplesGridItem.tsx index 21b76a0..ce87e2b 100644 --- a/src/components/Samples/SamplesGridItem.tsx +++ b/src/components/Samples/SamplesGridItem.tsx @@ -3,19 +3,19 @@ import { openFile } from '../../functions/utility'; import { CardItem } from '../Common/CardItem'; export const SamplesGridItem = ({ FileName, FilePath, Description, DateModified, Thumbnail }: Samples) => { - const handleClick = (e: MouseEvent) => { - e.preventDefault(); - openFile(FilePath); - }; + const handleClick = (e: MouseEvent) => { + e.preventDefault(); + openFile(FilePath); + }; - return ( - - ); -} + return ( + + ); +}; diff --git a/src/components/Samples/SamplesTable.tsx b/src/components/Samples/SamplesTable.tsx index 008b107..35213b6 100644 --- a/src/components/Samples/SamplesTable.tsx +++ b/src/components/Samples/SamplesTable.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any, react/jsx-key, react-hooks/rules-of-hooks, react-hooks/exhaustive-deps */ import React, { useState, useEffect } from 'react'; import { useTable, useFlexLayout, useResizeColumns } from 'react-table'; import styles from '../Common/Table.module.css'; @@ -41,7 +42,7 @@ export const SamplesTable = ({ columns, data, onRowClick, onCollapsedRowsChange const flattenData = (data: Samples, parentId = null, depth = 0): any[] => { if (!Array.isArray(data) || data.length === 0) { - return []; + return []; } const startingData = parentId === null ? data.flatMap(d => d.Children || []) : data; @@ -51,14 +52,14 @@ export const SamplesTable = ({ columns, data, onRowClick, onCollapsedRowsChange }, [collapsedRows, onCollapsedRowsChange]); return startingData.flatMap((item) => { - const isParent = item.Children && item.Children.length > 0; - // Constructing a unique ID for the parent - const id = parentId === null ? item.FileName : `${parentId}-${item.FileName}`; - const flatItem = { ...item, parentId, isParent, depth, id }; - - // When flattening children, pass the newly constructed id as their parentId - const children = isParent ? flattenData(item.Children, id, depth + 1) : []; - return [flatItem, ...children]; + const isParent = item.Children && item.Children.length > 0; + // Constructing a unique ID for the parent + const id = parentId === null ? item.FileName : `${parentId}-${item.FileName}`; + const flatItem = { ...item, parentId, isParent, depth, id }; + + // When flattening children, pass the newly constructed id as their parentId + const children = isParent ? flattenData(item.Children, id, depth + 1) : []; + return [flatItem, ...children]; }); }; @@ -75,8 +76,8 @@ export const SamplesTable = ({ columns, data, onRowClick, onCollapsedRowsChange ); return ( -
-
+
+
{headerGroups.map((headerGroup: any) => ( @@ -116,8 +117,8 @@ export const SamplesTable = ({ columns, data, onRowClick, onCollapsedRowsChange onClick: isParentRow ? () => handleCollapseClick(row.original.id) : isChildRow - ? () => handleChildRowClick(row) - : undefined + ? () => handleChildRowClick(row) + : undefined })} > {row.cells.map((cell: Cell, index: number) => { @@ -138,7 +139,7 @@ export const SamplesTable = ({ columns, data, onRowClick, onCollapsedRowsChange // Default rendering for other cells return ; + })}>{cell.render('Cell')}; })} ); diff --git a/src/components/SettingsContext.tsx b/src/components/SettingsContext.tsx index a594709..ba01c46 100644 --- a/src/components/SettingsContext.tsx +++ b/src/components/SettingsContext.tsx @@ -1,25 +1,27 @@ import { createContext, useContext, useState } from 'react'; // Create the context +// eslint-disable-next-line @typescript-eslint/no-explicit-any const SettingsContext = createContext(null); // Provider component that wraps the app components export const SettingsProvider = ({ children }) => { - const [settings, setSettings] = useState({}); + const [settings, setSettings] = useState({}); - // Update settings - const updateSettings = (newSettings: any) => { - setSettings(prev => ({ ...prev, ...newSettings })); - }; + // Update settings + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const updateSettings = (newSettings: any) => { + setSettings(prev => ({ ...prev, ...newSettings })); + }; - return ( - - {children} - - ); -} + return ( + + {children} + + ); +}; // Use settings hook export function useSettings() { - return useContext(SettingsContext); + return useContext(SettingsContext); } diff --git a/src/components/Sidebar/CustomDropDown.tsx b/src/components/Sidebar/CustomDropDown.tsx index 0f7a15c..9ef9ba4 100644 --- a/src/components/Sidebar/CustomDropDown.tsx +++ b/src/components/Sidebar/CustomDropDown.tsx @@ -3,95 +3,96 @@ import styles from './CustomDropDown.module.css'; import { OpenArrow } from '../Common/Arrow'; export const CustomDropdown = ({ - id, - options, - placeholder, - onSelectionChange, - className, - showDivider = true, - wholeButtonActionable = false, - disableArrowHoverShadow = false + id, + options, + placeholder, + onSelectionChange, + className, + showDivider = true, + wholeButtonActionable = false, + disableArrowHoverShadow = false }: Dropdown & { className?: string, showDivider?: boolean, wholeButtonActionable?: boolean, disableArrowHoverShadow?: boolean }) => { - const [isOpen, setIsOpen] = useState(false); - const [lastSelected, setLastSelected] = useState(options[0]); - const dropdownRef = useRef(null); - const arrowColor = isOpen ? "rgba(56,171,223,0.35)" : "#949494"; + const [isOpen, setIsOpen] = useState(false); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [lastSelected, setLastSelected] = useState(options[0]); + const dropdownRef = useRef(null); + const arrowColor = isOpen ? 'rgba(56,171,223,0.35)' : '#949494'; - const toggleDropdown = () => setIsOpen(!isOpen); + const toggleDropdown = () => setIsOpen(!isOpen); - /** Peforms the selected action type when used as a Drop-down */ - const handleOptionSelect = (option: option) => { - setIsOpen(false); - if (onSelectionChange) { - onSelectionChange(option.value); - } - }; + /** Peforms the selected action type when used as a Drop-down */ + const handleOptionSelect = (option: option) => { + setIsOpen(false); + if (onSelectionChange) { + onSelectionChange(option.value); + } + }; - /** Peforms the selected action type when used as a Button */ - const handleDefaultAction = () => { - if (onSelectionChange) { - onSelectionChange(lastSelected.value); - } - }; + /** Peforms the selected action type when used as a Button */ + const handleDefaultAction = () => { + if (onSelectionChange) { + onSelectionChange(lastSelected.value); + } + }; - /** Handles navigate away from the drop-down control */ - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { - setIsOpen(false); - } - }; + /** Handles navigate away from the drop-down control */ + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { + setIsOpen(false); + } + }; - if (isOpen) { - document.addEventListener('mousedown', handleClickOutside); - } + if (isOpen) { + document.addEventListener('mousedown', handleClickOutside); + } - return () => { - document.removeEventListener('mousedown', handleClickOutside); - }; - }, [isOpen]); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [isOpen]); - return ( -
-
- {placeholder} - {showDivider && } -
{ - e.stopPropagation(); - toggleDropdown(); // Arrow always toggles the dropdown - }} - > -
- -
-
-
-
- {options.map((option, index) => ( -
handleOptionSelect(option)}> - {option.label} -
- ))} -
+ ref={dropdownRef} + data-testid={`${id}-dropdown`}> +
+ {placeholder} + {showDivider && } +
{ + e.stopPropagation(); + toggleDropdown(); // Arrow always toggles the dropdown + }} + > +
+ +
- ); +
+
+ {options.map((option, index) => ( +
handleOptionSelect(option)}> + {option.label} +
+ ))} +
+
+ ); }; \ No newline at end of file diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index a24ffee..add6a4b 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -5,77 +5,77 @@ import { sideBarCommand } from '../../functions/utility'; import styles from './Sidebar.module.css'; export const Sidebar = ({ onItemSelect, selectedSidebarItem }: Sidebar) => { - const isSelected = (item: string) => selectedSidebarItem === item; + const isSelected = (item: string) => selectedSidebarItem === item; - /**Trigger the backend command based on the drop-down value */ - const setSelectedValue = (value: SidebarCommand) => { - sideBarCommand(value); - }; + /**Trigger the backend command based on the drop-down value */ + const setSelectedValue = (value: SidebarCommand) => { + sideBarCommand(value); + }; - return ( + return ( -
-
-
-

Dynamo

- {/* Files Dropdown */} - } - onSelectionChange={setSelectedValue} - options={[ - { label: , value: 'open-file' }, - { label: , value: 'open-template' }, - { label: , value: 'open-backup-locations' } - ]} - /> +
+
+
+

Dynamo

+ {/* Files Dropdown */} + } + onSelectionChange={setSelectedValue} + options={[ + { label: , value: 'open-file' }, + { label: , value: 'open-template' }, + { label: , value: 'open-backup-locations' } + ]} + /> - {/* New Dropdown */} - } - onSelectionChange={setSelectedValue} - options={[ - { label: , value: 'workspace' }, - { label: , value: 'custom-node' } - ]} - /> + {/* New Dropdown */} + } + onSelectionChange={setSelectedValue} + options={[ + { label: , value: 'workspace' }, + { label: , value: 'custom-node' } + ]} + /> -
-
onItemSelect('Recent')} data-testid="nav-recent"> - }> - - - - -
-
onItemSelect('Samples')} data-testid="nav-samples"> - }> - - - - -
-
onItemSelect('Learning')} data-testid="nav-learning"> - }> - - - - -
-
-
-
-
-
- +
+
onItemSelect('Recent')} data-testid="nav-recent"> + }> + + + +
+
onItemSelect('Samples')} data-testid="nav-samples"> + }> + + + + +
+
onItemSelect('Learning')} data-testid="nav-learning"> + }> + + + + +
+
+
+
+
+
+ - ) -} \ No newline at end of file +
+
+ ); +}; \ No newline at end of file diff --git a/src/functions/placeholder.ts b/src/functions/placeholder.ts index db903cc..079c5eb 100644 --- a/src/functions/placeholder.ts +++ b/src/functions/placeholder.ts @@ -6,13 +6,13 @@ export const getPlaceholderImage = (filePath: string): string => { const extension = filePath.toLowerCase().split('.').pop(); switch (extension) { - case 'dyn': - return placeholderDyn; - case 'dyf': - return placeholderDyf; - case 'dyt': - return placeholderDyt; - default: - return img; // fallback for unknown types + case 'dyn': + return placeholderDyn; + case 'dyf': + return placeholderDyf; + case 'dyt': + return placeholderDyt; + default: + return img; // fallback for unknown types } }; \ No newline at end of file diff --git a/src/functions/utility.ts b/src/functions/utility.ts index 0008a31..e659550 100644 --- a/src/functions/utility.ts +++ b/src/functions/utility.ts @@ -56,6 +56,7 @@ export function showSamplesCommand(value: ShowSamplesCommand) { /** * A call to a backend function requesting to save the current HomePage settings */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function saveHomePageSettings(settings: any) { if (window.chrome?.webview !== undefined) { const settingsJson = JSON.stringify(settings); diff --git a/src/index.tsx b/src/index.tsx index 43096a8..82b5e79 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -7,7 +7,7 @@ import './index.css'; const root = createRoot(document.getElementById('root') as HTMLElement); root.render( - - - + + + ); diff --git a/tests/unit/App.test.tsx b/tests/unit/App.test.tsx index 3b31292..0386704 100644 --- a/tests/unit/App.test.tsx +++ b/tests/unit/App.test.tsx @@ -1,8 +1,10 @@ +import type { ReactNode } from 'react'; import { render, screen, act } from '@testing-library/react'; import App from '../../src/App'; jest.mock('react-split-pane', () => { - return function SplitPaneMock({ children }: any) { + return function SplitPaneMock(props: unknown) { + const { children } = props as { children: ReactNode }; return
{children}
; }; }); diff --git a/tests/unit/LayoutContainer.test.tsx b/tests/unit/LayoutContainer.test.tsx index 0746f39..162b04a 100644 --- a/tests/unit/LayoutContainer.test.tsx +++ b/tests/unit/LayoutContainer.test.tsx @@ -1,3 +1,4 @@ +import type { ReactNode } from 'react'; import { render, screen, fireEvent, act } from '@testing-library/react'; import { IntlProvider } from 'react-intl'; import { SettingsProvider } from '../../src/components/SettingsContext'; @@ -6,7 +7,11 @@ import { getMessagesForLocale } from '../../src/localization/localization'; import { saveHomePageSettings } from '../../src/functions/utility'; jest.mock('react-split-pane', () => { - return function SplitPaneMock({ children, onDragFinished }: any) { + return function SplitPaneMock(props: unknown) { + const { children, onDragFinished } = props as { + children: ReactNode; + onDragFinished?: (size: number) => void; + }; return (
{cell.render('Cell')}