From 44f86f3042615496039624a0ecc7a53c3a96a0f2 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Wed, 24 Jul 2024 23:58:18 +0200 Subject: [PATCH 1/5] go to new version --- package-lock.json | 81 ++++++++++++++++++++++++++++------ package.json | 2 +- src/components/app-top-bar.tsx | 13 +++--- src/components/app.tsx | 4 +- src/redux/reducer.ts | 7 +-- src/utils/rest-api.ts | 4 +- 6 files changed, 81 insertions(+), 30 deletions(-) diff --git a/package-lock.json b/package-lock.json index 26c7c0b..cc3237f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@gridsuite/commons-ui": "0.63.0", "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.15.14", "@mui/lab": "^5.0.0-alpha.169", @@ -36,6 +35,7 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@gridsuite/commons-ui": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.2.tgz", "@types/core-js": "^2.5.8", "@types/eslint-config-prettier": "^6.11.3", "@types/jest": "^27.5.2", @@ -2753,9 +2753,11 @@ } }, "node_modules/@gridsuite/commons-ui": { - "version": "0.63.0", - "resolved": "https://registry.npmjs.org/@gridsuite/commons-ui/-/commons-ui-0.63.0.tgz", - "integrity": "sha512-+hO2HUv2D/rd1UX5BBw7O/FDbpUXrjCm/fVSAeBT/Ml72CROhva458aBPczkjb9sg/lxV8U3L2tRAwhyuuI/iQ==", + "version": "0.63.2", + "resolved": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.2.tgz", + "integrity": "sha512-mQLOg3A4OUCEioijw3wbiquwcDBKj/rPDtSNSDvEF4amfiUYDcl9He3RtElTJYdV3qRGnrObAWj+m1N4AWmHVw==", + "dev": true, + "license": "MPL-2.0", "dependencies": { "@react-querybuilder/dnd": "^7.2.0", "@react-querybuilder/material": "^7.2.0", @@ -2771,6 +2773,7 @@ "react-dnd-html5-backend": "^16.0.1", "react-querybuilder": "^7.2.0", "react-virtualized": "^9.22.5", + "type-fest": "^4.21.0", "uuid": "^9.0.1" }, "engines": { @@ -2796,6 +2799,7 @@ "react-intl": "^6.6.4", "react-papaparse": "^4.1.0", "react-router-dom": "^6.22.3", + "reconnecting-websocket": "^4.4.0", "yup": "^1.4.0" } }, @@ -2803,10 +2807,23 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "dev": true, "engines": { "node": ">=6" } }, + "node_modules/@gridsuite/commons-ui/node_modules/type-fest": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", + "integrity": "sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@hookform/resolvers": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.4.tgz", @@ -4690,22 +4707,26 @@ "node_modules/@react-dnd/asap": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", - "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==", + "dev": true }, "node_modules/@react-dnd/invariant": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", - "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==", + "dev": true }, "node_modules/@react-dnd/shallowequal": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", - "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==", + "dev": true }, "node_modules/@react-querybuilder/dnd": { "version": "7.5.2", "resolved": "https://registry.npmjs.org/@react-querybuilder/dnd/-/dnd-7.5.2.tgz", "integrity": "sha512-7rMeZ6gFQow2jpz0exMQSq/f3MZEL5OuiWW6YOkDuFfJWPR7ijXV6Cz0x7TiFS7jbTD5Axr44u7nFCWx06hZeg==", + "dev": true, "peerDependencies": { "react": ">=18", "react-dnd": ">=14.0.0", @@ -4717,6 +4738,7 @@ "version": "7.5.2", "resolved": "https://registry.npmjs.org/@react-querybuilder/material/-/material-7.5.2.tgz", "integrity": "sha512-wWjwKjaD5LIX9Lta3QE/smd9lYEWzIAR7A93XyHHwv8BtP1EQoZgjKogNCSuQZhfkrTT5U1n9g4uORCUk7Z9ZQ==", + "dev": true, "peerDependencies": { "@emotion/react": "^11", "@emotion/styled": "^11", @@ -5329,6 +5351,7 @@ "version": "5.3.14", "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.14.tgz", "integrity": "sha512-LxJ4iEFcpqc6METwp9f6BV6VVc43m6MfH0VqFosHvrUgfXiFe6ww7R3itkOQ+TCK6Y+Iv/+RnnvtRZnkc5Kc9g==", + "dev": true, "peer": true, "dependencies": { "@types/node": "*" @@ -6124,12 +6147,14 @@ "version": "31.3.2", "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-31.3.2.tgz", "integrity": "sha512-GxqFRD0OcjaVRE1gwLgoP0oERNPH8Lk8wKJ1txulsxysEQ5dZWHhiIoXXSiHjvOCVMkK/F5qzY6HNrn6VeDMTQ==", + "dev": true, "peer": true }, "node_modules/ag-grid-react": { "version": "31.3.2", "resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-31.3.2.tgz", "integrity": "sha512-SFHN05bsXp901rIT00Fa6iQLCtyavoJiKaXEDUtAU5LMu+GTkjs/FPQBQ8754omgdDFr4NsS3Ri6QbqBne3rug==", + "dev": true, "peer": true, "dependencies": { "ag-grid-community": "31.3.2", @@ -6545,6 +6570,7 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/autosuggest-highlight/-/autosuggest-highlight-3.3.4.tgz", "integrity": "sha512-j6RETBD2xYnrVcoV1S5R4t3WxOlWZKyDQjkwnggDPSjF5L4jV98ZltBpvPvbkM1HtoSe5o+bNrTHyjPbieGeYA==", + "dev": true, "dependencies": { "remove-accents": "^0.4.2" } @@ -6911,6 +6937,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, "funding": [ { "type": "github", @@ -7607,7 +7634,8 @@ "node_modules/crypto-js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "dev": true }, "node_modules/crypto-random-string": { "version": "2.0.0", @@ -8310,6 +8338,7 @@ "version": "16.0.1", "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "dev": true, "dependencies": { "@react-dnd/asap": "^5.0.1", "@react-dnd/invariant": "^4.0.1", @@ -8320,6 +8349,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dev": true, "dependencies": { "@babel/runtime": "^7.9.2" } @@ -9647,7 +9677,8 @@ "node_modules/file-saver": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", - "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "dev": true }, "node_modules/filelist": { "version": "1.0.4", @@ -14688,6 +14719,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "dev": true, "engines": { "node": ">=18" } @@ -14836,7 +14868,8 @@ "node_modules/localized-countries": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/localized-countries/-/localized-countries-2.0.0.tgz", - "integrity": "sha512-17CwJ/oetI5cB6KmPa+Cxw/8vunawUouVv5MFxYqsVzryXeR5u/MF32m3SBaHxP4EqYPOePV+3jx7xxYZnAJpQ==" + "integrity": "sha512-17CwJ/oetI5cB6KmPa+Cxw/8vunawUouVv5MFxYqsVzryXeR5u/MF32m3SBaHxP4EqYPOePV+3jx7xxYZnAJpQ==", + "dev": true }, "node_modules/locate-path": { "version": "6.0.0", @@ -14966,7 +14999,8 @@ "node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "dev": true }, "node_modules/merge-descriptors": { "version": "1.0.1", @@ -15343,6 +15377,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/numeric-quantity/-/numeric-quantity-2.0.1.tgz", "integrity": "sha512-+Bt2X6YxM5bg8XIBl76NVeG2eL0Y5VQRoyz6GLYrZXW/TDh7We+tGeX4/WZWhaVGOg5ZjNBEOZt9a86slMhOJA==", + "dev": true, "engines": { "node": ">=16" } @@ -15505,6 +15540,7 @@ "version": "1.11.5", "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.11.5.tgz", "integrity": "sha512-LcKrKC8Av0m/KD/4EFmo9Sg8fSQ+WFJWBrmtWd+tZkNn3WT/sQG3REmPANE9tzzhbjW6VkTNy4xhAXCfPApAOg==", + "dev": true, "dependencies": { "acorn": "^7.4.1", "base64-js": "^1.5.1", @@ -15517,6 +15553,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -15677,6 +15714,7 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==", + "dev": true, "peer": true }, "node_modules/param-case": { @@ -17505,6 +17543,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/react-csv-downloader/-/react-csv-downloader-3.1.0.tgz", "integrity": "sha512-ART4CNMU89Y5OZQp9gR3IUlVt541djWwRfokQY+CYsGQjHNZFJAk6FvgOwLUNG0o/CxeUdexYjnMMFinMv4Xjg==", + "dev": true, "dependencies": { "file-saver": "^2.0.2" }, @@ -17625,6 +17664,7 @@ "version": "16.0.1", "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", + "dev": true, "dependencies": { "@react-dnd/invariant": "^4.0.1", "@react-dnd/shallowequal": "^4.0.1", @@ -17654,6 +17694,7 @@ "version": "16.0.1", "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", + "dev": true, "dependencies": { "dnd-core": "^16.0.1" } @@ -17724,12 +17765,14 @@ "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "dev": true }, "node_modules/react-papaparse": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/react-papaparse/-/react-papaparse-4.4.0.tgz", "integrity": "sha512-xTEwHZYJ+1dh9mQDQjjwJXmWyX20DdZ52u+ddw75V+Xm5qsjXSvWmC7c8K82vRwMjKAOH2S9uFyGpHEyEztkUQ==", + "dev": true, "peer": true, "dependencies": { "@types/papaparse": "^5.3.9", @@ -17744,6 +17787,7 @@ "version": "7.5.0", "resolved": "https://registry.npmjs.org/react-querybuilder/-/react-querybuilder-7.5.0.tgz", "integrity": "sha512-tWrwLf2dPkI1TYluW6Oy/Tif/Z0X8OBoDXkh2C/oloAItPJEmKAcInuIYOlEKDVK6KM6lHJsGNBmApuMWY5c/g==", + "dev": true, "dependencies": { "@reduxjs/toolkit": "^2.2.5", "clsx": "^2.1.1", @@ -17759,6 +17803,7 @@ "version": "2.2.6", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz", "integrity": "sha512-kH0r495c5z1t0g796eDQAkYbEQ3a1OLYN9o8jQQVZyKyw367pfRGS+qZLkHYvFHiUUdafpoSlQ2QYObIApjPWA==", + "dev": true, "dependencies": { "immer": "^10.0.3", "redux": "^5.0.1", @@ -17782,6 +17827,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, "engines": { "node": ">=6" } @@ -17790,6 +17836,7 @@ "version": "10.1.1", "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -17799,6 +17846,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", + "dev": true, "dependencies": { "@types/use-sync-external-store": "^0.0.3", "use-sync-external-store": "^1.0.0" @@ -17821,6 +17869,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "dev": true, "peerDependencies": { "redux": "^5.0.0" } @@ -17828,7 +17877,8 @@ "node_modules/react-querybuilder/node_modules/reselect": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", - "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "dev": true }, "node_modules/react-redux": { "version": "8.1.3", @@ -18027,6 +18077,7 @@ "version": "9.22.5", "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.5.tgz", "integrity": "sha512-YqQMRzlVANBv1L/7r63OHa2b0ZsAaDp1UhVNEdUaXI8A5u6hTpA5NYtUueLH2rFuY/27mTGIBl7ZhqFKzw18YQ==", + "dev": true, "dependencies": { "@babel/runtime": "^7.7.2", "clsx": "^1.0.4", @@ -18290,7 +18341,8 @@ "node_modules/remove-accents": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.4.tgz", - "integrity": "sha512-EpFcOa/ISetVHEXqu+VwI96KZBmq+a8LJnGkaeFw45epGlxIZz5dhEEnNZMsQXgORu3qaMoLX4qJCzOik6ytAg==" + "integrity": "sha512-EpFcOa/ISetVHEXqu+VwI96KZBmq+a8LJnGkaeFw45epGlxIZz5dhEEnNZMsQXgORu3qaMoLX4qJCzOik6ytAg==", + "dev": true }, "node_modules/renderkid": { "version": "3.0.0", @@ -20466,6 +20518,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" diff --git a/package.json b/package.json index 6ccfedb..a11ba2d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@gridsuite/commons-ui": "0.63.0", "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.15.14", "@mui/lab": "^5.0.0-alpha.169", @@ -82,6 +81,7 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@gridsuite/commons-ui": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.2.tgz", "@types/core-js": "^2.5.8", "@types/eslint-config-prettier": "^6.11.3", "@types/jest": "^27.5.2", diff --git a/src/components/app-top-bar.tsx b/src/components/app-top-bar.tsx index 645bbe8..d4458f6 100644 --- a/src/components/app-top-bar.tsx +++ b/src/components/app-top-bar.tsx @@ -12,6 +12,7 @@ import React, { useState, } from 'react'; import { + AppMetadataCommon, LIGHT_THEME, logout, TopBar, @@ -20,11 +21,7 @@ import { import Parameters, { useParameterState } from './parameters'; import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params'; import { useDispatch, useSelector } from 'react-redux'; -import { - fetchAppsAndUrls, - fetchVersion, - MetadataJson, -} from '../utils/rest-api'; +import { fetchAppsAndUrls, fetchVersion } from '../utils/rest-api'; import { getServersInfos } from '../rest/study'; import { useNavigate } from 'react-router-dom'; import { ReactComponent as PowsyblLogo } from '../images/powsybl_logo.svg'; @@ -41,7 +38,7 @@ const AppTopBar: FunctionComponent = (props) => { const dispatch = useDispatch(); - const [appsAndUrls, setAppsAndUrls] = useState([]); + const [appsAndUrls, setAppsAndUrls] = useState([]); const theme = useSelector((state: AppState) => state[PARAM_THEME]); @@ -55,7 +52,7 @@ const AppTopBar: FunctionComponent = (props) => { const hideParameters = useCallback(() => setShowParameters(false), []); useEffect(() => { - if (props.user !== null) { + if (props.user !== undefined) { fetchAppsAndUrls().then((res) => { setAppsAndUrls(res); }); @@ -81,7 +78,7 @@ const AppTopBar: FunctionComponent = (props) => { logout(dispatch, props.userManager.instance) } onLogoClick={() => navigate('/', { replace: true })} - user={props.user ?? undefined} + user={props.user} appsAndUrls={appsAndUrls} globalVersionPromise={() => fetchVersion().then( diff --git a/src/components/app.tsx b/src/components/app.tsx index 299a60a..ae32ea5 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -181,7 +181,7 @@ const App: FunctionComponent = () => { ]); useEffect(() => { - if (user !== null) { + if (user !== undefined) { fetchConfigParameters(COMMON_APP_NAME) .then((params) => updateParams(params)) .catch((error) => @@ -215,7 +215,7 @@ const App: FunctionComponent = () => { <> - {user !== null ? ( + {user !== undefined ? ( { +export function fetchAppsAndUrls(): Promise { console.info(`Fetching apps and urls...`); return fetchEnv() .then((env: EnvJson) => From ba6affb0b7be24bbf07dba8aafef0822126eea0d Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 25 Jul 2024 00:56:45 +0200 Subject: [PATCH 2/5] define types for env vars --- src/react-app-env.d.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index 7b288b8..a3e466c 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -6,3 +6,26 @@ */ /// + +import { UrlString } from '@gridsuite/commons-ui'; + +type EnvDev = { + REACT_APP_USE_AUTHENTICATION: true; + REACT_APP_SRV_STUDY_URI: string; +}; + +type EnvProd = { + REACT_APP_USE_AUTHENTICATION: false; + REACT_APP_API_GATEWAY: string; + REACT_APP_WS_GATEWAY: string; +}; + +type EnvCompile = EnvProd | EnvDev; + +declare global { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + namespace NodeJS { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface ProcessEnv extends EnvCompile {} + } +} From b77ab9d27413bd34b0554beab071abb1a128dc5e Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 25 Jul 2024 00:59:26 +0200 Subject: [PATCH 3/5] migrate to new arch --- .env.development | 2 - README.md | 2 +- src/components/app-top-bar.tsx | 50 +++--- src/components/app-wrapper.tsx | 2 +- src/components/app.tsx | 45 ++--- src/components/parameters.tsx | 5 +- src/react-app-env.d.ts | 6 +- src/redux/actions.ts | 3 +- src/redux/local-storage.ts | 44 ----- src/redux/reducer.ts | 22 +-- src/redux/store.ts | 6 + src/rest/study.ts | 30 ---- src/services/app-local.ts | 19 +++ src/services/index.ts | 70 ++++++++ src/setupProxy.js | 6 +- src/utils/config-params.ts | 23 --- src/utils/error.ts | 26 --- src/utils/language.ts | 27 --- src/utils/rest-api.ts | 290 --------------------------------- 19 files changed, 169 insertions(+), 509 deletions(-) delete mode 100644 src/redux/local-storage.ts delete mode 100644 src/rest/study.ts create mode 100644 src/services/app-local.ts create mode 100644 src/services/index.ts delete mode 100644 src/utils/error.ts delete mode 100644 src/utils/language.ts delete mode 100644 src/utils/rest-api.ts diff --git a/.env.development b/.env.development index 1451cfd..2f1d4e1 100644 --- a/.env.development +++ b/.env.development @@ -1,3 +1 @@ REACT_APP_USE_AUTHENTICATION=false - -REACT_APP_SRV_STUDY_URI=study-server diff --git a/README.md b/README.md index 11e6ab7..8b497be 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This template setup the authentication mechanism and provides a configured empty To customize this repository for an app, search and replace the string `XXX` with the name of the app. For example, GridXXX -> GridFoo, gridXXX-app -> gridfoo-app. -Create a new view in study-server and replace `yyy` with the new token in rest api `src/rest/study.ts`. +Create a new view in study-server and replace `yyy` with the new token in rest api `src/services/index.ts`. ## Typescript config diff --git a/src/components/app-top-bar.tsx b/src/components/app-top-bar.tsx index d4458f6..b75b87e 100644 --- a/src/components/app-top-bar.tsx +++ b/src/components/app-top-bar.tsx @@ -11,23 +11,24 @@ import React, { useEffect, useState, } from 'react'; -import { - AppMetadataCommon, - LIGHT_THEME, - logout, - TopBar, - UserManagerState, -} from '@gridsuite/commons-ui'; import Parameters, { useParameterState } from './parameters'; -import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params'; +import { APP_NAME } from '../utils/config-params'; import { useDispatch, useSelector } from 'react-redux'; -import { fetchAppsAndUrls, fetchVersion } from '../utils/rest-api'; -import { getServersInfos } from '../rest/study'; +import { appsMetadataSrv, studySrv } from '../services'; import { useNavigate } from 'react-router-dom'; import { ReactComponent as PowsyblLogo } from '../images/powsybl_logo.svg'; import AppPackage from '../../package.json'; import { AppState } from '../redux/reducer'; import { AppDispatch } from '../redux/store'; +import { + AppMetadataCommon, + LIGHT_THEME, + logout, + PARAM_LANGUAGE, + PARAM_THEME, + TopBar, + UserManagerState, +} from '@gridsuite/commons-ui'; export type AppTopBarProps = { user?: AppState['user']; @@ -50,14 +51,29 @@ const AppTopBar: FunctionComponent = (props) => { const [showParameters, setShowParameters] = useState(false); const displayParameters = useCallback(() => setShowParameters(true), []); const hideParameters = useCallback(() => setShowParameters(false), []); + const onLogoutClick = useCallback( + () => logout(dispatch, props.userManager.instance), + [dispatch, props.userManager.instance] + ); useEffect(() => { if (props.user !== undefined) { - fetchAppsAndUrls().then((res) => { + appsMetadataSrv.fetchAppsMetadata().then((res) => { setAppsAndUrls(res); }); } }, [props.user]); + const globalVersionFetcher = useCallback( + () => + appsMetadataSrv + .fetchVersion() + .then((res) => res?.deployVersion ?? 'unknown'), + [] + ); + const additionalModulesFetcher = useCallback( + () => studySrv.getServersInfos('yyy'), + [] + ); return ( <> @@ -74,18 +90,12 @@ const AppTopBar: FunctionComponent = (props) => { appVersion={AppPackage.version} appLicense={AppPackage.license} onParametersClick={displayParameters} - onLogoutClick={() => - logout(dispatch, props.userManager.instance) - } + onLogoutClick={onLogoutClick} onLogoClick={() => navigate('/', { replace: true })} user={props.user} appsAndUrls={appsAndUrls} - globalVersionPromise={() => - fetchVersion().then( - (res) => res?.deployVersion ?? 'unknown' - ) - } - additionalModulesPromise={getServersInfos} + globalVersionPromise={globalVersionFetcher} + additionalModulesPromise={additionalModulesFetcher} onThemeClick={handleChangeTheme} theme={themeLocal} onLanguageClick={handleChangeLanguage} diff --git a/src/components/app-wrapper.tsx b/src/components/app-wrapper.tsx index 0803483..da0a8c4 100644 --- a/src/components/app-wrapper.tsx +++ b/src/components/app-wrapper.tsx @@ -22,6 +22,7 @@ import { LIGHT_THEME, login_en, login_fr, + PARAM_THEME, SnackbarProvider, top_bar_en, top_bar_fr, @@ -34,7 +35,6 @@ import messages_fr from '../translations/fr.json'; import messages_plugins_en from '../plugins/translations/en.json'; import messages_plugins_fr from '../plugins/translations/fr.json'; import { store } from '../redux/store'; -import { PARAM_THEME } from '../utils/config-params'; import { IntlConfig } from 'react-intl/src/types'; import { AppState } from '../redux/reducer'; diff --git a/src/components/app.tsx b/src/components/app.tsx index ae32ea5..f8a2e99 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -25,9 +25,15 @@ import { Box, Typography } from '@mui/material'; import { AuthenticationRouter, CardErrorBoundary, + COMMON_APP_NAME, + ConfigParameters, + getComputedLanguage, + getErrorMessage, getPreLoginPath, initializeAuthenticationDev, initializeAuthenticationProd, + PARAM_LANGUAGE, + PARAM_THEME, useSnackMessage, } from '@gridsuite/commons-ui'; import { @@ -37,23 +43,14 @@ import { } from '../redux/actions'; import { AppState } from '../redux/reducer'; import { - ConfigParameters, - connectNotificationsWsUpdateConfig, - fetchConfigParameter, - fetchConfigParameters, - fetchIdpSettings, - fetchValidateUser, -} from '../utils/rest-api'; -import { - APP_NAME, - COMMON_APP_NAME, - PARAM_LANGUAGE, - PARAM_THEME, -} from '../utils/config-params'; -import { getComputedLanguage } from '../utils/language'; + appLocalSrv, + configNotificationSrv, + configSrv, + userAdminSrv, +} from '../services'; +import { APP_NAME } from '../utils/config-params'; import AppTopBar, { AppTopBarProps } from './app-top-bar'; import ReconnectingWebSocket from 'reconnecting-websocket'; -import { getErrorMessage } from '../utils/error'; import { AppDispatch } from '../redux/store'; const App: FunctionComponent = () => { @@ -107,11 +104,15 @@ const App: FunctionComponent = () => { const connectNotificationsUpdateConfig = useCallback((): ReconnectingWebSocket => { - const ws = connectNotificationsWsUpdateConfig(); + const ws = + configNotificationSrv.connectNotificationsWsUpdateConfig( + APP_NAME + ); ws.onmessage = function (event) { let eventData = JSON.parse(event.data); if (eventData.headers?.parameterName) { - fetchConfigParameter(eventData.headers.parameterName) + configSrv + .fetchConfigParameter(eventData.headers.parameterName) .then((param) => updateParams([param])) .catch((error) => snackError({ @@ -152,8 +153,8 @@ const App: FunctionComponent = () => { ? initializeAuthenticationProd( dispatch, initialMatchSilentRenewCallbackUrl != null, - fetchIdpSettings, - fetchValidateUser, + appLocalSrv.fetchIdpSettings, + userAdminSrv.fetchValidateUser, initialMatchSigninCallbackUrl != null ) : initializeAuthenticationDev( @@ -182,7 +183,8 @@ const App: FunctionComponent = () => { useEffect(() => { if (user !== undefined) { - fetchConfigParameters(COMMON_APP_NAME) + configSrv + .fetchConfigParameters(COMMON_APP_NAME) .then((params) => updateParams(params)) .catch((error) => snackError({ @@ -191,7 +193,8 @@ const App: FunctionComponent = () => { }) ); - fetchConfigParameters(APP_NAME) + configSrv + .fetchConfigParameters(APP_NAME) .then((params) => updateParams(params)) .catch((error) => snackError({ diff --git a/src/components/parameters.tsx b/src/components/parameters.tsx index b46df2b..34dacad 100644 --- a/src/components/parameters.tsx +++ b/src/components/parameters.tsx @@ -29,7 +29,7 @@ import { TypographyTypeMap, } from '@mui/material'; import { CSSObject, Theme } from '@emotion/react'; -import { updateConfigParameter } from '../utils/rest-api'; +import { configSrv } from '../services'; import { useSnackMessage } from '@gridsuite/commons-ui'; import { AppState, AppStateKey } from '../redux/reducer'; @@ -62,7 +62,8 @@ export function useParameterState( const handleChangeParamLocalState = useCallback( (value: AppState[K]) => { setParamLocalState(value); - updateConfigParameter(paramName, value as string) //TODO how to check/cast? + configSrv + .updateConfigParameter(paramName, value as string) //TODO how to check/cast? .catch((error) => { setParamLocalState(paramGlobalState); snackError({ diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index a3e466c..b8ba40c 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2024, RTE (http://www.rte-france.com) +/* + * Copyright © 2024, RTE (http://www.rte-france.com) * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -7,8 +7,6 @@ /// -import { UrlString } from '@gridsuite/commons-ui'; - type EnvDev = { REACT_APP_USE_AUTHENTICATION: true; REACT_APP_SRV_STUDY_URI: string; diff --git a/src/redux/actions.ts b/src/redux/actions.ts index 65aa3cf..22c2ec6 100644 --- a/src/redux/actions.ts +++ b/src/redux/actions.ts @@ -5,8 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { GsTheme } from '@gridsuite/commons-ui'; -import { PARAM_LANGUAGE } from '../utils/config-params'; +import { GsTheme, PARAM_LANGUAGE } from '@gridsuite/commons-ui'; import { Action } from 'redux'; import { AppState } from './reducer'; diff --git a/src/redux/local-storage.ts b/src/redux/local-storage.ts deleted file mode 100644 index f38ddab..0000000 --- a/src/redux/local-storage.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2020, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -import { - DARK_THEME, - GsLang, - GsLangUser, - GsTheme, - LANG_SYSTEM, -} from '@gridsuite/commons-ui'; -import { getComputedLanguage } from '../utils/language'; -import { APP_NAME } from '../utils/config-params'; - -const LOCAL_STORAGE_THEME_KEY = (APP_NAME + '_THEME').toUpperCase(); -const LOCAL_STORAGE_LANGUAGE_KEY = (APP_NAME + '_LANGUAGE').toUpperCase(); - -export function getLocalStorageTheme() { - return ( - (localStorage.getItem(LOCAL_STORAGE_THEME_KEY) as GsTheme) || DARK_THEME - ); -} - -export function saveLocalStorageTheme(theme: GsTheme): void { - localStorage.setItem(LOCAL_STORAGE_THEME_KEY, theme); -} - -export function getLocalStorageLanguage() { - return ( - (localStorage.getItem(LOCAL_STORAGE_LANGUAGE_KEY) as GsLang) || - LANG_SYSTEM - ); -} - -export function saveLocalStorageLanguage(language: GsLang): void { - localStorage.setItem(LOCAL_STORAGE_LANGUAGE_KEY, language); -} - -export function getLocalStorageComputedLanguage(): GsLangUser { - return getComputedLanguage(getLocalStorageLanguage()); -} diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index cda395c..ffd6be8 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -6,12 +6,6 @@ */ import { createReducer, Draft } from '@reduxjs/toolkit'; -import { - getLocalStorageComputedLanguage, - getLocalStorageLanguage, - getLocalStorageTheme, - saveLocalStorageTheme, -} from './local-storage'; import { ComputedLanguageAction, LanguageAction, @@ -23,12 +17,18 @@ import { AuthenticationActions, AuthenticationRouterErrorAction, AuthenticationRouterErrorState, + getLocalStorageComputedLanguage, + getLocalStorageLanguage, + getLocalStorageTheme, GsLang, GsLangUser, GsTheme, LOGOUT_ERROR, LogoutErrorAction, + PARAM_LANGUAGE, + PARAM_THEME, RESET_AUTHENTICATION_ROUTER_ERROR, + saveLocalStorageTheme, SHOW_AUTH_INFO_LOGIN, ShowAuthenticationRouterLoginAction, SIGNIN_CALLBACK_ERROR, @@ -40,9 +40,9 @@ import { UserAction, UserValidationErrorAction, } from '@gridsuite/commons-ui'; -import { PARAM_LANGUAGE, PARAM_THEME } from '../utils/config-params'; import { ReducerWithInitialState } from '@reduxjs/toolkit/dist/createReducer'; import { User } from 'oidc-client'; +import { APP_NAME } from '../utils/config-params'; export type AppState = { user: User | undefined; @@ -63,9 +63,9 @@ const initialState: AppState = { showAuthenticationRouterLogin: false, // params - [PARAM_THEME]: getLocalStorageTheme(), - [PARAM_LANGUAGE]: getLocalStorageLanguage(), - computedLanguage: getLocalStorageComputedLanguage(), + [PARAM_THEME]: getLocalStorageTheme(APP_NAME), + [PARAM_LANGUAGE]: getLocalStorageLanguage(APP_NAME), + computedLanguage: getLocalStorageComputedLanguage(APP_NAME), }; export type Actions = @@ -83,7 +83,7 @@ export const reducer: ReducerWithInitialState = createReducer( SELECT_THEME, (state: Draft, action: ThemeAction) => { state.theme = action.theme; - saveLocalStorageTheme(state.theme); + saveLocalStorageTheme(APP_NAME, state.theme); } ); diff --git a/src/redux/store.ts b/src/redux/store.ts index 89ab5af..a529a3c 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -6,6 +6,12 @@ */ import { createStore, Store } from 'redux'; import { Actions, AppState, reducer } from './reducer'; +import { initCommonServices } from '@gridsuite/commons-ui'; +import { APP_NAME } from '../utils/config-params'; export const store: Store = createStore(reducer); export type AppDispatch = typeof store.dispatch; + +export function getUser() { + return store.getState().user; +} diff --git a/src/rest/study.ts b/src/rest/study.ts deleted file mode 100644 index ae23221..0000000 --- a/src/rest/study.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2023, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -import { GridSuiteModule } from '@gridsuite/commons-ui'; -import { backendFetchJson } from '../utils/rest-api'; -import { getErrorMessage } from '../utils/error'; - -const API_URL = - '/api/' + - (process.env.REACT_APP_USE_AUTHENTICATION === 'true' - ? `${process.env.REACT_APP_API_GATEWAY}/study/v1` - : `${process.env.REACT_APP_SRV_STUDY_URI}/v1`); - -export function getServersInfos() { - return backendFetchJson(`${API_URL}/servers/about?view=yyy`, { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }).catch((error) => { - console.error( - `Error while fetching the servers infos : ${getErrorMessage(error)}` - ); - throw error; - }) as Promise; -} diff --git a/src/services/app-local.ts b/src/services/app-local.ts new file mode 100644 index 0000000..cce6482 --- /dev/null +++ b/src/services/app-local.ts @@ -0,0 +1,19 @@ +/* + * Copyright © 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +import { AppLocalComSvc, Env } from '@gridsuite/commons-ui'; + +export type EnvJson = Env & typeof import('../../public/env.json'); + +export default class AppLocalSvc extends AppLocalComSvc { + public constructor() { + super(); + } + + public async fetchEnv(): Promise { + return (await super.fetchEnv()) as EnvJson; + } +} diff --git a/src/services/index.ts b/src/services/index.ts new file mode 100644 index 0000000..8934647 --- /dev/null +++ b/src/services/index.ts @@ -0,0 +1,70 @@ +/* + * Copyright © 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import { + AppsMetadataComSvc, + ConfigComSvc, + ConfigNotificationComSvc, + DirectoryComSvc, + ExploreComSvc, + setCommonServices, + StudyComSvc, + UrlString, + UserAdminComSvc, +} from '@gridsuite/commons-ui'; +import AppLocalSvc from './app-local'; +import { getUser } from '../redux/store'; +import { APP_NAME } from '../utils/config-params'; + +export type { EnvJson } from './app-local'; + +// If you want to use user-admin-server in dev mode you must avoid passing through gateway +// and use the user-admin-server directly. SetupProxy should allow this. +// const PREFIX_USER_ADMIN_SERVER_QUERIES = +// process.env.REACT_APP_API_PREFIX + +// (process.env.REACT_APP_USE_AUTHENTICATION === 'true' +// ? `${process.env.REACT_APP_API_GATEWAY}/user-admin` +// : process.env.REACT_APP_USER_ADMIN_URI); + +export const appLocalSrv = new AppLocalSvc(), + appsMetadataSrv = new AppsMetadataComSvc(appLocalSrv), + configSrv = new ConfigComSvc( + APP_NAME, + getUser, + process.env.REACT_APP_API_GATEWAY as UrlString + ), + configNotificationSrv = new ConfigNotificationComSvc( + getUser, + process.env.REACT_APP_WS_GATEWAY as UrlString + ), + directorySrv = new DirectoryComSvc( + getUser, + process.env.REACT_APP_API_GATEWAY as UrlString + ), + exploreSrv = new ExploreComSvc( + getUser, + process.env.REACT_APP_API_GATEWAY as UrlString + ), + studySrv = new StudyComSvc( + getUser, + process.env.REACT_APP_API_GATEWAY as UrlString + ), + userAdminSrv = new UserAdminComSvc( + getUser, + process.env.REACT_APP_API_GATEWAY as UrlString + ); + +setCommonServices( + appLocalSrv, + appsMetadataSrv, + configSrv, + configNotificationSrv, + directorySrv, + exploreSrv, + studySrv, + userAdminSrv +); diff --git a/src/setupProxy.js b/src/setupProxy.js index 4b47f9b..7b1b15b 100644 --- a/src/setupProxy.js +++ b/src/setupProxy.js @@ -18,9 +18,5 @@ module.exports = function (app) { ws: true, }) ); - app.use( - createProxyMiddleware('http://localhost:5001/api/study-server', { - pathRewrite: { '^/api/study-server/': '/' }, - }) - ); + // TODO: redirect localhost:9000/api/gateway/study directly to http://localhost:5001/ }; diff --git a/src/utils/config-params.ts b/src/utils/config-params.ts index 30807f3..bf6eaf7 100644 --- a/src/utils/config-params.ts +++ b/src/utils/config-params.ts @@ -5,27 +5,4 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -export const COMMON_APP_NAME = 'common'; export const APP_NAME = 'XXX'; - -export const PARAM_THEME = 'theme'; -export const PARAM_LANGUAGE = 'language'; - -const COMMON_CONFIG_PARAMS_NAMES = new Set([PARAM_THEME, PARAM_LANGUAGE]); - -export type AppConfigParameter = - | typeof PARAM_THEME - | typeof PARAM_LANGUAGE - | string; - -export type AppConfigType = typeof COMMON_APP_NAME | typeof APP_NAME; - -/** - * Permit knowing if a parameter is common/shared between webapps or is specific to this application. - * @param paramName the parameter name/key - */ -export function getAppName(paramName: AppConfigParameter): AppConfigType { - return COMMON_CONFIG_PARAMS_NAMES.has(paramName) - ? COMMON_APP_NAME - : APP_NAME; -} diff --git a/src/utils/error.ts b/src/utils/error.ts deleted file mode 100644 index c8959d9..0000000 --- a/src/utils/error.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2024, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -export function getErrorMessage(error: unknown): string | null { - if (error instanceof Error) { - return error.message; - } else if (error instanceof Object && 'message' in error) { - if ( - typeof error.message === 'string' || - typeof error.message === 'number' || - typeof error.message === 'boolean' - ) { - return `${error.message}`; - } else { - return JSON.stringify(error.message ?? undefined) ?? null; - } - } else if (typeof error === 'string') { - return error; - } else { - return JSON.stringify(error ?? undefined) ?? null; - } -} diff --git a/src/utils/language.ts b/src/utils/language.ts deleted file mode 100644 index aa7003a..0000000 --- a/src/utils/language.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2021, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -import { - GsLang, - GsLangUser, - LANG_ENGLISH, - LANG_FRENCH, - LANG_SYSTEM, -} from '@gridsuite/commons-ui'; - -const supportedLanguages = [LANG_FRENCH, LANG_ENGLISH]; - -export function getSystemLanguage(): GsLangUser { - const systemLanguage = navigator.language.split(/[-_]/)[0]; - return supportedLanguages.includes(systemLanguage) - ? (systemLanguage as GsLangUser) - : LANG_ENGLISH; -} - -export function getComputedLanguage(language: GsLang) { - return language === LANG_SYSTEM ? getSystemLanguage() : language; -} diff --git a/src/utils/rest-api.ts b/src/utils/rest-api.ts deleted file mode 100644 index df1728f..0000000 --- a/src/utils/rest-api.ts +++ /dev/null @@ -1,290 +0,0 @@ -/** - * Copyright (c) 2020, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -import { AppMetadata, Env, GsLangUser, GsTheme } from '@gridsuite/commons-ui'; -import { User } from 'oidc-client'; -import { - APP_NAME, - getAppName, - PARAM_LANGUAGE, - PARAM_THEME, -} from './config-params'; -import { store } from '../redux/store'; -import ReconnectingWebSocket, { Event } from 'reconnecting-websocket'; -import { AppState } from '../redux/reducer'; -import { getErrorMessage } from './error'; - -export interface ErrorWithStatus extends Error { - status?: number; -} - -// TODO remove when exported in commons-ui (src/utils/AuthService.ts) -type IdpSettings = { - authority: string; - client_id: string; - redirect_uri: string; - post_logout_redirect_uri: string; - silent_redirect_uri: string; - scope: string; - maxExpiresIn?: number; -}; - -export type Url = string | URL; -export type InitRequest = Partial; -export type Token = string; - -const PREFIX_USER_ADMIN_SERVER_QUERIES = `${process.env.REACT_APP_API_GATEWAY}/user-admin`; - -// If you want to use user-admin-server in dev mode you must avoid passing through gateway -// and use the user-admin-server directly. SetupProxy should allow this. -// const PREFIX_USER_ADMIN_SERVER_QUERIES = -// process.env.REACT_APP_API_PREFIX + -// (process.env.REACT_APP_USE_AUTHENTICATION === 'true' -// ? `${process.env.REACT_APP_API_GATEWAY}/user-admin` -// : process.env.REACT_APP_USER_ADMIN_URI); - -const PREFIX_CONFIG_QUERIES = `${process.env.REACT_APP_API_GATEWAY}/config`; -const PREFIX_CONFIG_NOTIFICATION_WS = `${process.env.REACT_APP_WS_GATEWAY}/config-notification`; - -function getToken(): Token | null { - const state: AppState = store.getState(); - return state.user?.id_token ?? null; -} - -export function connectNotificationsWsUpdateConfig(): ReconnectingWebSocket { - const webSocketBaseUrl = document.baseURI - .replace(/^http:\/\//, 'ws://') - .replace(/^https:\/\//, 'wss://'); - const webSocketUrl = `${webSocketBaseUrl}${PREFIX_CONFIG_NOTIFICATION_WS}/notify?appName=${APP_NAME}`; - - const reconnectingWebSocket = new ReconnectingWebSocket( - () => `${webSocketUrl}&access_token=${getToken()}` - ); - reconnectingWebSocket.onopen = function (event: Event) { - console.info( - `Connected Websocket update config ui ${webSocketUrl} ...` - ); - }; - return reconnectingWebSocket; -} - -function parseError(text: string) { - try { - return JSON.parse(text); - } catch (err) { - return null; - } -} - -function handleError(response: Response): Promise { - return response.text().then((text: string) => { - const errorName = 'HttpResponseError : '; - let error: ErrorWithStatus; - const errorJson = parseError(text); - if (errorJson?.status && errorJson?.error && errorJson?.message) { - error = new Error( - `${errorName}${errorJson.status} ${errorJson.error}, message : ${errorJson.message}` - ) as ErrorWithStatus; - error.status = errorJson.status; - } else { - error = new Error( - `${errorName}${response.status} ${response.statusText}` - ) as ErrorWithStatus; - error.status = response.status; - } - throw error; - }); -} - -function prepareRequest(init?: InitRequest, token?: Token): RequestInit { - if (!(typeof init == 'undefined' || typeof init == 'object')) { - throw new TypeError( - `Argument 2 of backendFetch is not an object ${typeof init}` - ); - } - const initCopy: RequestInit = { ...init }; - initCopy.headers = new Headers(initCopy.headers || {}); - const tokenCopy = token || getToken(); - initCopy.headers.append('Authorization', `Bearer ${tokenCopy}`); - return initCopy; -} - -function safeFetch(url: Url, initCopy?: InitRequest) { - return fetch(url, initCopy).then((response: Response) => - response.ok ? response : handleError(response) - ); -} - -export function backendFetch( - url: Url, - init?: InitRequest, - token?: Token -): Promise { - return safeFetch(url, prepareRequest(init, token)); -} - -export function backendFetchText( - url: Url, - init?: InitRequest, - token?: Token -): Promise { - return backendFetch(url, init, token).then((safeResponse: Response) => - safeResponse.text() - ); -} - -export function backendFetchJson( - url: Url, - init?: InitRequest, - token?: Token -): Promise { - return backendFetch(url, init, token).then((safeResponse: Response) => - safeResponse.json() - ); -} - -export function fetchValidateUser(user: User): Promise { - const sub = user?.profile?.sub; - if (!sub) { - return Promise.reject( - new Error( - `Error : Fetching access for missing user.profile.sub : ${user}` - ) - ); - } - - console.info(`Fetching access for user...`); - const CheckAccessUrl = `${PREFIX_USER_ADMIN_SERVER_QUERIES}/v1/users/${sub}`; - console.debug(CheckAccessUrl); - - return backendFetch(CheckAccessUrl, { method: 'head' }, user?.id_token) - .then((response: Response) => { - //if the response is ok, the responseCode will be either 200 or 204 otherwise it's a Http error and it will be caught - return response.status === 200; - }) - .catch((error) => { - if (error.status === 403) { - return false; - } else { - throw error; - } - }); -} - -export type EnvJson = Env & typeof import('../../public/env.json'); - -function fetchEnv(): Promise { - return fetch('env.json').then((res: Response) => res.json()); -} - -export function fetchIdpSettings(): Promise { - return fetch('idpSettings.json').then((res) => res.json()); -} - -export type VersionJson = { - deployVersion?: string; -}; - -export function fetchVersion(): Promise { - console.info(`Fetching global metadata...`); - return fetchEnv() - .then((env: EnvJson) => - fetch(`${env.appsMetadataServerUrl}/version.json`) - ) - .then((response: Response) => response.json()) - .catch((error) => { - console.error( - `Error while fetching the version : ${getErrorMessage(error)}` - ); - throw error; - }); -} - -export type MetadataCommon = { - name: string; - url: Url; - appColor: string; - hiddenInAppsMenu: boolean; -}; - -export type MetadataStudy = MetadataCommon & { - readonly name: 'Study'; - resources?: { - types: string[]; - path: string; - }[]; - predefinedEquipmentProperties?: { - substation?: { - region?: string[]; - tso?: string[]; - totallyFree?: unknown[]; - Demo?: string[]; - }; - load?: { - codeOI?: string[]; - }; - }; - defaultParametersValues?: { - fluxConvention?: string; - enableDeveloperMode?: string; //maybe 'true'|'false' type? - mapManualRefresh?: string; //maybe 'true'|'false' type? - }; -}; - -// https://github.com/gridsuite/deployment/blob/main/docker-compose/docker-compose.base.yml -// https://github.com/gridsuite/deployment/blob/main/k8s/resources/common/config/apps-metadata.json -export type MetadataJson = MetadataCommon | MetadataStudy; - -export function fetchAppsAndUrls(): Promise { - console.info(`Fetching apps and urls...`); - return fetchEnv() - .then((env: EnvJson) => - fetch(`${env.appsMetadataServerUrl}/apps-metadata.json`) - ) - .then((response: Response) => response.json()); -} - -// https://github.com/gridsuite/config-server/blob/main/src/main/java/org/gridsuite/config/server/dto/ParameterInfos.java -export type ConfigParameter = - | { - readonly name: typeof PARAM_LANGUAGE; - value: GsLangUser; - } - | { - readonly name: typeof PARAM_THEME; - value: GsTheme; - }; -export type ConfigParameters = ConfigParameter[]; - -export function fetchConfigParameters( - appName: string = APP_NAME -): Promise { - console.info(`Fetching UI configuration params for app : ${appName}`); - const fetchParams = `${PREFIX_CONFIG_QUERIES}/v1/applications/${appName}/parameters`; - return backendFetchJson(fetchParams) as Promise; -} - -export function fetchConfigParameter(name: string): Promise { - const appName = getAppName(name); - console.info(`Fetching UI config parameter '${name}' for app '${appName}'`); - const fetchParams = `${PREFIX_CONFIG_QUERIES}/v1/applications/${appName}/parameters/${name}`; - return backendFetchJson(fetchParams) as Promise; -} - -export function updateConfigParameter( - name: string, - value: Parameters[0] -): Promise { - const appName = getAppName(name); - console.info( - `Updating config parameter '${name}=${value}' for app '${appName}'` - ); - const updateParams = `${PREFIX_CONFIG_QUERIES}/v1/applications/${appName}/parameters/${name}?value=${encodeURIComponent( - value - )}`; - return backendFetch(updateParams, { method: 'put' }).then(); -} From 8920c88725dcbc089f502a8777bc7de98b81c424 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 9 Aug 2024 08:32:31 +0200 Subject: [PATCH 4/5] pick 120 --- .prettierrc.json | 1 + README.md | 2 +- license-checker-config.json | 2 +- src/__mocks__/svgrMock.js | 4 +- src/components/app-top-bar.tsx | 25 ++---- src/components/app-wrapper.tsx | 16 +--- src/components/app.test.tsx | 6 +- src/components/app.tsx | 146 ++++++++----------------------- src/components/parameters.tsx | 31 ++----- src/index.css | 10 +-- src/module-mui.d.ts | 9 +- src/plugins/README.md | 7 +- src/plugins/translations/en.json | 3 +- src/plugins/translations/fr.json | 3 +- src/redux/actions.ts | 8 +- src/redux/reducer.ts | 130 +++++++++------------------ src/services/index.ts | 31 ++----- 17 files changed, 119 insertions(+), 315 deletions(-) diff --git a/.prettierrc.json b/.prettierrc.json index 27512b6..fda48c3 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,6 @@ { "trailingComma": "es5", "tabWidth": 4, + "printWidth": 120, "singleQuote": true } diff --git a/README.md b/README.md index 8b497be..c06a7ed 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This template setup the authentication mechanism and provides a configured empty To customize this repository for an app, search and replace the string `XXX` with the name of the app. For example, GridXXX -> GridFoo, gridXXX-app -> gridfoo-app. -Create a new view in study-server and replace `yyy` with the new token in rest api `src/services/index.ts`. +Create a new view in study-server and replace `yyy` with the new token in rest api `src/services/index.ts`. ## Typescript config diff --git a/license-checker-config.json b/license-checker-config.json index 94edbfb..8f50cca 100644 --- a/license-checker-config.json +++ b/license-checker-config.json @@ -1,5 +1,5 @@ { - "onlyAllow" : [ + "onlyAllow": [ "MPL-2.0", "MIT", "BSD-3-Clause", diff --git a/src/__mocks__/svgrMock.js b/src/__mocks__/svgrMock.js index 2e01553..2eecbf2 100644 --- a/src/__mocks__/svgrMock.js +++ b/src/__mocks__/svgrMock.js @@ -7,9 +7,7 @@ import React from 'react'; -const SvgrMock = React.forwardRef((props, ref) => ( - -)); +const SvgrMock = React.forwardRef((props, ref) => ); export const ReactComponent = SvgrMock; export default SvgrMock; diff --git a/src/components/app-top-bar.tsx b/src/components/app-top-bar.tsx index b75b87e..ec5be73 100644 --- a/src/components/app-top-bar.tsx +++ b/src/components/app-top-bar.tsx @@ -5,12 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { - FunctionComponent, - useCallback, - useEffect, - useState, -} from 'react'; +import React, { FunctionComponent, useCallback, useEffect, useState } from 'react'; import Parameters, { useParameterState } from './parameters'; import { APP_NAME } from '../utils/config-params'; import { useDispatch, useSelector } from 'react-redux'; @@ -45,8 +40,7 @@ const AppTopBar: FunctionComponent = (props) => { const [themeLocal, handleChangeTheme] = useParameterState(PARAM_THEME); - const [languageLocal, handleChangeLanguage] = - useParameterState(PARAM_LANGUAGE); + const [languageLocal, handleChangeLanguage] = useParameterState(PARAM_LANGUAGE); const [showParameters, setShowParameters] = useState(false); const displayParameters = useCallback(() => setShowParameters(true), []); @@ -64,16 +58,10 @@ const AppTopBar: FunctionComponent = (props) => { } }, [props.user]); const globalVersionFetcher = useCallback( - () => - appsMetadataSrv - .fetchVersion() - .then((res) => res?.deployVersion ?? 'unknown'), - [] - ); - const additionalModulesFetcher = useCallback( - () => studySrv.getServersInfos('yyy'), + () => appsMetadataSrv.fetchVersion().then((res) => res?.deployVersion ?? 'unknown'), [] ); + const additionalModulesFetcher = useCallback(() => studySrv.getServersInfos('yyy'), []); return ( <> @@ -101,10 +89,7 @@ const AppTopBar: FunctionComponent = (props) => { onLanguageClick={handleChangeLanguage} language={languageLocal} /> - + ); }; diff --git a/src/components/app-wrapper.tsx b/src/components/app-wrapper.tsx index da0a8c4..4f06d8a 100644 --- a/src/components/app-wrapper.tsx +++ b/src/components/app-wrapper.tsx @@ -8,12 +8,7 @@ import App from './app'; import React, { FunctionComponent } from 'react'; import { CssBaseline } from '@mui/material'; -import { - createTheme, - StyledEngineProvider, - Theme, - ThemeProvider, -} from '@mui/material/styles'; +import { createTheme, StyledEngineProvider, Theme, ThemeProvider } from '@mui/material/styles'; import { card_error_boundary_en, card_error_boundary_fr, @@ -118,15 +113,10 @@ const messages: Record = { const basename = new URL(document.querySelector('base')?.href ?? '').pathname; const AppWrapperWithRedux: FunctionComponent = () => { - const computedLanguage = useSelector( - (state: AppState) => state.computedLanguage - ); + const computedLanguage = useSelector((state: AppState) => state.computedLanguage); const theme = useSelector((state: AppState) => state[PARAM_THEME]); return ( - + diff --git a/src/components/app.test.tsx b/src/components/app.test.tsx index 4bb28d7..4799e8d 100644 --- a/src/components/app.test.tsx +++ b/src/components/app.test.tsx @@ -15,11 +15,7 @@ import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import App from './app'; import { store } from '../redux/store'; -import { - createTheme, - StyledEngineProvider, - ThemeProvider, -} from '@mui/material/styles'; +import { createTheme, StyledEngineProvider, ThemeProvider } from '@mui/material/styles'; import { SnackbarProvider } from '@gridsuite/commons-ui'; import { CssBaseline } from '@mui/material'; diff --git a/src/components/app.tsx b/src/components/app.tsx index f8a2e99..ab2ecd9 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -5,21 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { - FunctionComponent, - useCallback, - useEffect, - useState, -} from 'react'; +import React, { FunctionComponent, useCallback, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { - Navigate, - Route, - Routes, - useLocation, - useMatch, - useNavigate, -} from 'react-router-dom'; +import { Navigate, Route, Routes, useLocation, useMatch, useNavigate } from 'react-router-dom'; import { FormattedMessage } from 'react-intl'; import { Box, Typography } from '@mui/material'; import { @@ -36,18 +24,9 @@ import { PARAM_THEME, useSnackMessage, } from '@gridsuite/commons-ui'; -import { - selectComputedLanguage, - selectLanguage, - selectTheme, -} from '../redux/actions'; +import { selectComputedLanguage, selectLanguage, selectTheme } from '../redux/actions'; import { AppState } from '../redux/reducer'; -import { - appLocalSrv, - configNotificationSrv, - configSrv, - userAdminSrv, -} from '../services'; +import { appLocalSrv, configNotificationSrv, configSrv, userAdminSrv } from '../services'; import { APP_NAME } from '../utils/config-params'; import AppTopBar, { AppTopBarProps } from './app-top-bar'; import ReconnectingWebSocket from 'reconnecting-websocket'; @@ -58,19 +37,11 @@ const App: FunctionComponent = () => { const user = useSelector((state: AppState) => state.user); - const signInCallbackError = useSelector( - (state: AppState) => state.signInCallbackError - ); - const authenticationRouterError = useSelector( - (state: AppState) => state.authenticationRouterError - ); - const showAuthenticationRouterLogin = useSelector( - (state: AppState) => state.showAuthenticationRouterLogin - ); + const signInCallbackError = useSelector((state: AppState) => state.signInCallbackError); + const authenticationRouterError = useSelector((state: AppState) => state.authenticationRouterError); + const showAuthenticationRouterLogin = useSelector((state: AppState) => state.showAuthenticationRouterLogin); - const [userManager, setUserManager] = useState< - AppTopBarProps['userManager'] - >({ instance: null, error: null }); + const [userManager, setUserManager] = useState({ instance: null, error: null }); const navigate = useNavigate(); @@ -88,11 +59,7 @@ const App: FunctionComponent = () => { break; case PARAM_LANGUAGE: dispatch(selectLanguage(param.value)); - dispatch( - selectComputedLanguage( - getComputedLanguage(param.value) - ) - ); + dispatch(selectComputedLanguage(getComputedLanguage(param.value))); break; default: break; @@ -102,31 +69,27 @@ const App: FunctionComponent = () => { [dispatch] ); - const connectNotificationsUpdateConfig = - useCallback((): ReconnectingWebSocket => { - const ws = - configNotificationSrv.connectNotificationsWsUpdateConfig( - APP_NAME - ); - ws.onmessage = function (event) { - let eventData = JSON.parse(event.data); - if (eventData.headers?.parameterName) { - configSrv - .fetchConfigParameter(eventData.headers.parameterName) - .then((param) => updateParams([param])) - .catch((error) => - snackError({ - messageTxt: error.message, - headerId: 'paramsRetrievingError', - }) - ); - } - }; - ws.onerror = function (event) { - console.error('Unexpected Notification WebSocket error', event); - }; - return ws; - }, [updateParams, snackError]); + const connectNotificationsUpdateConfig = useCallback((): ReconnectingWebSocket => { + const ws = configNotificationSrv.connectNotificationsWsUpdateConfig(APP_NAME); + ws.onmessage = function (event) { + let eventData = JSON.parse(event.data); + if (eventData.headers?.parameterName) { + configSrv + .fetchConfigParameter(eventData.headers.parameterName) + .then((param) => updateParams([param])) + .catch((error) => + snackError({ + messageTxt: error.message, + headerId: 'paramsRetrievingError', + }) + ); + } + }; + ws.onerror = function (event) { + console.error('Unexpected Notification WebSocket error', event); + }; + return ws; + }, [updateParams, snackError]); // Can't use lazy initializer because useMatch is a hook const [initialMatchSilentRenewCallbackUrl] = useState( @@ -145,9 +108,7 @@ const App: FunctionComponent = () => { // need subfunction when async as suggested by rule react-hooks/exhaustive-deps (async function initializeAuthentication() { try { - console.debug( - `auth dev mode: ${process.env.REACT_APP_USE_AUTHENTICATION}` - ); + console.debug(`auth dev mode: ${process.env.REACT_APP_USE_AUTHENTICATION}`); const initAuth = process.env.REACT_APP_USE_AUTHENTICATION === 'true' ? initializeAuthenticationProd( @@ -175,11 +136,7 @@ const App: FunctionComponent = () => { } })(); // Note: dispatch and initialMatchSilentRenewCallbackUrl won't change - }, [ - initialMatchSigninCallbackUrl, - initialMatchSilentRenewCallbackUrl, - dispatch, - ]); + }, [initialMatchSigninCallbackUrl, initialMatchSilentRenewCallbackUrl, dispatch]); useEffect(() => { if (user !== undefined) { @@ -206,13 +163,7 @@ const App: FunctionComponent = () => { const ws = connectNotificationsUpdateConfig(); return () => ws.close(); } - }, [ - user, - dispatch, - updateParams, - snackError, - connectNotificationsUpdateConfig, - ]); + }, [user, dispatch, updateParams, snackError, connectNotificationsUpdateConfig]); return ( <> @@ -224,33 +175,16 @@ const App: FunctionComponent = () => { path="/" element={ - + Connected } /> - - } - /> + } /> - Error: logout failed; you are still logged - in. - - } + element={

Error: logout failed; you are still logged in.

} /> { userManager={userManager} signInCallbackError={signInCallbackError} authenticationRouterError={authenticationRouterError} - showAuthenticationRouterLogin={ - showAuthenticationRouterLogin - } + showAuthenticationRouterLogin={showAuthenticationRouterLogin} dispatch={dispatch} navigate={navigate} location={location} @@ -281,7 +213,5 @@ const App: FunctionComponent = () => { export default App; function validateUserDev(): Promise { - return new Promise((resolve) => - window.setTimeout(() => resolve(true), 500) - ); + return new Promise((resolve) => window.setTimeout(() => resolve(true), 500)); } diff --git a/src/components/parameters.tsx b/src/components/parameters.tsx index 34dacad..efafc06 100644 --- a/src/components/parameters.tsx +++ b/src/components/parameters.tsx @@ -5,14 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { - FunctionComponent, - PropsWithChildren, - ReactElement, - useCallback, - useEffect, - useState, -} from 'react'; +import React, { FunctionComponent, PropsWithChildren, ReactElement, useCallback, useEffect, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { useSelector } from 'react-redux'; import { @@ -48,9 +41,7 @@ const styles = { } as CSSObject, }; -export function useParameterState( - paramName: K -): [AppState[K], (value: AppState[K]) => void] { +export function useParameterState(paramName: K): [AppState[K], (value: AppState[K]) => void] { const { snackError } = useSnackMessage(); const paramGlobalState = useSelector((state: AppState) => state[paramName]); const [paramLocalState, setParamLocalState] = useState(paramGlobalState); @@ -82,15 +73,8 @@ function GUITab(): ReactElement { return ; } -type TabPanelProps = PropsWithChildren< - TypographyTypeMap<{ index: number; value: number }, 'div'>['props'] ->; -function TabPanel({ - children, - value, - index, - ...typoProps -}: TabPanelProps): ReactElement { +type TabPanelProps = PropsWithChildren['props']>; +function TabPanel({ children, value, index, ...typoProps }: TabPanelProps): ReactElement { return ( = (props) => { - diff --git a/src/index.css b/src/index.css index 407ba15..8e8c67b 100644 --- a/src/index.css +++ b/src/index.css @@ -1,22 +1,20 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', - 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', - 'Helvetica Neue', sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', + 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } /* In order for oidc-client-js silent renew to work it inserts an iframe in the DOM directly under body tag, it is supposed to be invisible thus its height and width are set to 0 by default. Except iframes have a border value set to 2 which can cause a slight offset to the UI. This rule prevent the iframe to cause an unwanted offset. It can be removed if oidc-client-js is no longer the authentification library in use in this project. */ - + body > iframe[width='0'][height='0'] { border: 0; } diff --git a/src/module-mui.d.ts b/src/module-mui.d.ts index 27c4207..f746709 100644 --- a/src/module-mui.d.ts +++ b/src/module-mui.d.ts @@ -7,10 +7,7 @@ // https://mui.com/material-ui/customization/theming/#typescript import { CSSObject } from '@mui/styled-engine'; -import { - Theme as MuiTheme, - ThemeOptions as MuiThemeOptions, -} from '@mui/material/styles/createTheme'; +import { Theme as MuiTheme, ThemeOptions as MuiThemeOptions } from '@mui/material/styles/createTheme'; declare module '@mui/material/styles/createTheme' { export * from '@mui/material/styles/createTheme'; @@ -25,7 +22,5 @@ declare module '@mui/material/styles/createTheme' { }; export interface Theme extends MuiTheme, Required {} // allow configuration using `createTheme` - export interface ThemeOptions - extends MuiThemeOptions, - Partial {} + export interface ThemeOptions extends MuiThemeOptions, Partial {} } diff --git a/src/plugins/README.md b/src/plugins/README.md index fd2ae97..3650fb0 100644 --- a/src/plugins/README.md +++ b/src/plugins/README.md @@ -1,4 +1,3 @@ - # How to add plugins Add a plugin component or object in the corresponding group represented as folders. @@ -12,6 +11,7 @@ export default MyNewPlugin; ``` Edit `index.ts` to export your new plugin in the corresponding group + ```ts import MyNewPlugin from './myPluginGroup/myNewPlugin'; ... @@ -48,5 +48,6 @@ const MyPluggableComponent: FunctionComponent = () => { # How to overwrite translations Add your private translations to the following files to complete or overwrite existing translations -* `src/plugins/translations/en.json` -* `src/plugins/translations/fr.json` + +- `src/plugins/translations/en.json` +- `src/plugins/translations/fr.json` diff --git a/src/plugins/translations/en.json b/src/plugins/translations/en.json index 2c63c08..0967ef4 100644 --- a/src/plugins/translations/en.json +++ b/src/plugins/translations/en.json @@ -1,2 +1 @@ -{ -} +{} diff --git a/src/plugins/translations/fr.json b/src/plugins/translations/fr.json index 2c63c08..0967ef4 100644 --- a/src/plugins/translations/fr.json +++ b/src/plugins/translations/fr.json @@ -1,2 +1 @@ -{ -} +{} diff --git a/src/redux/actions.ts b/src/redux/actions.ts index 22c2ec6..9aba0f9 100644 --- a/src/redux/actions.ts +++ b/src/redux/actions.ts @@ -28,15 +28,11 @@ export function selectLanguage(language: AppState['language']): LanguageAction { } export const SELECT_COMPUTED_LANGUAGE = 'SELECT_COMPUTED_LANGUAGE'; -export type ComputedLanguageAction = Readonly< - Action -> & { +export type ComputedLanguageAction = Readonly> & { computedLanguage: AppState['computedLanguage']; }; -export function selectComputedLanguage( - computedLanguage: AppState['computedLanguage'] -): ComputedLanguageAction { +export function selectComputedLanguage(computedLanguage: AppState['computedLanguage']): ComputedLanguageAction { return { type: SELECT_COMPUTED_LANGUAGE, computedLanguage: computedLanguage, diff --git a/src/redux/reducer.ts b/src/redux/reducer.ts index ffd6be8..0319e27 100644 --- a/src/redux/reducer.ts +++ b/src/redux/reducer.ts @@ -6,13 +6,7 @@ */ import { createReducer, Draft } from '@reduxjs/toolkit'; -import { - ComputedLanguageAction, - LanguageAction, - SELECT_COMPUTED_LANGUAGE, - SELECT_THEME, - ThemeAction, -} from './actions'; +import { ComputedLanguageAction, LanguageAction, SELECT_COMPUTED_LANGUAGE, SELECT_THEME, ThemeAction } from './actions'; import { AuthenticationActions, AuthenticationRouterErrorAction, @@ -68,86 +62,48 @@ const initialState: AppState = { computedLanguage: getLocalStorageComputedLanguage(APP_NAME), }; -export type Actions = - | AuthenticationActions - | ThemeAction - | LanguageAction - | ComputedLanguageAction; +export type Actions = AuthenticationActions | ThemeAction | LanguageAction | ComputedLanguageAction; export type AppStateKey = keyof AppState; -export const reducer: ReducerWithInitialState = createReducer( - initialState, - (builder) => { - builder.addCase( - SELECT_THEME, - (state: Draft, action: ThemeAction) => { - state.theme = action.theme; - saveLocalStorageTheme(APP_NAME, state.theme); - } - ); - - builder.addCase(USER, (state: Draft, action: UserAction) => { - state.user = action.user; - }); - - builder.addCase( - SIGNIN_CALLBACK_ERROR, - (state: Draft, action: SignInCallbackErrorAction) => { - state.signInCallbackError = action.signInCallbackError; - } - ); - - builder.addCase( - UNAUTHORIZED_USER_INFO, - (state: Draft, action: UnauthorizedUserAction) => { - state.authenticationRouterError = - action.authenticationRouterError; - } - ); - - builder.addCase( - LOGOUT_ERROR, - (state: Draft, action: LogoutErrorAction) => { - state.authenticationRouterError = - action.authenticationRouterError; - } - ); - - builder.addCase( - USER_VALIDATION_ERROR, - (state: Draft, action: UserValidationErrorAction) => { - state.authenticationRouterError = - action.authenticationRouterError; - } - ); - - builder.addCase( - RESET_AUTHENTICATION_ROUTER_ERROR, - ( - state: Draft, - action: AuthenticationRouterErrorAction - ) => { - state.authenticationRouterError = null; - } - ); - - builder.addCase( - SHOW_AUTH_INFO_LOGIN, - ( - state: Draft, - action: ShowAuthenticationRouterLoginAction - ) => { - state.showAuthenticationRouterLogin = - action.showAuthenticationRouterLogin; - } - ); - - builder.addCase( - SELECT_COMPUTED_LANGUAGE, - (state: Draft, action: ComputedLanguageAction) => { - state.computedLanguage = action.computedLanguage; - } - ); - } -); +export const reducer: ReducerWithInitialState = createReducer(initialState, (builder) => { + builder.addCase(SELECT_THEME, (state: Draft, action: ThemeAction) => { + state.theme = action.theme; + saveLocalStorageTheme(APP_NAME, state.theme); + }); + + builder.addCase(USER, (state: Draft, action: UserAction) => { + state.user = action.user; + }); + + builder.addCase(SIGNIN_CALLBACK_ERROR, (state: Draft, action: SignInCallbackErrorAction) => { + state.signInCallbackError = action.signInCallbackError; + }); + + builder.addCase(UNAUTHORIZED_USER_INFO, (state: Draft, action: UnauthorizedUserAction) => { + state.authenticationRouterError = action.authenticationRouterError; + }); + + builder.addCase(LOGOUT_ERROR, (state: Draft, action: LogoutErrorAction) => { + state.authenticationRouterError = action.authenticationRouterError; + }); + + builder.addCase(USER_VALIDATION_ERROR, (state: Draft, action: UserValidationErrorAction) => { + state.authenticationRouterError = action.authenticationRouterError; + }); + + builder.addCase( + RESET_AUTHENTICATION_ROUTER_ERROR, + (state: Draft, action: AuthenticationRouterErrorAction) => { + state.authenticationRouterError = null; + } + ); + + builder.addCase(SHOW_AUTH_INFO_LOGIN, (state: Draft, action: ShowAuthenticationRouterLoginAction) => { + state.showAuthenticationRouterLogin = action.showAuthenticationRouterLogin; + }); + + builder.addCase(SELECT_COMPUTED_LANGUAGE, (state: Draft, action: ComputedLanguageAction) => { + state.computedLanguage = action.computedLanguage; + }); +}); diff --git a/src/services/index.ts b/src/services/index.ts index 8934647..71620bb 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -32,31 +32,12 @@ export type { EnvJson } from './app-local'; export const appLocalSrv = new AppLocalSvc(), appsMetadataSrv = new AppsMetadataComSvc(appLocalSrv), - configSrv = new ConfigComSvc( - APP_NAME, - getUser, - process.env.REACT_APP_API_GATEWAY as UrlString - ), - configNotificationSrv = new ConfigNotificationComSvc( - getUser, - process.env.REACT_APP_WS_GATEWAY as UrlString - ), - directorySrv = new DirectoryComSvc( - getUser, - process.env.REACT_APP_API_GATEWAY as UrlString - ), - exploreSrv = new ExploreComSvc( - getUser, - process.env.REACT_APP_API_GATEWAY as UrlString - ), - studySrv = new StudyComSvc( - getUser, - process.env.REACT_APP_API_GATEWAY as UrlString - ), - userAdminSrv = new UserAdminComSvc( - getUser, - process.env.REACT_APP_API_GATEWAY as UrlString - ); + configSrv = new ConfigComSvc(APP_NAME, getUser, process.env.REACT_APP_API_GATEWAY as UrlString), + configNotificationSrv = new ConfigNotificationComSvc(getUser, process.env.REACT_APP_WS_GATEWAY as UrlString), + directorySrv = new DirectoryComSvc(getUser, process.env.REACT_APP_API_GATEWAY as UrlString), + exploreSrv = new ExploreComSvc(getUser, process.env.REACT_APP_API_GATEWAY as UrlString), + studySrv = new StudyComSvc(getUser, process.env.REACT_APP_API_GATEWAY as UrlString), + userAdminSrv = new UserAdminComSvc(getUser, process.env.REACT_APP_API_GATEWAY as UrlString); setCommonServices( appLocalSrv, From b42d0dc27945c18afed100152f77c064e33fdaaa Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Mon, 12 Aug 2024 12:43:36 +0200 Subject: [PATCH 5/5] update commons-ui --- package-lock.json | 8 ++++---- package.json | 2 +- src/services/app-local.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index cc3237f..ec43880 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@gridsuite/commons-ui": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.2.tgz", + "@gridsuite/commons-ui": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.4.tgz", "@types/core-js": "^2.5.8", "@types/eslint-config-prettier": "^6.11.3", "@types/jest": "^27.5.2", @@ -2753,9 +2753,9 @@ } }, "node_modules/@gridsuite/commons-ui": { - "version": "0.63.2", - "resolved": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.2.tgz", - "integrity": "sha512-mQLOg3A4OUCEioijw3wbiquwcDBKj/rPDtSNSDvEF4amfiUYDcl9He3RtElTJYdV3qRGnrObAWj+m1N4AWmHVw==", + "version": "0.63.4", + "resolved": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.4.tgz", + "integrity": "sha512-3vvFWa40RY81G57P5H8zUUbAhUwcd1ayB1NWWZnHRvizq+0woRcw9qiy+bTdnt0mA7qznq9a5+IMcQU2bOPQPw==", "dev": true, "license": "MPL-2.0", "dependencies": { diff --git a/package.json b/package.json index a11ba2d..4f8a634 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@gridsuite/commons-ui": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.2.tgz", + "@gridsuite/commons-ui": "file:../_frontend/commons-ui/gridsuite-commons-ui-0.63.4.tgz", "@types/core-js": "^2.5.8", "@types/eslint-config-prettier": "^6.11.3", "@types/jest": "^27.5.2", diff --git a/src/services/app-local.ts b/src/services/app-local.ts index cce6482..564acb0 100644 --- a/src/services/app-local.ts +++ b/src/services/app-local.ts @@ -13,7 +13,7 @@ export default class AppLocalSvc extends AppLocalComSvc { super(); } - public async fetchEnv(): Promise { + public async fetchEnv() { return (await super.fetchEnv()) as EnvJson; } }