diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 542c09d6..00000000 --- a/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -build -dist -.docz -.github -node_modules diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index fc10be15..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true, - "jest/globals": true - }, - "extends": ["plugin:react/recommended", "standard", "eslint:recommended", "prettier", "plugin:prettier/recommended"], - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": 12, - "sourceType": "module" - }, - "plugins": ["react", "react-hooks", "prettier", "jest"], - "rules": { - "no-constant-binary-expression": "error", - "react-hooks/rules-of-hooks": "error", - "react-hooks/exhaustive-deps": "warn", - "semi": [2, "always"], - "max-len": ["error", { "code": 120 }] - }, - "settings": { - "react": { - "version": "17" - } - } -} - diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..8cdca871 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,74 @@ +import react from 'eslint-plugin-react'; +import reactHooks from 'eslint-plugin-react-hooks'; +import { fixupPluginRules } from '@eslint/compat'; +import { FlatCompat } from '@eslint/eslintrc'; +import js from '@eslint/js'; +import jest from 'eslint-plugin-jest'; +import prettier from 'eslint-plugin-prettier'; +import globals from 'globals'; +import neostandard from 'neostandard'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const neostandardConfig = neostandard({ semi: true, noStyle: true }); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [ + { + ignores: ['**/build', '**/dist', '**/.docz', '**/.github', '**/node_modules'], + }, + ...neostandardConfig, + ...compat.extends('plugin:react/recommended', 'prettier', 'plugin:prettier/recommended'), + { + plugins: { + react, + 'react-hooks': fixupPluginRules(reactHooks), + prettier, + jest, + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.es2021, + ...jest.environments.globals.globals, + }, + + ecmaVersion: 12, + sourceType: 'module', + + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + + settings: { + react: { + version: '18', + }, + }, + + rules: { + 'no-constant-binary-expression': 'error', + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + semi: [2, 'always'], + + 'max-len': [ + 'error', + { + code: 120, + }, + ], + }, + }, +]; diff --git a/package.json b/package.json index fe455080..c95e505f 100644 --- a/package.json +++ b/package.json @@ -25,80 +25,87 @@ }, "homepage": "https://github.com/Cosmo-Tech/webapp-component-ui#readme", "devDependencies": { - "@babel/core": "^7.25.2", - "@babel/preset-env": "^7.25.2", - "@babel/preset-react": "^7.24.7", + "@babel/core": "^7.25.8", + "@babel/preset-env": "^7.25.8", + "@babel/preset-react": "^7.25.7", "@cosmotech/azure": "^2.0.1", - "@cosmotech/core": "^1.17.0", - "@mui/icons-material": "^5.16.5", + "@cosmotech/core": "^1.19.1", + "@emotion/react": "^11.13.0", + "@emotion/styled": "^11.13.0", + "@eslint/compat": "^1.2.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.13.0", + "@mui/icons-material": "^6.0.0", "@mui/lab": "^5.0.0-alpha.170", - "@mui/material": "^5.16.5", - "@mui/styles": "^5.16.5", + "@mui/material": "^6.0.0", + "@mui/styles": "^6.0.0", "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-commonjs": "^26.0.1", + "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-image": "^3.0.3", - "@rollup/plugin-node-resolve": "^15.2.3", - "@testing-library/jest-dom": "^6.4.8", - "@testing-library/react": "^12.1.5", + "@rollup/plugin-node-resolve": "^15.3.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.2", + "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "babel-jest": "^29.7.0", - "eslint": "^8.57.0", + "dayjs": "^1.11.13", + "eslint": "^9.13.0", "eslint-config-prettier": "^9.1.0", - "eslint-config-standard": "^17.1.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jest-dom": "^5.4.0", - "eslint-plugin-n": "^16.6.2", + "eslint-plugin-n": "^17.11.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.2.1", - "eslint-plugin-promise": "^6.6.0", - "eslint-plugin-react": "^7.35.0", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-testing-library": "^6.2.2", + "eslint-plugin-promise": "^7.1.0", + "eslint-plugin-react": "^7.37.1", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-testing-library": "^6.4.0", + "globals": "^15.11.0", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", "jest-canvas-mock": "^2.5.2", "jest-environment-jsdom": "^29.7.0", - "postcss": "^8.4.40", + "neostandard": "^0.11.6", + "postcss": "^8.4.47", "prettier": "^3.3.3", "prop-types": "^15.8.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-i18next": "^13.5.0", - "rollup": "^4.19.1", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-i18next": "^15.1.0", + "rollup": "^4.24.0", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-visualizer": "^5.12.0" }, "peerDependencies": { "@cosmotech/azure": "^2.0.1", - "@cosmotech/core": "^1.6.3", - "@mui/icons-material": "^5.11.0", - "@mui/lab": "^5.0.0-alpha.117", - "@mui/material": "^5.11.6", - "@mui/styles": "^5.11.2", + "@cosmotech/core": "^1.19.1", + "@mui/icons-material": "^6.0.0", + "@mui/material": "^6.0.0", + "@mui/styles": "^6.0.0", "prop-types": "^15.7.2", - "react": "^17.0.1", - "react-dom": "^17.0.1", - "react-i18next": "^11.8.13" + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-i18next": "^15.1.0" }, "dependencies": { "@emotion/react": "^11.13.0", "@emotion/styled": "^11.13.0", - "@mui/x-date-pickers": "^5.0.20", + "@mui/x-date-pickers": "^7.0.0", "@nosferatu500/react-sortable-tree": "^3.0.6", - "ag-grid-community": "~32.0.2", - "ag-grid-react": "~32.0.2", + "ag-grid-community": "~32.2.2", + "ag-grid-react": "~32.2.2", "clsx": "^2.1.1", - "cytoscape": "^3.30.1", + "cytoscape": "^3.30.2", "cytoscape-bubblesets": "^3.2.2", "cytoscape-dagre": "^2.5.0", "cytoscape-layers": "^2.4.5", "powerbi-client-react": "^1.4.0", "react-cytoscapejs": "^2.0.0", - "react-lottie-player": "^1.5.6", - "react-number-format": "^5.4.0", + "react-lottie-player": "^2.1.0", + "react-number-format": "^5.4.2", "rfdc": "^1.4.1" }, "resolutions": { diff --git a/rollup.config.mjs b/rollup.config.mjs index 9e25bec4..63b662d1 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -1,11 +1,13 @@ import babel from '@rollup/plugin-babel'; import commonjs from '@rollup/plugin-commonjs'; +import image from '@rollup/plugin-image'; +import resolve from '@rollup/plugin-node-resolve'; +import { readFileSync } from 'fs'; import external from 'rollup-plugin-peer-deps-external'; import postcss from 'rollup-plugin-postcss'; -import resolve from '@rollup/plugin-node-resolve'; -import image from '@rollup/plugin-image'; import { visualizer } from 'rollup-plugin-visualizer'; -import pkg from './package.json' assert { type: 'json' }; + +const pkg = JSON.parse(readFileSync('./package.json')); export default { onwarn: (warning, warn) => { @@ -33,7 +35,6 @@ export default { 'react-virtualized', '@mui/material', '@mui/icons-material', - '@mui/lab', '@mui/styles', 'react-i18next', 'react-router-dom', @@ -46,7 +47,7 @@ export default { babelHelpers: 'bundled', }), resolve(), - commonjs(), + commonjs({ strictRequires: 'auto' }), image(), visualizer(), ], diff --git a/src/buttons/CreateScenarioButton/CreateScenarioButton.js b/src/buttons/CreateScenarioButton/CreateScenarioButton.js index 5246e648..3a738915 100644 --- a/src/buttons/CreateScenarioButton/CreateScenarioButton.js +++ b/src/buttons/CreateScenarioButton/CreateScenarioButton.js @@ -5,6 +5,29 @@ import { Button, IconButton } from '@mui/material'; import { FadingTooltip } from '../../misc'; import CreateScenarioDialog from './components'; +const DEFAULT_LABELS = { + button: { + title: 'Create', + tooltip: 'Create new Scenario', + }, + dialog: { + title: 'Create new Scenario', + scenarioName: 'Scenario Name', + scenarioMaster: 'Master', + scenarioParent: 'Scenario Parent', + datasetPlaceholder: 'Dataset', + dataset: 'Dataset', + scenarioTypePlaceholder: 'Scenario run type', + scenarioType: 'Run type', + cancel: 'Cancel', + create: 'Create', + }, + errors: { + emptyScenarioName: 'Scenario Name should not be empty', + existingScenarioName: 'Scenario Name already exists', + forbiddenCharsInScenarioName: 'Forbidden characters in Scenario Name', + }, +}; export const CreateScenarioButton = ({ currentScenario, datasets, @@ -15,10 +38,11 @@ export const CreateScenarioButton = ({ createScenario, workspaceId, solution, - disabled, - labels, + disabled = false, + labels: tmpLabels, isIconButton, }) => { + const labels = { ...DEFAULT_LABELS, ...tmpLabels }; const [open, setOpen] = useState(false); const openDialog = () => setOpen(true); const closeDialog = () => setOpen(false); @@ -155,30 +179,3 @@ CreateScenarioButton.propTypes = { */ isIconButton: PropTypes.bool, }; - -CreateScenarioButton.defaultProps = { - disabled: false, - labels: { - button: { - title: 'Create', - tooltip: 'Create new Scenario', - }, - dialog: { - title: 'Create new Scenario', - scenarioName: 'Scenario Name', - scenarioMaster: 'Master', - scenarioParent: 'Scenario Parent', - datasetPlaceholder: 'Dataset', - dataset: 'Dataset', - scenarioTypePlaceholder: 'Scenario run type', - scenarioType: 'Run type', - cancel: 'Cancel', - create: 'Create', - }, - errors: { - emptyScenarioName: 'Scenario Name should not be empty', - existingScenarioName: 'Scenario Name already exists', - forbiddenCharsInScenarioName: 'Forbidden characters in Scenario Name', - }, - }, -}; diff --git a/src/buttons/CreateScenarioButton/components/CreateScenarioDialog/CreateScenarioDialog.js b/src/buttons/CreateScenarioButton/components/CreateScenarioDialog/CreateScenarioDialog.js index 2d77e29a..6d170133 100644 --- a/src/buttons/CreateScenarioButton/components/CreateScenarioDialog/CreateScenarioDialog.js +++ b/src/buttons/CreateScenarioButton/components/CreateScenarioDialog/CreateScenarioDialog.js @@ -10,7 +10,7 @@ import { DialogContent, DialogTitle, FormControlLabel, - Grid, + Grid2 as Grid, TextField, Autocomplete, Chip, @@ -197,7 +197,7 @@ const CreateScenarioDialog = ({ {dialogLabels.title} - + - + - + setScenarioTags(values)} /> - + - + - + {isMaster || !currentScenarioSelected ? ( { + const labels = { ...DEFAULT_LABELS, ...tmpLabels }; const [open, setOpen] = useState(false); const openDialog = () => setOpen(true); const closeDialog = () => setOpen(false); @@ -173,16 +181,3 @@ RolesEditionButton.propTypes = { dialog: PropTypes.object.isRequired, }), }; -RolesEditionButton.defaultProps = { - isIconButton: false, - isReadOnly: false, - disabled: false, - preventNoneRoleForAgents: false, - defaultRole: '', - labels: { - button: { - title: 'Share', - tooltip: 'Modify access', - }, - }, -}; diff --git a/src/buttons/RolesEditionButton/components/RolesEditionDialog/RolesEditionDialog.js b/src/buttons/RolesEditionButton/components/RolesEditionDialog/RolesEditionDialog.js index 61ca23b9..d863f268 100644 --- a/src/buttons/RolesEditionButton/components/RolesEditionDialog/RolesEditionDialog.js +++ b/src/buttons/RolesEditionButton/components/RolesEditionDialog/RolesEditionDialog.js @@ -9,7 +9,7 @@ import { Dialog, DialogTitle, DialogContent, - Grid, + Grid2 as Grid, TextField, DialogActions, Button, @@ -32,18 +32,35 @@ const useStyles = makeStyles((theme) => ({ }, })); +const DEFAULT_LABELS = { + title: 'Share ', + readOnlyTitle: 'Permissions for ', + addPeople: 'Add people', + cancel: 'Cancel', + close: 'Close', + share: 'Share', + noAdminError: 'The scenario must have at least one administrator', + userSelected: 'Selected user', + usersAccess: 'Users access', + generalAccess: 'General access', + removeAccess: 'Remove access', + editor: { + helperText: null, + }, +}; + const ADMIN_ROLE = 'admin'; const sortById = (agentA, agentB) => (agentA.id < agentB.id ? -1 : 1); export const RolesEditionDialog = ({ - labels: labelsBeforeDefaultValuesPatch, - isReadOnly, + labels: tmpLabels, + isReadOnly = false, resourceRolesPermissionsMapping, - preventNoneRoleForAgents, + preventNoneRoleForAgents = false, onConfirmChanges, agents, accessControlList, - defaultRole, + defaultRole = '', open, closeDialog, allRoles, @@ -56,7 +73,7 @@ export const RolesEditionDialog = ({ const [newAccessControlList, setNewAccessControlList] = useState([...accessControlList].sort(sortById)); const [newDefaultRole, setNewDefaultRole] = useState(defaultRole || ''); - const labels = { ...DEFAULT_LABELS, ...labelsBeforeDefaultValuesPatch }; + const labels = { ...DEFAULT_LABELS, ...tmpLabels }; useEffect(() => { if (open) { @@ -120,7 +137,7 @@ export const RolesEditionDialog = ({ {!isReadOnly && ( - + )} - + {labels.usersAccess} {newAccessControlList.length > 0 && newAccessControlList.map((agent) => ( @@ -171,12 +188,12 @@ export const RolesEditionDialog = ({ {hasNoAdmin && ( - + {labels.noAdminError} )} - + {labels.generalAccess} { const classes = useStyle(); + const labels = { ...DEFAULT_LABELS, ...tmpLabels }; const [selectedRole, setSelectedRole] = useState(defaultRole); const sortedPermissions = _sortGrantedPermissionsForRole(rolesPermissionsMapping, allPermissions, selectedRole); return ( @@ -63,7 +74,7 @@ export const RolesAddingDialog = ({ )} /> - + {!selectedRole && ( {labels.rolesHelperText} @@ -92,10 +103,10 @@ export const RolesAddingDialog = ({ ))} - + - + {labels.grantedPermissions} {sortedPermissions.granted.map((permission) => ( { const classes = useStyles(); - const { generate, height, width, labels, timeout } = props; - + const { generate, height = '40px', width = '143px', labels: tmpLabels, timeout = 15 } = props; + const labels = { ...DEFAULT_LABELS, ...tmpLabels }; const [status, setStatus] = useState(STATUS.IDLE); const [downloadLink, setDownloadLink] = useState(null); const timeoutRef = useRef(null); @@ -106,13 +109,3 @@ SelfDestructLinkButton.propTypes = { */ timeout: PropTypes.number, // Expressed in seconds }; - -SelfDestructLinkButton.defaultProps = { - height: '40px', - width: '143px', - labels: { - generateLink: 'Generate link', - download: 'Download', - }, - timeout: 15, // Expressed in seconds -}; diff --git a/src/buttons/SignInButton/SignInButton.js b/src/buttons/SignInButton/SignInButton.js index ead0cf3a..6264d897 100644 --- a/src/buttons/SignInButton/SignInButton.js +++ b/src/buttons/SignInButton/SignInButton.js @@ -2,7 +2,7 @@ // Licensed under the MIT license. import React from 'react'; import PropTypes from 'prop-types'; -import { Grid, Typography, Avatar } from '@mui/material'; +import { Grid2 as Grid, Typography, Avatar } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; const useStyles = makeStyles((theme) => ({ @@ -32,15 +32,15 @@ const useStyles = makeStyles((theme) => ({ export const SignInButton = (props) => { const classes = useStyles(); - const { id, label, logo, onClick } = props; + const { id, label = 'Sign in', logo = '../../assets/microsoft_logo.png', onClick } = props; return ( @@ -575,7 +621,7 @@ export const CytoViz = (props) => {
-
{labels_.settings.layout}
+
{labels.settings.layout}