From 0cd13b77e4b7996b3994a462c64a9fb20e58ad22 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Thu, 4 May 2023 09:22:33 +0300 Subject: [PATCH 01/82] Upgrade to Node v18 --- .github/workflows/audit.yml | 2 +- .github/workflows/bf-applicant-frontend-tests.yml | 4 ++-- .github/workflows/bf-handler-frontend-tests.yml | 4 ++-- .github/workflows/bf-review.yml | 2 +- .github/workflows/bf-shared-frontend-tests.yml | 2 +- .github/workflows/ks-empl-frontend-tests.yml | 4 ++-- .github/workflows/ks-handler-frontend-tests.yml | 4 ++-- .github/workflows/ks-review.yml | 2 +- .github/workflows/ks-shared-frontend-tests.yml | 2 +- .github/workflows/ks-youth-frontend-tests.yml | 4 ++-- .github/workflows/shared-frontend-tests.yml | 2 +- .github/workflows/te-admn-frontend-tests.yml | 4 ++-- .github/workflows/te-review.yml | 2 +- .github/workflows/te-shared-frontend-tests.yml | 2 +- .github/workflows/te-yout-frontend-tests.yml | 4 ++-- .github/workflows/yarn-audit-scheduled.yml | 2 +- README.md | 2 +- frontend/README.md | 4 ++-- frontend/benefit/README.md | 6 +++--- frontend/kesaseteli/README.md | 4 ++-- frontend/package.json | 4 ++-- package.json | 2 +- 22 files changed, 34 insertions(+), 34 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index c8eb3d452c..7a9b75d3d3 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/bf-applicant-frontend-tests.yml b/.github/workflows/bf-applicant-frontend-tests.yml index 251c268d96..c4d28edb66 100644 --- a/.github/workflows/bf-applicant-frontend-tests.yml +++ b/.github/workflows/bf-applicant-frontend-tests.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" @@ -52,7 +52,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/bf-handler-frontend-tests.yml b/.github/workflows/bf-handler-frontend-tests.yml index 0c50506891..c8e1103c96 100644 --- a/.github/workflows/bf-handler-frontend-tests.yml +++ b/.github/workflows/bf-handler-frontend-tests.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" @@ -52,7 +52,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/bf-review.yml b/.github/workflows/bf-review.yml index 8ef45cf3a7..bcb6647e5e 100644 --- a/.github/workflows/bf-review.yml +++ b/.github/workflows/bf-review.yml @@ -238,7 +238,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/bf-shared-frontend-tests.yml b/.github/workflows/bf-shared-frontend-tests.yml index 03f5dfa07d..6cfa4d0f96 100644 --- a/.github/workflows/bf-shared-frontend-tests.yml +++ b/.github/workflows/bf-shared-frontend-tests.yml @@ -24,7 +24,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/ks-empl-frontend-tests.yml b/.github/workflows/ks-empl-frontend-tests.yml index dfb9bc36fb..d3dc1ecb88 100644 --- a/.github/workflows/ks-empl-frontend-tests.yml +++ b/.github/workflows/ks-empl-frontend-tests.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" @@ -63,7 +63,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/ks-handler-frontend-tests.yml b/.github/workflows/ks-handler-frontend-tests.yml index d15e7da6a3..f91a288813 100644 --- a/.github/workflows/ks-handler-frontend-tests.yml +++ b/.github/workflows/ks-handler-frontend-tests.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" @@ -63,7 +63,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/ks-review.yml b/.github/workflows/ks-review.yml index 49151e01d6..a4588457b2 100644 --- a/.github/workflows/ks-review.yml +++ b/.github/workflows/ks-review.yml @@ -256,7 +256,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/ks-shared-frontend-tests.yml b/.github/workflows/ks-shared-frontend-tests.yml index 272e4af157..39341ccd38 100644 --- a/.github/workflows/ks-shared-frontend-tests.yml +++ b/.github/workflows/ks-shared-frontend-tests.yml @@ -24,7 +24,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/ks-youth-frontend-tests.yml b/.github/workflows/ks-youth-frontend-tests.yml index 1bc22fb856..d6da1681db 100644 --- a/.github/workflows/ks-youth-frontend-tests.yml +++ b/.github/workflows/ks-youth-frontend-tests.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" @@ -63,7 +63,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/shared-frontend-tests.yml b/.github/workflows/shared-frontend-tests.yml index 1b6faeeaf0..45317f81bc 100644 --- a/.github/workflows/shared-frontend-tests.yml +++ b/.github/workflows/shared-frontend-tests.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/te-admn-frontend-tests.yml b/.github/workflows/te-admn-frontend-tests.yml index 227d992fcf..ecee92a43c 100644 --- a/.github/workflows/te-admn-frontend-tests.yml +++ b/.github/workflows/te-admn-frontend-tests.yml @@ -24,7 +24,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" @@ -62,7 +62,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/te-review.yml b/.github/workflows/te-review.yml index a1fee5245a..da23cec1e2 100644 --- a/.github/workflows/te-review.yml +++ b/.github/workflows/te-review.yml @@ -247,7 +247,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/te-shared-frontend-tests.yml b/.github/workflows/te-shared-frontend-tests.yml index 1a38d7038e..6700d9c690 100644 --- a/.github/workflows/te-shared-frontend-tests.yml +++ b/.github/workflows/te-shared-frontend-tests.yml @@ -24,7 +24,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/te-yout-frontend-tests.yml b/.github/workflows/te-yout-frontend-tests.yml index 65592e4390..2bee662baa 100644 --- a/.github/workflows/te-yout-frontend-tests.yml +++ b/.github/workflows/te-yout-frontend-tests.yml @@ -24,7 +24,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" @@ -62,7 +62,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/.github/workflows/yarn-audit-scheduled.yml b/.github/workflows/yarn-audit-scheduled.yml index 0c567a606c..ad180fb4b5 100644 --- a/.github/workflows/yarn-audit-scheduled.yml +++ b/.github/workflows/yarn-audit-scheduled.yml @@ -20,7 +20,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3 with: - node-version: '16' + node-version: "18" - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn config get cacheFolder)" diff --git a/README.md b/README.md index 069b3659cf..d0c542523d 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This monorepo contains code for four different employment services: ## Requirements * Docker@^19.03.0 (or higher) -* NodeJS@^16.19.0 +* NodeJS@^18.16.0 * Yarn@^1.22 --- diff --git a/frontend/README.md b/frontend/README.md index 4449b17cdd..995cf0c4dc 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -9,14 +9,14 @@ Project is automatically deployed to testing environment when pushing to develop ## Requirements -- Node 16.x (match with dockerfile: helsinkitest/node:16-slim) +- Node 18.x (match with dockerfile: helsinkitest/node:16-slim) - Yarn - Git - Docker ### install node with nvm - nvm install 16 --lts + nvm install 18 --lts ## Available Scripts diff --git a/frontend/benefit/README.md b/frontend/benefit/README.md index 1195083cea..8c5e20efe5 100644 --- a/frontend/benefit/README.md +++ b/frontend/benefit/README.md @@ -9,7 +9,7 @@ Project is automatically deployed to testing environment when pushing to develop ## Requirements -- Node 16.x +- Node 18.x - Lerna - Yarn - Git @@ -18,8 +18,8 @@ Project is automatically deployed to testing environment when pushing to develop ### Install NodeJS # Use node manager (n or nvm, for example) - n 16 - nvm install 16 --lts + n 18 + nvm install 18 --lts # Alternative methods https://nodejs.org/dist/ https://nodejs.org/en/download/package-manager diff --git a/frontend/kesaseteli/README.md b/frontend/kesaseteli/README.md index 9b0c8aaa8c..4819339fa1 100644 --- a/frontend/kesaseteli/README.md +++ b/frontend/kesaseteli/README.md @@ -19,7 +19,7 @@ Project is automatically deployed to testing environment when pushing to develop ## Requirements -- Node 16.x +- Node 18.x - Lerna - Yarn - Git @@ -27,7 +27,7 @@ Project is automatically deployed to testing environment when pushing to develop ### install node with nvm - nvm install 16 --lts + nvm install 18 --lts ## Available Scripts diff --git a/frontend/package.json b/frontend/package.json index b347873500..762a5ff76f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,7 @@ "shared" ], "engines" : { - "node" : ">=16.19.0 <17.0.0" + "node" : ">=18.16.0 <19.0.0" }, "scripts": { "audit": "npx lerna-audit --level=high --groups=dependencies", @@ -82,7 +82,7 @@ "@types/jest": "^27.4.0", "@types/jest-axe": "^3.5.3", "@types/leaflet": "^1.7.9", - "@types/node": "^17.0.43", + "@types/node": "^18.16.0", "@types/pretty": "^2.0.1", "@types/react-input-mask": "2.0.5", "@types/react-leaflet": "^2.8.2", diff --git a/package.json b/package.json index 484b0a4420..5ee113596b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "husky": "^8.0.3" }, "engines" : { - "node" : ">=16.19.0 <17.0.0" + "node" : ">=18.16.0 <17.0.0" }, "scripts": { "prepare": "husky install", From 3290d9de9ca6609c7f34c0b5dbdc9e2f14403e9d Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Thu, 4 May 2023 09:25:16 +0300 Subject: [PATCH 02/82] Bump docker images to Node v18 --- frontend/Dockerfile | 4 ++-- frontend/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/Dockerfile b/frontend/Dockerfile index e3efeefc75..aab2783340 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,5 +1,5 @@ # ======================================= -FROM helsinkitest/node:16-slim as appbase +FROM helsinkitest/node:18-slim as appbase # ======================================= # Install ca-certificates so that Sentry can upload source maps @@ -99,7 +99,7 @@ RUN rm -rf node_modules RUN yarn cache clean # ========================================== -FROM helsinkitest/node:16-slim AS production +FROM helsinkitest/node:18-slim AS production # ========================================== ARG PORT diff --git a/frontend/README.md b/frontend/README.md index 995cf0c4dc..bdb33d3ef5 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -9,7 +9,7 @@ Project is automatically deployed to testing environment when pushing to develop ## Requirements -- Node 18.x (match with dockerfile: helsinkitest/node:16-slim) +- Node 18.x (match with dockerfile: helsinkitest/node:18-slim) - Yarn - Git - Docker From e8c3e597c50538f964173334a8c0be5d3292d7d0 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Thu, 4 May 2023 09:27:05 +0300 Subject: [PATCH 03/82] Update yarn.lock --- frontend/yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 4fde9cd69e..791e21d04f 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -3336,10 +3336,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.47.tgz#ca9237d51f2a2557419688511dab1c8daf475188" integrity sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg== -"@types/node@^17.0.43": - version "17.0.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.43.tgz#7f16898cdd791c9d64069000ad448b47b3ca8353" - integrity sha512-jnUpgw8fL9kP2iszfIDyBQtw5Mf4/XSqy0Loc1J9pI14ejL83XcCEvSf50Gs/4ET0I9VCCDoOfufQysj0S66xA== +"@types/node@^18.16.0": + version "18.16.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.3.tgz#6bda7819aae6ea0b386ebc5b24bdf602f1b42b01" + integrity sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q== "@types/normalize-package-data@^2.4.0": version "2.4.1" From d5b19cee4358e43ec9e3ba60eee56f58e48b3ba8 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Thu, 4 May 2023 09:27:51 +0300 Subject: [PATCH 04/82] Fix 'node smaller than 17' issue --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ee113596b..45b1917ac5 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "husky": "^8.0.3" }, "engines" : { - "node" : ">=18.16.0 <17.0.0" + "node" : ">=18.16.0 <19.0.0" }, "scripts": { "prepare": "husky install", From 489d31dd109116c6b73ce3dc035979bbfb2e06c6 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Fri, 19 May 2023 15:03:19 +0300 Subject: [PATCH 05/82] Fix builds by using webpack with --openssl-legacy-provider --- frontend/Dockerfile | 2 +- frontend/package.json | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/Dockerfile b/frontend/Dockerfile index aab2783340..beb351fee0 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -92,7 +92,7 @@ COPY --chown=appuser:appuser . . # Build application WORKDIR /app/$PROJECT/$FOLDER/ -RUN yarn build +RUN NODE_OPTIONS=--openssl-legacy-provider yarn build # Clean all dependencies (this should avoid caching + missing /pages directory problem) RUN rm -rf node_modules diff --git a/frontend/package.json b/frontend/package.json index 762a5ff76f..67bfa1c2b6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,11 +16,11 @@ "scripts": { "audit": "npx lerna-audit --level=high --groups=dependencies", "build": "npx lerna run build", - "ks-empl:build": "npx lerna run --scope @frontend/employer --stream build", - "ks-hdlr:build": "npx lerna run --scope @frontend/ks-handler --stream build", - "ks-youth:build": "npx lerna run --scope @frontend/youth --stream build", - "bf-appl:build": "npx lerna run --scope @frontend/applicant --stream build", - "bf-hdlr:build": "npx lerna run --scope @frontend/bf-handler --stream build", + "ks-empl:build": "cross-env NODE_OPTIONS=--openssl-legacy-provider npx lerna run --scope @frontend/employer --stream build", + "ks-hdlr:build": "cross-env NODE_OPTIONS=--openssl-legacy-provider npx lerna run --scope @frontend/ks-handler --stream build", + "ks-youth:build": "cross-env NODE_OPTIONS=--openssl-legacy-provider npx lerna run --scope @frontend/youth --stream build", + "bf-appl:build": "cross-env NODE_OPTIONS=--openssl-legacy-provider npx lerna run --scope @frontend/applicant --stream build", + "bf-hdlr:build": "cross-env NODE_OPTIONS=--openssl-legacy-provider npx lerna run --scope @frontend/bf-handler --stream build", "ks-empl:dev": "npx lerna run --scope @frontend/employer --stream dev", "ks-hdlr:dev": "npx lerna run --scope @frontend/ks-handler --stream dev", "ks-youth:dev": "npx lerna run --scope @frontend/youth --stream dev", @@ -50,13 +50,13 @@ "ks-youth:browser-test:ci": "yarn --cwd kesaseteli/youth browser-test:ci", "shared:test": " yarn --cwd shared test", "ks-shared:test": " yarn --cwd kesaseteli/shared test", - "te-admin:build": "npx lerna run --scope @frontend/te-admin --stream build", + "te-admin:build": "cross-env NODE_OPTIONS=--openssl-legacy-provider npx lerna run --scope @frontend/te-admin --stream build", "te-admin:dev": "npx lerna run --scope @frontend/te-admin --stream dev", "te-admin:start": "npx lerna run --scope @frontend/te-admin --stream start", "te-admin:test": " yarn --cwd tet/admin test", "te-admin:browser-test": "yarn --cwd tet/admin browser-test", "te-admin:browser-test:ci": "yarn --cwd tet/admin browser-test:ci", - "te-youth:build": "npx lerna run --scope @frontend/te-youth --stream build", + "te-youth:build": "cross-env NODE_OPTIONS=--openssl-legacy-provider npx lerna run --scope @frontend/te-youth --stream build", "te-youth:dev": "npx lerna run --scope @frontend/te-youth --stream dev", "te-youth:start": "npx lerna run --scope @frontend/te-youth --stream start", "te-youth:test": " yarn --cwd tet/youth test", From 62d06fafe28d8bd6ba8bb7d2495613efc69b8740 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Fri, 19 May 2023 15:08:44 +0300 Subject: [PATCH 06/82] Use webpack's --openssl-legacy-provider option in GH actions --- .github/workflows/bf-applicant-frontend-tests.yml | 2 +- .github/workflows/bf-handler-frontend-tests.yml | 2 +- .github/workflows/ks-empl-frontend-tests.yml | 14 +++++++------- .github/workflows/ks-handler-frontend-tests.yml | 14 +++++++------- .github/workflows/ks-youth-frontend-tests.yml | 14 +++++++------- .github/workflows/te-admn-frontend-tests.yml | 12 ++++++------ .github/workflows/te-yout-frontend-tests.yml | 12 ++++++------ 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/.github/workflows/bf-applicant-frontend-tests.yml b/.github/workflows/bf-applicant-frontend-tests.yml index c4d28edb66..6c3326332f 100644 --- a/.github/workflows/bf-applicant-frontend-tests.yml +++ b/.github/workflows/bf-applicant-frontend-tests.yml @@ -68,4 +68,4 @@ jobs: - name: Check that building dev application works env: NEXTJS_DISABLE_SENTRY: true - run: yarn build + run: NODE_OPTIONS=--openssl-legacy-provider yarn build diff --git a/.github/workflows/bf-handler-frontend-tests.yml b/.github/workflows/bf-handler-frontend-tests.yml index c8e1103c96..9596a69797 100644 --- a/.github/workflows/bf-handler-frontend-tests.yml +++ b/.github/workflows/bf-handler-frontend-tests.yml @@ -68,4 +68,4 @@ jobs: - name: Check that building dev application works env: NEXTJS_DISABLE_SENTRY: true - run: yarn build + run: NODE_OPTIONS=--openssl-legacy-provider yarn build diff --git a/.github/workflows/ks-empl-frontend-tests.yml b/.github/workflows/ks-empl-frontend-tests.yml index d3dc1ecb88..b6e75f0e5a 100644 --- a/.github/workflows/ks-empl-frontend-tests.yml +++ b/.github/workflows/ks-empl-frontend-tests.yml @@ -2,14 +2,14 @@ name: (KS Employer) Frontend Lint, Unit and Component tests on: push: - branches: [ develop, main ] + branches: [develop, main] pull_request: paths: - - 'frontend/shared/**' - - 'frontend/kesaseteli/shared/**' - - 'frontend/kesaseteli/employer/**' - - 'frontend/*' - - '.github/workflows/ks-empl-frontend-tests.yml' + - "frontend/shared/**" + - "frontend/kesaseteli/shared/**" + - "frontend/kesaseteli/employer/**" + - "frontend/*" + - ".github/workflows/ks-empl-frontend-tests.yml" - "!**/browser-tests/**" - "!**/README.md" workflow_dispatch: @@ -79,7 +79,7 @@ jobs: - name: Check that building dev application works env: NEXTJS_DISABLE_SENTRY: true - run: yarn build + run: NODE_OPTIONS=--openssl-legacy-provider yarn build - name: Frontend build failure slack notification uses: rtCamp/action-slack-notify@v2 env: diff --git a/.github/workflows/ks-handler-frontend-tests.yml b/.github/workflows/ks-handler-frontend-tests.yml index f91a288813..aae9af617d 100644 --- a/.github/workflows/ks-handler-frontend-tests.yml +++ b/.github/workflows/ks-handler-frontend-tests.yml @@ -2,14 +2,14 @@ name: (KS Handler) Frontend Lint, Unit and Component tests on: push: - branches: [ develop, main ] + branches: [develop, main] pull_request: paths: - - 'frontend/shared/**' - - 'frontend/kesaseteli/shared/**' - - 'frontend/kesaseteli/handler/**' - - 'frontend/*' - - '.github/workflows/ks-handler-frontend-tests.yml' + - "frontend/shared/**" + - "frontend/kesaseteli/shared/**" + - "frontend/kesaseteli/handler/**" + - "frontend/*" + - ".github/workflows/ks-handler-frontend-tests.yml" - "!**/browser-tests/**" - "!**/README.md" workflow_dispatch: @@ -79,7 +79,7 @@ jobs: - name: Check that building dev application works env: NEXTJS_DISABLE_SENTRY: true - run: yarn build + run: NODE_OPTIONS=--openssl-legacy-provider yarn build - name: Frontend build failure slack notification uses: rtCamp/action-slack-notify@v2 env: diff --git a/.github/workflows/ks-youth-frontend-tests.yml b/.github/workflows/ks-youth-frontend-tests.yml index d6da1681db..8ba667154d 100644 --- a/.github/workflows/ks-youth-frontend-tests.yml +++ b/.github/workflows/ks-youth-frontend-tests.yml @@ -2,14 +2,14 @@ name: (KS Youth) Frontend Lint, Unit and Component tests on: push: - branches: [ develop, main ] + branches: [develop, main] pull_request: paths: - - 'frontend/shared/**' - - 'frontend/kesaseteli/shared/**' - - 'frontend/kesaseteli/youth/**' - - 'frontend/*' - - '.github/workflows/ks-youth-frontend-tests.yml' + - "frontend/shared/**" + - "frontend/kesaseteli/shared/**" + - "frontend/kesaseteli/youth/**" + - "frontend/*" + - ".github/workflows/ks-youth-frontend-tests.yml" - "!**/browser-tests/**" - "!**/README.md" workflow_dispatch: @@ -79,7 +79,7 @@ jobs: - name: Check that building dev application works env: NEXTJS_DISABLE_SENTRY: true - run: yarn build + run: NODE_OPTIONS=--openssl-legacy-provider yarn build - name: Frontend build failure slack notification uses: rtCamp/action-slack-notify@v2 env: diff --git a/.github/workflows/te-admn-frontend-tests.yml b/.github/workflows/te-admn-frontend-tests.yml index ecee92a43c..9b8b1a4143 100644 --- a/.github/workflows/te-admn-frontend-tests.yml +++ b/.github/workflows/te-admn-frontend-tests.yml @@ -2,13 +2,13 @@ name: (TET) Admin Frontend Lint, Unit and Component tests on: push: - branches: [ develop, main ] + branches: [develop, main] pull_request: paths: - - 'frontend/shared/**' - - 'frontend/tet/admin/**' - - 'frontend/*' - - '.github/workflows/te-admn-frontend-tests.yml' + - "frontend/shared/**" + - "frontend/tet/admin/**" + - "frontend/*" + - ".github/workflows/te-admn-frontend-tests.yml" - "!**/browser-tests/**" - "!**/README.md" workflow_dispatch: @@ -78,7 +78,7 @@ jobs: - name: Check that building dev application works env: NEXTJS_DISABLE_SENTRY: true - run: yarn build + run: NODE_OPTIONS=--openssl-legacy-provider yarn build - name: Frontend build failure slack notification uses: rtCamp/action-slack-notify@v2 env: diff --git a/.github/workflows/te-yout-frontend-tests.yml b/.github/workflows/te-yout-frontend-tests.yml index 2bee662baa..989b9b13ff 100644 --- a/.github/workflows/te-yout-frontend-tests.yml +++ b/.github/workflows/te-yout-frontend-tests.yml @@ -2,13 +2,13 @@ name: (TET) Youth Frontend Lint, Unit and Component tests on: push: - branches: [ develop, main ] + branches: [develop, main] pull_request: paths: - - 'frontend/shared/**' - - 'frontend/*' - - 'frontend/tet/**' - - '.github/workflows/te-yout-frontend-tests.yml' + - "frontend/shared/**" + - "frontend/*" + - "frontend/tet/**" + - ".github/workflows/te-yout-frontend-tests.yml" - "!**/browser-tests/**" - "!**/README.md" workflow_dispatch: @@ -78,7 +78,7 @@ jobs: - name: Check that building dev application works env: NEXTJS_DISABLE_SENTRY: true - run: yarn build + run: NODE_OPTIONS=--openssl-legacy-provider yarn build - name: Frontend build failure slack notification uses: rtCamp/action-slack-notify@v2 env: From b7c1abd414fba2b8f83b804830bf71c52de8991d Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Fri, 19 May 2023 16:47:59 +0300 Subject: [PATCH 07/82] TET: See if TypeScript errors can be dodged with older type definitions --- frontend/package.json | 2 +- frontend/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 67bfa1c2b6..520152ce74 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -82,7 +82,7 @@ "@types/jest": "^27.4.0", "@types/jest-axe": "^3.5.3", "@types/leaflet": "^1.7.9", - "@types/node": "^18.16.0", + "@types/node": "^17.0.43", "@types/pretty": "^2.0.1", "@types/react-input-mask": "2.0.5", "@types/react-leaflet": "^2.8.2", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 791e21d04f..cdd34ee442 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -3336,10 +3336,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.47.tgz#ca9237d51f2a2557419688511dab1c8daf475188" integrity sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg== -"@types/node@^18.16.0": - version "18.16.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.3.tgz#6bda7819aae6ea0b386ebc5b24bdf602f1b42b01" - integrity sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q== +"@types/node@^17.0.43": + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/normalize-package-data@^2.4.0": version "2.4.1" From 698f2c1b6d1b4b72658fd1a2f6568d81febb25e4 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Mon, 22 May 2023 13:08:30 +0300 Subject: [PATCH 08/82] Add --NODE_OPTIONS=--openssl-legacy-provider to dockerfile too --- frontend/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/Dockerfile b/frontend/Dockerfile index beb351fee0..1bb73acc6e 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -38,7 +38,7 @@ FROM appbase as development # Set V8 max heap size to 2GB (default is 512MB) # This prevents Docker Compose from crashing due to out of memory errors -ENV NODE_OPTIONS="--max_old_space_size=2048" +ENV NODE_OPTIONS="--max_old_space_size=2048 --openssl-legacy-provider" ARG PROJECT ARG FOLDER @@ -102,6 +102,8 @@ RUN yarn cache clean FROM helsinkitest/node:18-slim AS production # ========================================== +ENV NODE_OPTIONS="--openssl-legacy-provider" + ARG PORT ARG PROJECT ARG FOLDER From ce8459b95e31e311ac98eea5bc4ec03a86a5066b Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Tue, 23 May 2023 10:11:24 +0300 Subject: [PATCH 09/82] Revert 9646aba7, add @ts-ignore to rule out some issues with react-hook-form This reverts commit 9646aba74a47da766072ce1e303b8635ed619771. --- frontend/package.json | 2 +- frontend/tet/admin/src/components/editor/Editor.tsx | 13 ++++++++++--- .../admin/src/components/editor/HiddenIdInput.tsx | 5 +++++ .../admin/src/components/editor/SelectionGroup.tsx | 5 +++++ frontend/yarn.lock | 8 ++++---- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 520152ce74..67bfa1c2b6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -82,7 +82,7 @@ "@types/jest": "^27.4.0", "@types/jest-axe": "^3.5.3", "@types/leaflet": "^1.7.9", - "@types/node": "^17.0.43", + "@types/node": "^18.16.0", "@types/pretty": "^2.0.1", "@types/react-input-mask": "2.0.5", "@types/react-leaflet": "^2.8.2", diff --git a/frontend/tet/admin/src/components/editor/Editor.tsx b/frontend/tet/admin/src/components/editor/Editor.tsx index 8ca77bdd05..db1197d655 100644 --- a/frontend/tet/admin/src/components/editor/Editor.tsx +++ b/frontend/tet/admin/src/components/editor/Editor.tsx @@ -23,6 +23,13 @@ export type EditorSectionProps = { initialValue: TetPosting; }; +// Known issue with react-hook-form library, errors out with: +// Type of property 'prototype' circularly references itself in mapped type '{ [K in keyof Blob]-?: PathImpl; }'. +// More at: https://github.com/orgs/react-hook-form/discussions/7764 + +// @ts-ignore +const RenderHiddenIdInput = (id: string, value: string): JSXElement => ; + // add new posting / edit existing const Editor: React.FC = ({ initialValue, isNewPosting = false }) => { const { t } = useTranslation(); @@ -38,9 +45,9 @@ const Editor: React.FC = ({ initialValue, isNewPosting = false }) = return (
- - - + {RenderHiddenIdInput('id', initialValue?.id)} + {RenderHiddenIdInput('image_url', initialValue?.image_url)} + {RenderHiddenIdInput('image_id', initialValue?.image_id)}

* {t('common:editor.requiredInfo')}

diff --git a/frontend/tet/admin/src/components/editor/HiddenIdInput.tsx b/frontend/tet/admin/src/components/editor/HiddenIdInput.tsx index 71f53a8e12..2dd763e7a7 100644 --- a/frontend/tet/admin/src/components/editor/HiddenIdInput.tsx +++ b/frontend/tet/admin/src/components/editor/HiddenIdInput.tsx @@ -3,6 +3,11 @@ import { useFormContext } from 'react-hook-form'; import InputProps from 'shared/types/input-props'; import TetPosting from 'tet-shared/types/tetposting'; +// Known issue with react-hook-form library, errors out with: +// Type of property 'prototype' circularly references itself in mapped type '{ [K in keyof Blob]-?: PathImpl; }'. +// More at: https://github.com/orgs/react-hook-form/discussions/7764 + +// @ts-ignore const HiddenIdInput: React.FC> = ({ id, initialValue }) => { const { register } = useFormContext(); return ; diff --git a/frontend/tet/admin/src/components/editor/SelectionGroup.tsx b/frontend/tet/admin/src/components/editor/SelectionGroup.tsx index 7a70e86fd7..1284a744e1 100644 --- a/frontend/tet/admin/src/components/editor/SelectionGroup.tsx +++ b/frontend/tet/admin/src/components/editor/SelectionGroup.tsx @@ -34,6 +34,11 @@ const SelectionGroup: React.FC = ({ fieldId, label, options, required, ru }; return ( + // Known issue with react-hook-form library, errors out with: + // Type of property 'prototype' circularly references itself in mapped type '{ [K in keyof Blob]-?: PathImpl; }'. + // More at: https://github.com/orgs/react-hook-form/discussions/7764 + + // @ts-ignore Date: Mon, 26 Jun 2023 13:34:50 +0300 Subject: [PATCH 10/82] fix: wrong cwd for bf-handler ran all project's tests --- frontend/package.json | 6 +++--- package.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 67bfa1c2b6..056830de02 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,8 +10,8 @@ "tet/*", "shared" ], - "engines" : { - "node" : ">=18.16.0 <19.0.0" + "engines": { + "node": ">=18.16.0 <19.0.0" }, "scripts": { "audit": "npx lerna-audit --level=high --groups=dependencies", @@ -39,7 +39,7 @@ "test:staged": "npx lerna run test:staged", "test:coverage": "npx lerna run test:coverage --stream --concurrency 1", "bf-appl:test": "yarn --cwd benefit/applicant test", - "bf-hdlr:test": "yarn --cwd benefit/bf-handler test", + "bf-hdlr:test": "yarn --cwd benefit/handler test", "bf-appl:browser-test": "yarn --cwd benefit/applicant browser-test", "bf-appl:browser-test:ci": "yarn --cwd benefit/applicant browser-test:ci", "ks-empl:test": " yarn --cwd kesaseteli/employer test", diff --git a/package.json b/package.json index 45b1917ac5..3f53dc9d16 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,12 @@ "cross-env": "^7.0.3", "husky": "^8.0.3" }, - "engines" : { - "node" : ">=18.16.0 <19.0.0" + "engines": { + "node": ">=18.16.0 <19.0.0" }, "scripts": { "prepare": "husky install", - "// clean: stop and remove docker containers and database volume" : "", + "// clean: stop and remove docker containers and database volume": "", "clean": "docker compose -f compose.handler.yml down --remove-orphans; docker compose -f compose.employer.yml down --remove-orphans; docker compose -f compose.benefit.yml down --remove-orphans; docker rm -f $(docker ps -a -q); docker volume rm $(docker volume ls -q);", "// partial docker compose commands per service, dont use these straight. Use :up, :build or :rebuild instead ": "", "benefit": "cross-env COMPOSE_HTTP_TIMEOUT=200 docker compose -f compose.benefit.yml", From fc4d401773dae5abc66ab7d222d493169df5ab87 Mon Sep 17 00:00:00 2001 From: Maks Turtiainen Date: Thu, 20 Jul 2023 00:05:49 +0300 Subject: [PATCH 11/82] Review state backend implementation and start frontend --- .../applications/api/v1/review_state_views.py | 11 +++++++ .../api/v1/serializers/review_state.py | 9 +++++ .../migrations/0036_reviewstate.py | 28 ++++++++++++++++ backend/benefit/applications/models.py | 23 +++++++++++++ .../applicationReview/useApplicationReview.ts | 14 ++++++++ .../handler/src/hooks/useReviewStateQuery.ts | 26 +++++++++++++++ .../src/hooks/useUpdateReviewStateQuery.ts | 33 +++++++++++++++++++ 7 files changed, 144 insertions(+) create mode 100644 backend/benefit/applications/api/v1/review_state_views.py create mode 100644 backend/benefit/applications/api/v1/serializers/review_state.py create mode 100644 backend/benefit/applications/migrations/0036_reviewstate.py create mode 100644 frontend/benefit/handler/src/hooks/useReviewStateQuery.ts create mode 100644 frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts diff --git a/backend/benefit/applications/api/v1/review_state_views.py b/backend/benefit/applications/api/v1/review_state_views.py new file mode 100644 index 0000000000..a207bb57e8 --- /dev/null +++ b/backend/benefit/applications/api/v1/review_state_views.py @@ -0,0 +1,11 @@ +from rest_framework.viewsets import ModelViewSet + +from applications.api.v1.serializers.review_state import ReviewStateSerializer +from applications.models import ReviewState +from common.permissions import BFIsHandler + + +class ReviewStateViewSet(ModelViewSet): + queryset = ReviewState.objects.all() + serializer_class = ReviewStateSerializer + permission_classes = [BFIsHandler] diff --git a/backend/benefit/applications/api/v1/serializers/review_state.py b/backend/benefit/applications/api/v1/serializers/review_state.py new file mode 100644 index 0000000000..2518e1b1b1 --- /dev/null +++ b/backend/benefit/applications/api/v1/serializers/review_state.py @@ -0,0 +1,9 @@ +from rest_framework import serializers + +from applications.models import ReviewState + + +class ReviewStateSerializer(serializers.ModelSerializer): + class Meta: + model = ReviewState + fields = "__all__" diff --git a/backend/benefit/applications/migrations/0036_reviewstate.py b/backend/benefit/applications/migrations/0036_reviewstate.py new file mode 100644 index 0000000000..5e25986ba7 --- /dev/null +++ b/backend/benefit/applications/migrations/0036_reviewstate.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.18 on 2023-07-19 20:52 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('applications', '0035_alter_applicationbatch_handler'), + ] + + operations = [ + migrations.CreateModel( + name='ReviewState', + fields=[ + ('application', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='applications.application', verbose_name='application')), + ('company', models.BooleanField(default=False, verbose_name='company')), + ('company_contact_person', models.BooleanField(default=False, verbose_name='company contact person')), + ('de_minimis_aids', models.BooleanField(default=False, verbose_name='de minimis aids')), + ('co_operation_negotiations', models.BooleanField(default=False, verbose_name='co-operation negotiations')), + ('employee', models.BooleanField(default=False, verbose_name='employee')), + ('pay_subsidy', models.BooleanField(default=False, verbose_name='pay subsidy')), + ('benefit', models.BooleanField(default=False, verbose_name='benefit')), + ('employment', models.BooleanField(default=False, verbose_name='employment')), + ], + ), + ] diff --git a/backend/benefit/applications/models.py b/backend/benefit/applications/models.py index 6aa2f676c2..c22031fb31 100755 --- a/backend/benefit/applications/models.py +++ b/backend/benefit/applications/models.py @@ -827,3 +827,26 @@ class Meta: def __str__(self): return "{} {}".format(self.attachment_type, self.attachment_file.name) + + +class ReviewState(models.Model): + application = models.OneToOneField( + Application, + on_delete=models.CASCADE, + primary_key=True, + verbose_name=_("application"), + ) + company = models.BooleanField(default=False, verbose_name=_("company")) + company_contact_person = models.BooleanField( + default=False, verbose_name=_("company contact person") + ) + de_minimis_aids = models.BooleanField( + default=False, verbose_name=_("de minimis aids") + ) + co_operation_negotiations = models.BooleanField( + default=False, verbose_name=_("co-operation negotiations") + ) + employee = models.BooleanField(default=False, verbose_name=_("employee")) + pay_subsidy = models.BooleanField(default=False, verbose_name=_("pay subsidy")) + benefit = models.BooleanField(default=False, verbose_name=_("benefit")) + employment = models.BooleanField(default=False, verbose_name=_("employment")) diff --git a/frontend/benefit/handler/src/components/applicationReview/useApplicationReview.ts b/frontend/benefit/handler/src/components/applicationReview/useApplicationReview.ts index 8611c9d158..29e2c90383 100644 --- a/frontend/benefit/handler/src/components/applicationReview/useApplicationReview.ts +++ b/frontend/benefit/handler/src/components/applicationReview/useApplicationReview.ts @@ -1,5 +1,7 @@ import AppContext from 'benefit/handler/context/AppContext'; import useApplicationQuery from 'benefit/handler/hooks/useApplicationQuery'; +import useReviewStateQuery from 'benefit/handler/hooks/useReviewStateQuery'; +import useUpdateReviewStateQuery from 'benefit/handler/hooks/useUpdateReviewStateQuery'; import useUploadAttachmentQuery from 'benefit/handler/hooks/useUploadAttachmentQuery'; import { Application, @@ -42,6 +44,18 @@ const useApplicationReview = (): ExtendedComponentProps => { isError: isUploadingError, } = useUploadAttachmentQuery(); + const { + status: reviewStateDataStatus, + data: reviewStateData, + error: reviewStateDataError, + } = useReviewStateQuery(id); + + const { + mutate: updateReviewState, + isLoading: isUpdating, + isError: isUpdatingError, + } = useUpdateReviewStateQuery(); + const handleUpload = (attachment: FormData): void => { uploadAttachment({ applicationId: id, diff --git a/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts b/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts new file mode 100644 index 0000000000..003d9521f3 --- /dev/null +++ b/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts @@ -0,0 +1,26 @@ +import { BackendEndpoint } from 'benefit-shared/backend-api/backend-api'; +import { ApplicationData } from 'benefit-shared/types/application'; +import { useQuery, UseQueryResult } from 'react-query'; +import useBackendAPI from 'shared/hooks/useBackendAPI'; + +const useReviewStateQuery = ( + id: string +): UseQueryResult => { + const { axios, handleResponse } = useBackendAPI(); + + return useQuery( + ['reviewState', id], + () => + !id + ? Promise.reject(new Error('Missing application id')) + : handleResponse( + axios.get(`${BackendEndpoint.HANDLER_APPLICATIONS}${id}/`) + ), + { + enabled: Boolean(id), + staleTime: Infinity, + } + ); +}; + +export default useReviewStateQuery; diff --git a/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts b/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts new file mode 100644 index 0000000000..56aa37bba8 --- /dev/null +++ b/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts @@ -0,0 +1,33 @@ +import { AxiosError } from 'axios'; +import { BackendEndpoint } from 'benefit-shared/backend-api/backend-api'; +import { ApplicationData } from 'benefit-shared/types/application'; +import { useMutation, UseMutationResult, useQueryClient } from 'react-query'; +import useBackendAPI from 'shared/hooks/useBackendAPI'; + +import { ErrorData } from '../types/common'; + +const useUpdateReviewStateQuery = (): UseMutationResult< + ApplicationData, + AxiosError, + ApplicationData +> => { + const { axios, handleResponse } = useBackendAPI(); + const queryClient = useQueryClient(); + return useMutation, ApplicationData>( + 'updateApplication', + (application: ApplicationData) => + handleResponse( + axios.put( + `${BackendEndpoint.HANDLER_APPLICATIONS}${application?.id ?? ''}/`, + application + ) + ), + { + onSuccess: () => { + void queryClient.invalidateQueries('reviewState'); + }, + } + ); +}; + +export default useUpdateReviewStateQuery; From d79bb62ac0b76c2c7c3f5ec40edaae025768826a Mon Sep 17 00:00:00 2001 From: Maks Turtiainen Date: Fri, 21 Jul 2023 23:18:16 +0300 Subject: [PATCH 12/82] Review state endpoints and continue frontend --- .../applications/api/v1/review_state_views.py | 33 ++++++++++++++--- backend/benefit/helsinkibenefit/urls.py | 2 ++ .../applicationReview/useApplicationReview.ts | 35 ++++++++++++++++--- .../handler/src/hooks/useReviewStateQuery.ts | 2 +- .../src/hooks/useUpdateReviewStateQuery.ts | 18 +++++----- .../handler/src/types/application.d.ts | 24 +++++++++++++ 6 files changed, 94 insertions(+), 20 deletions(-) diff --git a/backend/benefit/applications/api/v1/review_state_views.py b/backend/benefit/applications/api/v1/review_state_views.py index a207bb57e8..972b57390c 100644 --- a/backend/benefit/applications/api/v1/review_state_views.py +++ b/backend/benefit/applications/api/v1/review_state_views.py @@ -1,11 +1,34 @@ -from rest_framework.viewsets import ModelViewSet +from rest_framework import status +from rest_framework.response import Response +from rest_framework.views import APIView from applications.api.v1.serializers.review_state import ReviewStateSerializer -from applications.models import ReviewState +from applications.models import Application, ReviewState from common.permissions import BFIsHandler -class ReviewStateViewSet(ModelViewSet): - queryset = ReviewState.objects.all() - serializer_class = ReviewStateSerializer +class ReviewStateViewSet(APIView): permission_classes = [BFIsHandler] + + def get(self, _, application_id): + try: + review_state = ReviewState.objects.get(application=application_id) + except ReviewState.DoesNotExist: + application = Application.objects.get(id=application_id) + if application: + review_state = ReviewState.objects.create(application=application) + else: + return Response(status=status.HTTP_404_NOT_FOUND) + serializer = ReviewStateSerializer(review_state) + return Response(serializer.data) + + def put(self, request, application_id): + try: + review_state = ReviewState.objects.get(application=application_id) + except ReviewState.DoesNotExist: + return Response(status=status.HTTP_404_NOT_FOUND) + serializer = ReviewStateSerializer(review_state, data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) diff --git a/backend/benefit/helsinkibenefit/urls.py b/backend/benefit/helsinkibenefit/urls.py index 0e970d750a..5731ad3e1a 100644 --- a/backend/benefit/helsinkibenefit/urls.py +++ b/backend/benefit/helsinkibenefit/urls.py @@ -12,6 +12,7 @@ from rest_framework_nested import routers from applications.api.v1 import application_batch_views, views as application_views +from applications.api.v1.review_state_views import ReviewStateViewSet from calculator.api.v1 import views as calculator_views from common.debug_util import debug_env from companies.api.v1.views import ( @@ -69,6 +70,7 @@ path("v1/company/search//", SearchOrganisationsView.as_view()), path("v1/company/get//", GetOrganisationByIdView.as_view()), path("v1/users/me/", CurrentUserView.as_view()), + path("v1/handlerapplications//review/", ReviewStateViewSet.as_view()), path("oidc/", include("shared.oidc.urls")), path("oauth2/", include("shared.azure_adfs.urls")), path("api-auth/", include("rest_framework.urls", namespace="rest_framework")), diff --git a/frontend/benefit/handler/src/components/applicationReview/useApplicationReview.ts b/frontend/benefit/handler/src/components/applicationReview/useApplicationReview.ts index 29e2c90383..ddbf70ac90 100644 --- a/frontend/benefit/handler/src/components/applicationReview/useApplicationReview.ts +++ b/frontend/benefit/handler/src/components/applicationReview/useApplicationReview.ts @@ -6,6 +6,8 @@ import useUploadAttachmentQuery from 'benefit/handler/hooks/useUploadAttachmentQ import { Application, HandledAplication, + ReviewState, + ReviewStateData, } from 'benefit/handler/types/application'; import camelcaseKeys from 'camelcase-keys'; import { useRouter } from 'next/router'; @@ -13,6 +15,7 @@ import { TFunction, useTranslation } from 'next-i18next'; import React, { useEffect, useState } from 'react'; import showErrorToast from 'shared/components/toast/show-error-toast'; import hdsToast from 'shared/components/toast/Toast'; +import snakecaseKeys from 'snakecase-keys'; type ExtendedComponentProps = { t: TFunction; @@ -23,6 +26,9 @@ type ExtendedComponentProps = { isLoading: boolean; isUploading: boolean; handleUpload: (attachment: FormData) => void; + reviewState: ReviewState; + isUpdating: boolean; + handleUpdateReviewState: (reviewState: ReviewState) => void; }; const useApplicationReview = (): ExtendedComponentProps => { @@ -63,6 +69,11 @@ const useApplicationReview = (): ExtendedComponentProps => { }); }; + const handleUpdateReviewState = (reviewState: ReviewState): void => { + const data: ReviewStateData = snakecaseKeys(reviewState); + updateReviewState(data); + }; + useEffect(() => { if (isUploadingError) { showErrorToast( @@ -73,7 +84,7 @@ const useApplicationReview = (): ExtendedComponentProps => { }, [isUploadingError, t]); useEffect(() => { - if (applicationDataError) { + if (applicationDataError || reviewStateDataError || isUpdatingError) { hdsToast({ autoDismissTime: 5000, type: 'error', @@ -81,17 +92,24 @@ const useApplicationReview = (): ExtendedComponentProps => { text: t('common:error.generic.text'), }); } - }, [t, applicationDataError]); + }, [t, applicationDataError, reviewStateDataError, isUpdatingError]); useEffect(() => { + const loadingDataStatuses = new Set(['idle', 'loading']); if ( id && - applicationDataStatus !== 'idle' && - applicationDataStatus !== 'loading' + !loadingDataStatuses.has(applicationDataStatus) && + !loadingDataStatuses.has(reviewStateDataStatus) ) { setIsLoading(false); } - }, [applicationDataStatus, id, applicationData]); + }, [ + id, + applicationDataStatus, + applicationData, + reviewStateDataStatus, + reviewStateData, + ]); useEffect(() => { if (router.isReady && !router.query.id) { @@ -103,6 +121,10 @@ const useApplicationReview = (): ExtendedComponentProps => { deep: true, }); + const reviewState: ReviewState = camelcaseKeys(reviewStateData || {}, { + deep: true, + }); + return { t, id, @@ -112,6 +134,9 @@ const useApplicationReview = (): ExtendedComponentProps => { isError: Boolean(id && applicationDataError), isUploading, handleUpload, + reviewState, + isUpdating, + handleUpdateReviewState, }; }; diff --git a/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts b/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts index 003d9521f3..d090667662 100644 --- a/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts +++ b/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts @@ -14,7 +14,7 @@ const useReviewStateQuery = ( !id ? Promise.reject(new Error('Missing application id')) : handleResponse( - axios.get(`${BackendEndpoint.HANDLER_APPLICATIONS}${id}/`) + axios.get(`${BackendEndpoint.HANDLER_APPLICATIONS}${id}/review/`) ), { enabled: Boolean(id), diff --git a/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts b/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts index 56aa37bba8..5795651a12 100644 --- a/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts +++ b/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts @@ -1,25 +1,25 @@ import { AxiosError } from 'axios'; +import { ReviewStateData } from 'benefit/handler/types/application'; import { BackendEndpoint } from 'benefit-shared/backend-api/backend-api'; -import { ApplicationData } from 'benefit-shared/types/application'; import { useMutation, UseMutationResult, useQueryClient } from 'react-query'; import useBackendAPI from 'shared/hooks/useBackendAPI'; import { ErrorData } from '../types/common'; const useUpdateReviewStateQuery = (): UseMutationResult< - ApplicationData, + ReviewStateData, AxiosError, - ApplicationData + ReviewStateData > => { const { axios, handleResponse } = useBackendAPI(); const queryClient = useQueryClient(); - return useMutation, ApplicationData>( - 'updateApplication', - (application: ApplicationData) => - handleResponse( + return useMutation, ReviewStateData>( + 'updateReviewState', + (reviewState: ReviewStateData) => + handleResponse( axios.put( - `${BackendEndpoint.HANDLER_APPLICATIONS}${application?.id ?? ''}/`, - application + `${BackendEndpoint.HANDLER_APPLICATIONS}${reviewState.id}/review/`, + reviewState ) ), { diff --git a/frontend/benefit/handler/src/types/application.d.ts b/frontend/benefit/handler/src/types/application.d.ts index a8121b0444..877e11f20a 100644 --- a/frontend/benefit/handler/src/types/application.d.ts +++ b/frontend/benefit/handler/src/types/application.d.ts @@ -177,3 +177,27 @@ export type ApplicationFields = Record< APPLICATION_FIELD_KEYS.EMPLOYEE, Record> >; + +export type ReviewState = { + id?: string; + company?: boolean; + companyContactPerson?: boolean; + deMinimisAids?: boolean; + coOperationNegotiations?: boolean; + employee?: boolean; + paySubsidy?: boolean; + benefit?: boolean; + employment?: boolean; +}; + +export type ReviewStateData = { + id?: string; + company?: boolean; + company_contact_person?: boolean; + de_minimis_aids?: boolean; + co_operation_negotiations?: boolean; + employee?: boolean; + pay_subsidy?: boolean; + benefit?: boolean; + employment?: boolean; +}; From d01efb53c335154c2b6bdf819d5bc525de4e6cea Mon Sep 17 00:00:00 2001 From: Maks Turtiainen Date: Sun, 23 Jul 2023 21:55:43 +0300 Subject: [PATCH 13/82] Review state frontend implementation --- .../applicationReview/ApplicationReview.tsx | 79 +++++++++++-------- .../benefitView/BenefitView.tsx | 1 + .../CoOperationNegotiationsView.tsx | 1 + .../companyInfoView/CompanyInfoView.tsx | 1 + .../contactPersonView/ContactPersonView.tsx | 1 + .../deminimisView/DeminimisView.tsx | 1 + .../employeeView/EmployeeView.tsx | 1 + .../employmentView/EmpoymentView.tsx | 1 + .../paySubsidyView/PaySubsidyView.tsx | 1 + .../applicationReview/useApplicationReview.ts | 13 +-- .../reviewSection/ReviewSection.sc.ts | 10 ++- .../reviewSection/ReviewSection.tsx | 36 ++++++++- .../src/context/ReviewStateContext.tsx | 24 ++++++ .../handler/src/hooks/useReviewStateQuery.ts | 8 +- .../src/hooks/useUpdateReviewStateQuery.ts | 2 +- .../handler/src/types/application.d.ts | 4 +- 16 files changed, 132 insertions(+), 52 deletions(-) create mode 100644 frontend/benefit/handler/src/context/ReviewStateContext.tsx diff --git a/frontend/benefit/handler/src/components/applicationReview/ApplicationReview.tsx b/frontend/benefit/handler/src/components/applicationReview/ApplicationReview.tsx index a1ac21a07e..9783b68630 100644 --- a/frontend/benefit/handler/src/components/applicationReview/ApplicationReview.tsx +++ b/frontend/benefit/handler/src/components/applicationReview/ApplicationReview.tsx @@ -1,5 +1,6 @@ import ApplicationHeader from 'benefit/handler/components/applicationHeader/ApplicationHeader'; import { HANDLED_STATUSES } from 'benefit/handler/constants'; +import ReviewStateContext from 'benefit/handler/context/ReviewStateContext'; import { APPLICATION_ORIGINS, APPLICATION_STATUSES, @@ -33,6 +34,7 @@ import PaySubsidyView from './paySubsidyView/PaySubsidyView'; import SalaryBenefitCalculatorView from './salaryBenefitCalculatorView/SalaryBenefitCalculatorView'; import { useApplicationReview } from './useApplicationReview'; + const ApplicationReview: React.FC = () => { const { application, @@ -41,6 +43,8 @@ const ApplicationReview: React.FC = () => { t, isUploading, handleUpload, + reviewState, + handleUpdateReviewState, } = useApplicationReview(); const theme = useTheme(); @@ -92,45 +96,52 @@ const ApplicationReview: React.FC = () => { })} )} - - - - - - - - - {application.applicationOrigin === APPLICATION_ORIGINS.HANDLER ? ( - - ) : ( - + + + + + - )} - {application.status === APPLICATION_STATUSES.HANDLING && ( - <> - - - - )} - {application.status && - HANDLED_STATUSES.includes(application.status) && ( - + + + + {application.applicationOrigin === APPLICATION_ORIGINS.HANDLER ? ( + + ) : ( + + )} + {application.status === APPLICATION_STATUSES.HANDLING && ( + <> + + + )} + {application.status && + HANDLED_STATUSES.includes(application.status) && ( + + )} + {application.status === APPLICATION_STATUSES.RECEIVED && ( diff --git a/frontend/benefit/handler/src/components/applicationReview/benefitView/BenefitView.tsx b/frontend/benefit/handler/src/components/applicationReview/benefitView/BenefitView.tsx index 9ec52cd8c1..9284f8fa9f 100644 --- a/frontend/benefit/handler/src/components/applicationReview/benefitView/BenefitView.tsx +++ b/frontend/benefit/handler/src/components/applicationReview/benefitView/BenefitView.tsx @@ -18,6 +18,7 @@ const BenefitView: React.FC = ({ data }) => { withoutDivider header={t(`${translationsBase}.headings.heading7`)} action={data.status !== APPLICATION_STATUSES.RECEIVED ? : null} + section='benefit' > <$GridCell $colSpan={6}> <$ViewField> diff --git a/frontend/benefit/handler/src/components/applicationReview/coOperationNegotiationsView/CoOperationNegotiationsView.tsx b/frontend/benefit/handler/src/components/applicationReview/coOperationNegotiationsView/CoOperationNegotiationsView.tsx index a27c2464e2..1271fdce1a 100644 --- a/frontend/benefit/handler/src/components/applicationReview/coOperationNegotiationsView/CoOperationNegotiationsView.tsx +++ b/frontend/benefit/handler/src/components/applicationReview/coOperationNegotiationsView/CoOperationNegotiationsView.tsx @@ -18,6 +18,7 @@ const CoOperationNegotiationsView: React.FC = ({ : null} + section='coOperationNegotiations' > <$GridCell $colSpan={12}> <$ViewField> diff --git a/frontend/benefit/handler/src/components/applicationReview/companyInfoView/CompanyInfoView.tsx b/frontend/benefit/handler/src/components/applicationReview/companyInfoView/CompanyInfoView.tsx index b879800627..3329b7d19b 100644 --- a/frontend/benefit/handler/src/components/applicationReview/companyInfoView/CompanyInfoView.tsx +++ b/frontend/benefit/handler/src/components/applicationReview/companyInfoView/CompanyInfoView.tsx @@ -21,6 +21,7 @@ const CompanyInfoView: React.FC = ({ data }) => { : null} + section='company' > <$GridCell $colSpan={3}> <$ViewField>{data.company?.name} diff --git a/frontend/benefit/handler/src/components/applicationReview/contactPersonView/ContactPersonView.tsx b/frontend/benefit/handler/src/components/applicationReview/contactPersonView/ContactPersonView.tsx index 1c57f5cf09..16297cfbb8 100644 --- a/frontend/benefit/handler/src/components/applicationReview/contactPersonView/ContactPersonView.tsx +++ b/frontend/benefit/handler/src/components/applicationReview/contactPersonView/ContactPersonView.tsx @@ -17,6 +17,7 @@ const ContactPersonView: React.FC = ({ data }) => { : null} + section='companyContactPerson' > <$GridCell $colSpan={6}> <$ViewField> diff --git a/frontend/benefit/handler/src/components/applicationReview/deminimisView/DeminimisView.tsx b/frontend/benefit/handler/src/components/applicationReview/deminimisView/DeminimisView.tsx index 7a3a2d1581..475bc71862 100644 --- a/frontend/benefit/handler/src/components/applicationReview/deminimisView/DeminimisView.tsx +++ b/frontend/benefit/handler/src/components/applicationReview/deminimisView/DeminimisView.tsx @@ -21,6 +21,7 @@ const DeminimisView: React.FC = ({ data }) => { : null} + section='deMinimisAids' > {data.deMinimisAidSet && data.deMinimisAidSet?.length > 0 ? ( <> diff --git a/frontend/benefit/handler/src/components/applicationReview/employeeView/EmployeeView.tsx b/frontend/benefit/handler/src/components/applicationReview/employeeView/EmployeeView.tsx index f57f42944c..1ca44308e0 100644 --- a/frontend/benefit/handler/src/components/applicationReview/employeeView/EmployeeView.tsx +++ b/frontend/benefit/handler/src/components/applicationReview/employeeView/EmployeeView.tsx @@ -26,6 +26,7 @@ const EmployeeView: React.FC = ({ return ( = ({ return ( = ({ return ( void; reviewState: ReviewState; - isUpdating: boolean; handleUpdateReviewState: (reviewState: ReviewState) => void; }; @@ -58,8 +57,7 @@ const useApplicationReview = (): ExtendedComponentProps => { const { mutate: updateReviewState, - isLoading: isUpdating, - isError: isUpdatingError, + isError: isUpdatingReviewStateError, } = useUpdateReviewStateQuery(); const handleUpload = (attachment: FormData): void => { @@ -84,7 +82,11 @@ const useApplicationReview = (): ExtendedComponentProps => { }, [isUploadingError, t]); useEffect(() => { - if (applicationDataError || reviewStateDataError || isUpdatingError) { + if ( + applicationDataError || + reviewStateDataError || + isUpdatingReviewStateError + ) { hdsToast({ autoDismissTime: 5000, type: 'error', @@ -92,7 +94,7 @@ const useApplicationReview = (): ExtendedComponentProps => { text: t('common:error.generic.text'), }); } - }, [t, applicationDataError, reviewStateDataError, isUpdatingError]); + }, [t, applicationDataError, reviewStateDataError, isUpdatingReviewStateError]); useEffect(() => { const loadingDataStatuses = new Set(['idle', 'loading']); @@ -135,7 +137,6 @@ const useApplicationReview = (): ExtendedComponentProps => { isUploading, handleUpload, reviewState, - isUpdating, handleUpdateReviewState, }; }; diff --git a/frontend/benefit/handler/src/components/reviewSection/ReviewSection.sc.ts b/frontend/benefit/handler/src/components/reviewSection/ReviewSection.sc.ts index 2fe6e5a9bc..0313d54e6a 100644 --- a/frontend/benefit/handler/src/components/reviewSection/ReviewSection.sc.ts +++ b/frontend/benefit/handler/src/components/reviewSection/ReviewSection.sc.ts @@ -1,4 +1,4 @@ -import { IconCheckCircle } from 'hds-react'; +import { IconCheckCircle, IconCheckCircleFill } from 'hds-react'; import styled, { DefaultTheme } from 'styled-components'; type ColorKeys = keyof DefaultTheme['colors']; @@ -16,4 +16,12 @@ export const $ActionLeft = styled.div` export const $CheckIcon = styled(IconCheckCircle)` padding-top: 20px; padding-left: ${(props) => props.theme.spacing.s}; + cursor: pointer; +`; + +export const $CheckIconFill = styled(IconCheckCircleFill)` + padding-top: 20px; + padding-left: ${(props) => props.theme.spacing.s}; + color: ${(props) => props.theme.colors.coatOfArms}; + cursor: pointer; `; diff --git a/frontend/benefit/handler/src/components/reviewSection/ReviewSection.tsx b/frontend/benefit/handler/src/components/reviewSection/ReviewSection.tsx index 4025075ac8..2542c00356 100644 --- a/frontend/benefit/handler/src/components/reviewSection/ReviewSection.tsx +++ b/frontend/benefit/handler/src/components/reviewSection/ReviewSection.tsx @@ -1,3 +1,5 @@ +import ReviewStateContext from 'benefit/handler/context/ReviewStateContext'; +import { ReviewState } from 'benefit/handler/types/application'; import * as React from 'react'; import Heading from 'shared/components/forms/heading/Heading'; import { HeadingProps } from 'shared/components/forms/heading/Heading.sc'; @@ -9,7 +11,7 @@ import { GridProps, } from 'shared/components/forms/section/FormSection.sc'; -import { $ActionLeft, $CheckIcon } from './ReviewSection.sc'; +import { $ActionLeft, $CheckIcon, $CheckIconFill } from './ReviewSection.sc'; import { useReviewSection } from './useReviewSection'; export type ReviewSectionProps = { @@ -18,6 +20,7 @@ export type ReviewSectionProps = { withMargin?: boolean; withoutDivider?: boolean; header?: string; + section?: keyof ReviewState; } & HeadingProps & GridProps; @@ -29,9 +32,36 @@ const ReviewSection: React.FC = ({ withoutDivider, role, loading, + section, ...rest }) => { const { theme, bgColor, withAction } = useReviewSection(action, withMargin); + const { reviewState, handleUpdateReviewState } = + React.useContext(ReviewStateContext); + const sectionState = reviewState[section]; + + const handleReviewClick = (): void => { + handleUpdateReviewState({ ...reviewState, [section]: !sectionState }); + }; + + const CheckIcon: React.FC = () => { + if (sectionState) { + return ( + <$CheckIconFill + aria-label="application-action" + size="m" + onClick={handleReviewClick} + /> + ); + } + return ( + <$CheckIcon + aria-label="application-action" + size="m" + onClick={handleReviewClick} + /> + ); + }; return ( <$Grid @@ -43,9 +73,7 @@ const ReviewSection: React.FC = ({ > {withAction && ( <$GridCell $colSpan={1}> - <$ActionLeft> - {action && <$CheckIcon aria-label="application-action" size="m" />} - + <$ActionLeft>{action && } )} <$GridCell $colStart={2} $colSpan={12}> diff --git a/frontend/benefit/handler/src/context/ReviewStateContext.tsx b/frontend/benefit/handler/src/context/ReviewStateContext.tsx new file mode 100644 index 0000000000..2d83cd74aa --- /dev/null +++ b/frontend/benefit/handler/src/context/ReviewStateContext.tsx @@ -0,0 +1,24 @@ +import { ReviewState } from 'benefit/handler/types/application'; +import React from 'react'; + +type ReviewStateContextType = { + reviewState: ReviewState; + handleUpdateReviewState: (reviewState: ReviewState) => void; +}; + +const defaultValues = { + reviewState: { + id: '', + company: false, + companyContactPerson: false, + deMinimisAids: false, + coOperationNegotiations: false, + employee: false, + paySubsidy: false, + benefit: false, + employment: false, + }, + handleUpdateReviewState: () => null, +}; + +export default React.createContext(defaultValues); diff --git a/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts b/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts index d090667662..6c5588b075 100644 --- a/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts +++ b/frontend/benefit/handler/src/hooks/useReviewStateQuery.ts @@ -1,19 +1,19 @@ +import { ReviewStateData } from 'benefit/handler/types/application'; import { BackendEndpoint } from 'benefit-shared/backend-api/backend-api'; -import { ApplicationData } from 'benefit-shared/types/application'; import { useQuery, UseQueryResult } from 'react-query'; import useBackendAPI from 'shared/hooks/useBackendAPI'; const useReviewStateQuery = ( id: string -): UseQueryResult => { +): UseQueryResult => { const { axios, handleResponse } = useBackendAPI(); - return useQuery( + return useQuery( ['reviewState', id], () => !id ? Promise.reject(new Error('Missing application id')) - : handleResponse( + : handleResponse( axios.get(`${BackendEndpoint.HANDLER_APPLICATIONS}${id}/review/`) ), { diff --git a/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts b/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts index 5795651a12..d62f0ae038 100644 --- a/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts +++ b/frontend/benefit/handler/src/hooks/useUpdateReviewStateQuery.ts @@ -18,7 +18,7 @@ const useUpdateReviewStateQuery = (): UseMutationResult< (reviewState: ReviewStateData) => handleResponse( axios.put( - `${BackendEndpoint.HANDLER_APPLICATIONS}${reviewState.id}/review/`, + `${BackendEndpoint.HANDLER_APPLICATIONS}${reviewState.application}/review/`, reviewState ) ), diff --git a/frontend/benefit/handler/src/types/application.d.ts b/frontend/benefit/handler/src/types/application.d.ts index 877e11f20a..f6b48f088f 100644 --- a/frontend/benefit/handler/src/types/application.d.ts +++ b/frontend/benefit/handler/src/types/application.d.ts @@ -179,7 +179,7 @@ export type ApplicationFields = Record< >; export type ReviewState = { - id?: string; + application?: string; company?: boolean; companyContactPerson?: boolean; deMinimisAids?: boolean; @@ -191,7 +191,7 @@ export type ReviewState = { }; export type ReviewStateData = { - id?: string; + application?: string; company?: boolean; company_contact_person?: boolean; de_minimis_aids?: boolean; From 03c5a997561400c4d573a23be3342503fbd2643f Mon Sep 17 00:00:00 2001 From: Maks Turtiainen Date: Sun, 23 Jul 2023 21:59:00 +0300 Subject: [PATCH 14/82] Rename review viewset to view --- backend/benefit/applications/api/v1/review_state_views.py | 2 +- backend/benefit/helsinkibenefit/urls.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/benefit/applications/api/v1/review_state_views.py b/backend/benefit/applications/api/v1/review_state_views.py index 972b57390c..348f5cb0d5 100644 --- a/backend/benefit/applications/api/v1/review_state_views.py +++ b/backend/benefit/applications/api/v1/review_state_views.py @@ -7,7 +7,7 @@ from common.permissions import BFIsHandler -class ReviewStateViewSet(APIView): +class ReviewStateView(APIView): permission_classes = [BFIsHandler] def get(self, _, application_id): diff --git a/backend/benefit/helsinkibenefit/urls.py b/backend/benefit/helsinkibenefit/urls.py index 5731ad3e1a..ff8a7c8f1f 100644 --- a/backend/benefit/helsinkibenefit/urls.py +++ b/backend/benefit/helsinkibenefit/urls.py @@ -12,7 +12,7 @@ from rest_framework_nested import routers from applications.api.v1 import application_batch_views, views as application_views -from applications.api.v1.review_state_views import ReviewStateViewSet +from applications.api.v1.review_state_views import ReviewStateView from calculator.api.v1 import views as calculator_views from common.debug_util import debug_env from companies.api.v1.views import ( @@ -70,7 +70,9 @@ path("v1/company/search//", SearchOrganisationsView.as_view()), path("v1/company/get//", GetOrganisationByIdView.as_view()), path("v1/users/me/", CurrentUserView.as_view()), - path("v1/handlerapplications//review/", ReviewStateViewSet.as_view()), + path( + "v1/handlerapplications//review/", ReviewStateView.as_view() + ), path("oidc/", include("shared.oidc.urls")), path("oauth2/", include("shared.azure_adfs.urls")), path("api-auth/", include("rest_framework.urls", namespace="rest_framework")), From 30b350116e48e383e479e56d1ece5b1150218018 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Mon, 31 Jul 2023 11:43:44 +0300 Subject: [PATCH 15/82] feat: expose is_staff attribute for user API --- backend/benefit/users/api/v1/serializers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/benefit/users/api/v1/serializers.py b/backend/benefit/users/api/v1/serializers.py index 28efb82dee..762a115fb7 100644 --- a/backend/benefit/users/api/v1/serializers.py +++ b/backend/benefit/users/api/v1/serializers.py @@ -26,6 +26,7 @@ class Meta: "terms_of_service_approvals", "terms_of_service_approval_needed", "terms_of_service_in_effect", + "is_staff", ] read_only_fields = [ "id", @@ -34,6 +35,7 @@ class Meta: "terms_of_service_approvals", "terms_of_service_approval_needed", "terms_of_service_in_effect", + "is_staff", ] terms_of_service_in_effect = serializers.SerializerMethodField( From e96b7e9eefa255b6856afbfce1aa3e072881b835 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Mon, 31 Jul 2023 11:46:52 +0300 Subject: [PATCH 16/82] feat: add is_staff property to user type --- frontend/shared/src/types/user.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/shared/src/types/user.d.ts b/frontend/shared/src/types/user.d.ts index d72931a874..3b331ada1b 100644 --- a/frontend/shared/src/types/user.d.ts +++ b/frontend/shared/src/types/user.d.ts @@ -5,5 +5,6 @@ type User = { family_name: string; name: string; organization_name?: string; + is_staff?: boolean; }; export default User; From 4a84f92ed1c20870094ebd288a1f6f59d0db1caa Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Mon, 31 Jul 2023 11:47:52 +0300 Subject: [PATCH 17/82] feat: users without permissions will be logged out --- .../benefit/handler/src/auth/AuthProvider.tsx | 4 +-- .../benefit/handler/src/hooks/useUserQuery.ts | 28 ++++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/frontend/benefit/handler/src/auth/AuthProvider.tsx b/frontend/benefit/handler/src/auth/AuthProvider.tsx index 14583505e9..103a2b400b 100644 --- a/frontend/benefit/handler/src/auth/AuthProvider.tsx +++ b/frontend/benefit/handler/src/auth/AuthProvider.tsx @@ -5,11 +5,11 @@ import AuthContext from 'shared/auth/AuthContext'; const AuthProvider = ({ children, }: React.PropsWithChildren

): JSX.Element => { - const userQuery = useUserQuery((user) => Boolean(user)); + const userQuery = useUserQuery((user) => user); return ( ( +const useUserQuery = ( select?: (user: User) => T -): UseQueryResult => { +): UseQueryResult => { const router = useRouter(); const locale = useLocale(); + const noPermissionLogout = useLogout(); + // Don't fetch user state if status is logged out const logout = - (router.route === '/login' || router.route === `${locale}/login`) && + (router.route === ROUTES.LOGIN || + router.route === `${locale}${ROUTES.LOGIN}`) && (router.asPath.includes('logout=true') || router.asPath.includes('userStateError=true')); const { axios, handleResponse } = useBackendAPI(); - const handleError = (error: Error): void => { + const handleError = (error: AxiosError): void => { if (logout) { - void router.push(`${locale}/login?logout=true`); + void router.push(`${locale}${ROUTES.LOGIN}?logout=true`); } else if (/40[13]/.test(error.message)) { - void router.push(`${locale}/login`); + void router.push(`${locale}${ROUTES.LOGIN}`); } else if ( !process.env.NEXT_PUBLIC_MOCK_FLAG || process.env.NEXT_PUBLIC_MOCK_FLAG === '0' ) { - void router.push(`${locale}/login?userStateError=true`); + void router.push(`${locale}${ROUTES.LOGIN}?userStateError=true`); + } + }; + + const checkForStaffStatus = (user: User): void => { + if (user && !user.is_staff) { + void noPermissionLogout(); } }; @@ -41,6 +54,7 @@ const useUserQuery = ( enabled: !logout, retry: false, select, + onSuccess: checkForStaffStatus, onError: (error) => handleError(error), } ); From 5cfb28c01cc32d690dd42d6b9eaccd919be9a9ff Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Tue, 1 Aug 2023 13:32:18 +0300 Subject: [PATCH 18/82] fix: hide certain actions when app is archived or in a batch --- .../HandlingApplicationActions.tsx | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/frontend/benefit/handler/src/components/applicationReview/actions/handlingApplicationActions/HandlingApplicationActions.tsx b/frontend/benefit/handler/src/components/applicationReview/actions/handlingApplicationActions/HandlingApplicationActions.tsx index 964edece1d..adfc291336 100644 --- a/frontend/benefit/handler/src/components/applicationReview/actions/handlingApplicationActions/HandlingApplicationActions.tsx +++ b/frontend/benefit/handler/src/components/applicationReview/actions/handlingApplicationActions/HandlingApplicationActions.tsx @@ -63,18 +63,21 @@ const HandlingApplicationActions: React.FC = ({ }` )} - {(application.status === APPLICATION_STATUSES.ACCEPTED || - application.status === APPLICATION_STATUSES.REJECTED) && ( - - )} + {[ + APPLICATION_STATUSES.ACCEPTED, + APPLICATION_STATUSES.REJECTED, + ].includes(application.status) && + !application.batch && + !application.archived && ( + + )} - {application.status !== APPLICATION_STATUSES.CANCELLED && ( - <$Column> - - - )} + {application.status !== APPLICATION_STATUSES.CANCELLED && + !application.batch && + !application.archived && ( + <$Column> + + + )} {isConfirmationModalOpen && ( Date: Wed, 2 Aug 2023 15:02:57 +0300 Subject: [PATCH 19/82] fix: allow two decimals for working hours There might be a scenario where a person works for say, 20 hours and 15 minutes. Previously it was impossible to input such value --- .../0036_alter_employee_working_hours.py | 21 +++++++++++++++++++ backend/benefit/applications/models.py | 4 ++-- .../handler/public/locales/en/common.json | 3 ++- .../handler/public/locales/fi/common.json | 3 ++- .../handler/public/locales/sv/common.json | 3 ++- .../newApplication/utils/validation.ts | 6 ++++++ frontend/benefit/shared/src/constants.ts | 1 + 7 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 backend/benefit/applications/migrations/0036_alter_employee_working_hours.py diff --git a/backend/benefit/applications/migrations/0036_alter_employee_working_hours.py b/backend/benefit/applications/migrations/0036_alter_employee_working_hours.py new file mode 100644 index 0000000000..4d16ce4848 --- /dev/null +++ b/backend/benefit/applications/migrations/0036_alter_employee_working_hours.py @@ -0,0 +1,21 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("applications", "0035_alter_applicationbatch_handler"), + ] + + operations = [ + migrations.AlterField( + model_name="employee", + name="working_hours", + field=models.DecimalField( + blank=True, + decimal_places=2, + max_digits=5, + null=True, + verbose_name="working hour", + ), + ), + ] diff --git a/backend/benefit/applications/models.py b/backend/benefit/applications/models.py index 6aa2f676c2..0430168a06 100755 --- a/backend/benefit/applications/models.py +++ b/backend/benefit/applications/models.py @@ -753,8 +753,8 @@ class Employee(UUIDModel, TimeStampedModel): ) working_hours = models.DecimalField( verbose_name=_("working hour"), - decimal_places=1, - max_digits=4, + decimal_places=2, + max_digits=5, blank=True, null=True, ) diff --git a/frontend/benefit/handler/public/locales/en/common.json b/frontend/benefit/handler/public/locales/en/common.json index b47a8cec5b..d43a85eddb 100644 --- a/frontend/benefit/handler/public/locales/en/common.json +++ b/frontend/benefit/handler/public/locales/en/common.json @@ -822,7 +822,8 @@ "number": { "invalid": "Virheellinen arvo, ilmoita vain numeroita", "max": "Arvon tulee olla enintään {{max}}", - "min": "Arvon tulee olla vähintään {{min}}" + "min": "Arvon tulee olla vähintään {{min}}", + "twoDecimals": "Arvon tulee sisältää enintään kaksi desimaalia" }, "string": { "max": "Tämä kenttä voi olla korkeintaan {{max}} merkkiä pitkä", diff --git a/frontend/benefit/handler/public/locales/fi/common.json b/frontend/benefit/handler/public/locales/fi/common.json index bd6c33c15d..39d39319a2 100644 --- a/frontend/benefit/handler/public/locales/fi/common.json +++ b/frontend/benefit/handler/public/locales/fi/common.json @@ -822,7 +822,8 @@ "number": { "invalid": "Virheellinen arvo, ilmoita vain numeroita", "max": "Arvon tulee olla enintään {{max}}", - "min": "Arvon tulee olla vähintään {{min}}" + "min": "Arvon tulee olla vähintään {{min}}", + "twoDecimals": "Arvon tulee sisältää enintään kaksi desimaalia" }, "string": { "max": "Tämä kenttä voi olla korkeintaan {{max}} merkkiä pitkä", diff --git a/frontend/benefit/handler/public/locales/sv/common.json b/frontend/benefit/handler/public/locales/sv/common.json index e9b9b86d4c..5544491483 100644 --- a/frontend/benefit/handler/public/locales/sv/common.json +++ b/frontend/benefit/handler/public/locales/sv/common.json @@ -828,7 +828,8 @@ "number": { "invalid": "Virheellinen arvo, ilmoita vain numeroita", "max": "Arvon tulee olla enintään {{max}}", - "min": "Arvon tulee olla vähintään {{min}}" + "min": "Arvon tulee olla vähintään {{min}}", + "twoDecimals": "Arvon tulee sisältää enintään kaksi desimaalia" }, "string": { "max": "Tämä kenttä voi olla korkeintaan {{max}} merkkiä pitkä", diff --git a/frontend/benefit/handler/src/components/newApplication/utils/validation.ts b/frontend/benefit/handler/src/components/newApplication/utils/validation.ts index 829cfc6ab3..afff0b3cca 100644 --- a/frontend/benefit/handler/src/components/newApplication/utils/validation.ts +++ b/frontend/benefit/handler/src/components/newApplication/utils/validation.ts @@ -297,6 +297,12 @@ export const getValidationSchema = ( .nullable() .required(t(VALIDATION_MESSAGE_KEYS.REQUIRED)), [EMPLOYEE_KEYS.WORKING_HOURS]: Yup.number() + .test( + 'is-decimal', + t(VALIDATION_MESSAGE_KEYS.NUMBER_TWO_DECIMALS), + (value: number): boolean => + value ? /^\d+.?\d{1,2}$/.test(String(value)) : false + ) .transform((_value, originalValue) => Number(getNumberValue(originalValue)) ) diff --git a/frontend/benefit/shared/src/constants.ts b/frontend/benefit/shared/src/constants.ts index 9bd6c70c2b..5f418bb468 100644 --- a/frontend/benefit/shared/src/constants.ts +++ b/frontend/benefit/shared/src/constants.ts @@ -17,6 +17,7 @@ export enum VALIDATION_MESSAGE_KEYS { NUMBER_INVALID = 'common:form.validation.number.invalid', NUMBER_MIN = 'common:form.validation.number.min', NUMBER_MAX = 'common:form.validation.number.max', + NUMBER_TWO_DECIMALS = 'common:form.validation.number.twoDecimals', PHONE_INVALID = 'common:form.validation.phone.invalid', STRING_POSITIVENUMBER = 'common:form.validation.string.positiveNumber', STRING_MIN = 'common:form.validation.string.min', From aa2c14c7d20862ad03183646956ac77483ff6562 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Tue, 8 Aug 2023 15:11:48 +0300 Subject: [PATCH 20/82] feat: add possibility to have chat in sms styled layout --- frontend/shared/src/components/messaging/Message.tsx | 8 ++++++-- .../shared/src/components/messaging/Messaging.sc.tsx | 11 ++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/frontend/shared/src/components/messaging/Message.tsx b/frontend/shared/src/components/messaging/Message.tsx index cb8d052118..c2c11c0062 100644 --- a/frontend/shared/src/components/messaging/Message.tsx +++ b/frontend/shared/src/components/messaging/Message.tsx @@ -15,6 +15,8 @@ export interface MessageProps { date: string; text: string; isPrimary?: boolean; + alignRight?: boolean; + wrapAsColumn?: boolean; variant: MessageVariant; } @@ -24,13 +26,15 @@ const Message: React.FC = ({ text, isPrimary, variant, + alignRight, + wrapAsColumn, }) => ( <$MessageContainer> - <$Meta> + <$Meta alignRight={alignRight} wrapAsColumn={wrapAsColumn}> <$Sender>{sender} <$Date>{date} - <$Message isPrimary={isPrimary} variant={variant}> + <$Message isPrimary={isPrimary} variant={variant} alignRight={alignRight}> {text} {variant === 'note' && <$Hr />} diff --git a/frontend/shared/src/components/messaging/Messaging.sc.tsx b/frontend/shared/src/components/messaging/Messaging.sc.tsx index 3798d0b227..74e66ef902 100644 --- a/frontend/shared/src/components/messaging/Messaging.sc.tsx +++ b/frontend/shared/src/components/messaging/Messaging.sc.tsx @@ -3,9 +3,15 @@ import styled from 'styled-components'; interface MessageProps { isPrimary?: boolean; + alignRight?: boolean; variant: MessageVariant; } +interface MetaProps { + wrapAsColumn?: boolean; + alignRight?: boolean; +} + interface MessageListProps { variant: MessageVariant; } @@ -23,11 +29,13 @@ export const $MessagesList = styled.div` padding: ${({ theme }) => theme.spacing.xs}; `; -export const $Meta = styled.div` +export const $Meta = styled.div` width: 100%; display: flex; justify-content: space-between; margin-top: ${({ theme }) => theme.spacing.s}; + flex-flow: ${(props) => (props.wrapAsColumn ? 'column' : 'row')}; + text-align: ${(props) => (props.alignRight ? 'right' : 'left')}; `; export const $Sender = styled.span` @@ -56,6 +64,7 @@ export const $Message = styled.div` margin-top: ${(props) => props.variant !== 'note' && props.theme.spacing.s}; color: ${(props) => props.theme.colors.black90}; white-space: pre-line; + margin-left: ${(props) => (props.alignRight ? 'auto' : '0')}; `; export const $Actions = styled.div` From c0ba913db40cea2d59235b819a8ce07a418ea5b9 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Tue, 8 Aug 2023 15:12:34 +0300 Subject: [PATCH 21/82] feat: use sms style layout for chats in applicant and handler --- .../benefit/applicant/src/components/messenger/Messages.tsx | 2 ++ frontend/benefit/handler/src/components/messenger/Messages.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/frontend/benefit/applicant/src/components/messenger/Messages.tsx b/frontend/benefit/applicant/src/components/messenger/Messages.tsx index 488a367495..97a255236e 100644 --- a/frontend/benefit/applicant/src/components/messenger/Messages.tsx +++ b/frontend/benefit/applicant/src/components/messenger/Messages.tsx @@ -38,6 +38,8 @@ const Messages: React.FC = ({ data, variant, withScroll }) => { date={message.modifiedAt || ''} text={message.content} isPrimary={message.messageType === MESSAGE_TYPES.APPLICANT_MESSAGE} + wrapAsColumn + alignRight={message.messageType === MESSAGE_TYPES.APPLICANT_MESSAGE} variant={variant} /> ))} diff --git a/frontend/benefit/handler/src/components/messenger/Messages.tsx b/frontend/benefit/handler/src/components/messenger/Messages.tsx index 5bd8ee13c8..b4a91c8bd6 100644 --- a/frontend/benefit/handler/src/components/messenger/Messages.tsx +++ b/frontend/benefit/handler/src/components/messenger/Messages.tsx @@ -39,6 +39,8 @@ const Messages: React.FC = ({ data, variant, withScroll }) => { text={message.content} isPrimary={message.messageType === MESSAGE_TYPES.HANDLER_MESSAGE} variant={variant} + alignRight={message.messageType === MESSAGE_TYPES.HANDLER_MESSAGE} + wrapAsColumn /> ))} {data.length === 0 && ( From 59d253fc0406b3d11d8f9a826ff6e20939b96502 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Tue, 8 Aug 2023 15:13:21 +0300 Subject: [PATCH 22/82] fix: add missing messenger translations --- frontend/benefit/handler/public/locales/en/common.json | 5 +++++ frontend/benefit/handler/public/locales/fi/common.json | 5 +++++ frontend/benefit/handler/public/locales/sv/common.json | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/frontend/benefit/handler/public/locales/en/common.json b/frontend/benefit/handler/public/locales/en/common.json index 487d9beb95..186caa8eba 100644 --- a/frontend/benefit/handler/public/locales/en/common.json +++ b/frontend/benefit/handler/public/locales/en/common.json @@ -32,6 +32,11 @@ } } }, + "titles": { + "applicantMessage": "Hakija", + "handlerMessage": "Käsittelijä", + "note": "" + }, "showEveryone": "Nämä viestit näkyvät hakijalle", "showToHanlderOnly": "Näkyy vain käsittelijöille", "compose": "Kirjoita viesti", diff --git a/frontend/benefit/handler/public/locales/fi/common.json b/frontend/benefit/handler/public/locales/fi/common.json index af510b57d3..0f62664773 100644 --- a/frontend/benefit/handler/public/locales/fi/common.json +++ b/frontend/benefit/handler/public/locales/fi/common.json @@ -32,6 +32,11 @@ } } }, + "titles": { + "applicantMessage": "Hakija", + "handlerMessage": "Käsittelijä", + "note": "" + }, "showEveryone": "Nämä viestit näkyvät hakijalle", "showToHanlderOnly": "Näkyy vain käsittelijöille", "compose": "Kirjoita viesti", diff --git a/frontend/benefit/handler/public/locales/sv/common.json b/frontend/benefit/handler/public/locales/sv/common.json index 07d47919da..2368a7cfd1 100644 --- a/frontend/benefit/handler/public/locales/sv/common.json +++ b/frontend/benefit/handler/public/locales/sv/common.json @@ -32,6 +32,11 @@ } } }, + "titles": { + "applicantMessage": "Hakija", + "handlerMessage": "Käsittelijä", + "note": "" + }, "showEveryone": "Nämä viestit näkyvät hakijalle", "showToHanlderOnly": "Näkyy vain käsittelijöille", "compose": "Kirjoita viesti", From f37d0dbc0da9571d9ddb15e0f42f3c487c6b63d9 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Thu, 10 Aug 2023 12:04:02 +0300 Subject: [PATCH 23/82] add translations for isUnfinishedDeminimisAid --- frontend/benefit/applicant/public/locales/en/common.json | 4 ++++ frontend/benefit/applicant/public/locales/fi/common.json | 4 ++++ frontend/benefit/applicant/public/locales/sv/common.json | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/frontend/benefit/applicant/public/locales/en/common.json b/frontend/benefit/applicant/public/locales/en/common.json index 6b3ce28ee3..d25fd345ba 100644 --- a/frontend/benefit/applicant/public/locales/en/common.json +++ b/frontend/benefit/applicant/public/locales/en/common.json @@ -86,6 +86,10 @@ "deMinimisAidMaxAmount": { "label": "Maximum amount exceeded", "content": "The maximum amount of de minimis aid has been exceeded. Under the EU Regulation, a company may receive a maximum EUR 200,000 of de minimis aid during the current year and the previous two tax years. All forms of de minimis aid granted by various authorities during this period will be taken into account in the maximum amount." + }, + "deMinimisUnfinished": { + "label": "Missing de minimis aid information", + "content": "Please fill any missing de minimis aid information and press 'Add' button." } }, "tooltips": { diff --git a/frontend/benefit/applicant/public/locales/fi/common.json b/frontend/benefit/applicant/public/locales/fi/common.json index 7020b7519b..b8b2217029 100644 --- a/frontend/benefit/applicant/public/locales/fi/common.json +++ b/frontend/benefit/applicant/public/locales/fi/common.json @@ -86,6 +86,10 @@ "deMinimisAidMaxAmount": { "label": "Enimmäismäärä ylitetty", "content": "De minimis-tuen enimmäismäärä on ylitetty. Tuki voi olla enintään 200 000 euroa, joka myönnetään yritykselle kuluvan vuoden ja kahden edellisen verovuoden kuluessa. Enimmäismäärässä huomioidaan kaikkien eri viranomaisten kyseisenä ajanjaksona de minimis -tukena myöntämä rahoitus." + }, + "deMinimisUnfinished": { + "label": "Puuttuvia de minimis-tuen tietoja", + "content": "Täytä puuttuvat de minimis -kentät ja paina 'Lisää' painiketta." } }, "tooltips": { diff --git a/frontend/benefit/applicant/public/locales/sv/common.json b/frontend/benefit/applicant/public/locales/sv/common.json index ac3f6fcb2c..0e9dc248b3 100644 --- a/frontend/benefit/applicant/public/locales/sv/common.json +++ b/frontend/benefit/applicant/public/locales/sv/common.json @@ -86,6 +86,10 @@ "deMinimisAidMaxAmount": { "label": "Maximibeloppet har överskridits", "content": "Maximibeloppet för de minimis-stöd har överskridits. Enligt EU:s förordning kan ett företag få de minimis-stöd till ett belopp om högst 200 000 euro under det innevarandet året och under de två föregående skatteåren. I maximibeloppet beaktas samtliga de minimis-stöd som olika myndigheter har beviljat under denna tidsperiod." + }, + "deMinimisUnfinished": { + "label": "Information saknar om de minimis stöd", + "content": "Vänligen fyll i eventuell saknad de minimis-stöd information och tryck på knappen 'Lägg till'." } }, "tooltips": { From e3f9e0d8d64731107ff649a7a071d2cee7edb51c Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Thu, 10 Aug 2023 14:21:46 +0300 Subject: [PATCH 24/82] disable eslint that nags of @ts-ignore --- frontend/tet/admin/src/components/editor/DateInput.tsx | 5 +++++ frontend/tet/admin/src/components/editor/Editor.tsx | 1 + frontend/tet/admin/src/components/editor/HiddenIdInput.tsx | 1 + frontend/tet/admin/src/components/editor/SelectionGroup.tsx | 1 + frontend/tet/admin/src/components/editor/TextArea.tsx | 5 +++++ frontend/tet/admin/src/components/editor/TextInput.tsx | 5 +++++ 6 files changed, 18 insertions(+) diff --git a/frontend/tet/admin/src/components/editor/DateInput.tsx b/frontend/tet/admin/src/components/editor/DateInput.tsx index bb7703b7d4..ca89c6d12d 100644 --- a/frontend/tet/admin/src/components/editor/DateInput.tsx +++ b/frontend/tet/admin/src/components/editor/DateInput.tsx @@ -6,7 +6,12 @@ import { Language } from 'shared/i18n/i18n'; import Id from 'shared/types/id'; import TetPosting from 'tet-shared/types/tetposting'; +// Known issue with react-hook-form library, errors out with: +// Type of property 'prototype' circularly references itself in mapped type '{ [K in keyof Blob]-?: PathImpl; }'. +// More at: https://github.com/orgs/react-hook-form/discussions/7764 type Props = { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore id: Id; label: string; registerOptions?: RegisterOptions; diff --git a/frontend/tet/admin/src/components/editor/Editor.tsx b/frontend/tet/admin/src/components/editor/Editor.tsx index db1197d655..cb8dfa3cd1 100644 --- a/frontend/tet/admin/src/components/editor/Editor.tsx +++ b/frontend/tet/admin/src/components/editor/Editor.tsx @@ -27,6 +27,7 @@ export type EditorSectionProps = { // Type of property 'prototype' circularly references itself in mapped type '{ [K in keyof Blob]-?: PathImpl; }'. // More at: https://github.com/orgs/react-hook-form/discussions/7764 +// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const RenderHiddenIdInput = (id: string, value: string): JSXElement => ; diff --git a/frontend/tet/admin/src/components/editor/HiddenIdInput.tsx b/frontend/tet/admin/src/components/editor/HiddenIdInput.tsx index 2dd763e7a7..bfae1707fa 100644 --- a/frontend/tet/admin/src/components/editor/HiddenIdInput.tsx +++ b/frontend/tet/admin/src/components/editor/HiddenIdInput.tsx @@ -7,6 +7,7 @@ import TetPosting from 'tet-shared/types/tetposting'; // Type of property 'prototype' circularly references itself in mapped type '{ [K in keyof Blob]-?: PathImpl; }'. // More at: https://github.com/orgs/react-hook-form/discussions/7764 +// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const HiddenIdInput: React.FC> = ({ id, initialValue }) => { const { register } = useFormContext(); diff --git a/frontend/tet/admin/src/components/editor/SelectionGroup.tsx b/frontend/tet/admin/src/components/editor/SelectionGroup.tsx index 1284a744e1..60663bd276 100644 --- a/frontend/tet/admin/src/components/editor/SelectionGroup.tsx +++ b/frontend/tet/admin/src/components/editor/SelectionGroup.tsx @@ -38,6 +38,7 @@ const SelectionGroup: React.FC = ({ fieldId, label, options, required, ru // Type of property 'prototype' circularly references itself in mapped type '{ [K in keyof Blob]-?: PathImpl; }'. // More at: https://github.com/orgs/react-hook-form/discussions/7764 + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore ; }'. +// More at: https://github.com/orgs/react-hook-form/discussions/7764 type Props = { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore id: Id; testId?: string; label: string; diff --git a/frontend/tet/admin/src/components/editor/TextInput.tsx b/frontend/tet/admin/src/components/editor/TextInput.tsx index 50172eaac0..8c974ccfc6 100644 --- a/frontend/tet/admin/src/components/editor/TextInput.tsx +++ b/frontend/tet/admin/src/components/editor/TextInput.tsx @@ -4,7 +4,12 @@ import { Controller, RegisterOptions, useFormContext } from 'react-hook-form'; import Id from 'shared/types/id'; import TetPosting from 'tet-shared/types/tetposting'; +// Known issue with react-hook-form library, errors out with: +// Type of property 'prototype' circularly references itself in mapped type '{ [K in keyof Blob]-?: PathImpl; }'. +// More at: https://github.com/orgs/react-hook-form/discussions/7764 type Props = { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore id: Id; label: string; placeholder: string; From d85001bced1aac0232356c8b7e21c2dbea39da61 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Fri, 4 Aug 2023 11:01:56 +0300 Subject: [PATCH 25/82] feat: p2p/ahjo inspection inputs are shown based on radio selection --- .../BatchActionsInspectionForm.tsx | 116 +++++++++++++----- 1 file changed, 86 insertions(+), 30 deletions(-) diff --git a/frontend/benefit/handler/src/components/batchProcessing/BatchActionsInspectionForm.tsx b/frontend/benefit/handler/src/components/batchProcessing/BatchActionsInspectionForm.tsx index 5c9f06d3cc..4338db5df9 100644 --- a/frontend/benefit/handler/src/components/batchProcessing/BatchActionsInspectionForm.tsx +++ b/frontend/benefit/handler/src/components/batchProcessing/BatchActionsInspectionForm.tsx @@ -5,10 +5,16 @@ import { PROPOSALS_FOR_DECISION, } from 'benefit-shared/constants'; import { BatchProposal } from 'benefit-shared/types/application'; -import { Button, DateInput, IconArrowUndo, TextInput } from 'hds-react'; +import { + Button, + DateInput, + IconArrowUndo, + RadioButton, + TextInput, +} from 'hds-react'; import noop from 'lodash/noop'; import { useTranslation } from 'next-i18next'; -import React from 'react'; +import React, { ChangeEvent } from 'react'; import { $GridCell } from 'shared/components/forms/section/FormSection.sc'; import Modal from 'shared/components/modal/Modal'; @@ -33,7 +39,8 @@ const BatchActionsInspectionForm: React.FC = ({ isInspectionFormSent, setInspectionFormSent, setBatchCloseAnimation, -}: BatchProps) => { +}: // eslint-disable-next-line sonarjs/cognitive-complexity +BatchProps) => { const { id, proposal_for_decision: proposalForDecision } = batch; const { t } = useTranslation(); const { formik, yearFromNow, isSuccess, isError } = useBatchActionsInspected( @@ -46,6 +53,8 @@ const BatchActionsInspectionForm: React.FC = ({ const [isModalBatchToCompletion, setModalBatchToCompletion] = React.useState(false); + const [inspectorMode, setInspectorMode] = React.useState('ahjo'); + React.useEffect(() => { if (isError) { setInspectionFormSent(false); @@ -82,6 +91,10 @@ const BatchActionsInspectionForm: React.FC = ({ return false; }); + const handleRadioButton = (event: ChangeEvent): void => { + setInspectorMode(event.target.value); + }; + const handleSubmit = (e: React.FormEvent): void => { e.preventDefault(); formik @@ -118,6 +131,33 @@ const BatchActionsInspectionForm: React.FC = ({ return ( <> + {proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED ? ( + <$FormSection> + <$GridCell $colSpan={2}> + + + <$GridCell $colSpan={2}> + + + + ) : null} + = ({ - <$FormSection> - <$GridCell $colSpan={3}> - - + {proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED && + inspectorMode === 'ahjo' ? ( + <$FormSection> + <$GridCell $colSpan={3}> + + - <$GridCell $colSpan={3}> - - - + <$GridCell $colSpan={3}> + + + <$GridCell $colSpan={3}> + + + + ) : null} - {proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED ? ( + {proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED && + inspectorMode === 'p2p' ? ( <$FormSection css="border-top: 1pox solid #000;"> <$GridCell $colSpan={3}> Date: Mon, 7 Aug 2023 15:37:09 +0300 Subject: [PATCH 26/82] refactor: make batch inspector mode selection prettier --- .../handler/public/locales/en/common.json | 4 + .../handler/public/locales/fi/common.json | 4 + .../handler/public/locales/sv/common.json | 4 + .../BatchActionsInspectionForm.tsx | 231 +++++++++--------- .../batchProcessing/BatchApplicationList.tsx | 11 +- .../useBatchActionsInspected.ts | 61 +++-- .../components/table/BatchCompletion.sc.ts | 20 ++ .../src/components/table/TableExtras.sc.ts | 9 +- 8 files changed, 215 insertions(+), 129 deletions(-) create mode 100644 frontend/benefit/handler/src/components/table/BatchCompletion.sc.ts diff --git a/frontend/benefit/handler/public/locales/en/common.json b/frontend/benefit/handler/public/locales/en/common.json index 4fbbd11f9f..3278727613 100644 --- a/frontend/benefit/handler/public/locales/en/common.json +++ b/frontend/benefit/handler/public/locales/en/common.json @@ -1018,6 +1018,10 @@ "p2pInspectorEmail": "Tarkastajan sähköposti, P2P", "p2pCheckerName": "Hyväksyjän nimi, P2P" }, + "headings": { + "decisionDetails": "Päätöksen tiedot", + "inspectionDetails": "Tarkastuksen tiedot" + }, "errors": { "decision_maker_name": "Pakollinen tieto", "decision_maker_title": "Pakollinen tieto", diff --git a/frontend/benefit/handler/public/locales/fi/common.json b/frontend/benefit/handler/public/locales/fi/common.json index 7671de54d6..29b9864b7e 100644 --- a/frontend/benefit/handler/public/locales/fi/common.json +++ b/frontend/benefit/handler/public/locales/fi/common.json @@ -1018,6 +1018,10 @@ "p2pInspectorEmail": "Tarkastajan sähköposti, P2P", "p2pCheckerName": "Hyväksyjän nimi, P2P" }, + "headings": { + "decisionDetails": "Päätöksen tiedot", + "inspectionDetails": "Tarkastuksen tiedot" + }, "errors": { "decision_maker_name": "Pakollinen tieto", "decision_maker_title": "Pakollinen tieto", diff --git a/frontend/benefit/handler/public/locales/sv/common.json b/frontend/benefit/handler/public/locales/sv/common.json index b5e351409c..d453a840f2 100644 --- a/frontend/benefit/handler/public/locales/sv/common.json +++ b/frontend/benefit/handler/public/locales/sv/common.json @@ -1024,6 +1024,10 @@ "p2pInspectorEmail": "Tarkastajan sähköposti, P2P", "p2pCheckerName": "Hyväksyjän nimi, P2P" }, + "headings": { + "decisionDetails": "Päätöksen tiedot", + "inspectionDetails": "Tarkastuksen tiedot" + }, "errors": { "decision_maker_name": "Pakollinen tieto", "decision_maker_title": "Pakollinen tieto", diff --git a/frontend/benefit/handler/src/components/batchProcessing/BatchActionsInspectionForm.tsx b/frontend/benefit/handler/src/components/batchProcessing/BatchActionsInspectionForm.tsx index 4338db5df9..d71b46dab4 100644 --- a/frontend/benefit/handler/src/components/batchProcessing/BatchActionsInspectionForm.tsx +++ b/frontend/benefit/handler/src/components/batchProcessing/BatchActionsInspectionForm.tsx @@ -19,6 +19,7 @@ import { $GridCell } from 'shared/components/forms/section/FormSection.sc'; import Modal from 'shared/components/modal/Modal'; import ConfirmModalContent from '../applicationReview/actions/ConfirmModalContent/confirm'; +import { $InspectionTypeContainer } from '../table/BatchCompletion.sc'; import { $FormSection } from '../table/TableExtras.sc'; import { useBatchActionsInspected } from './useBatchActionsInspected'; @@ -93,6 +94,7 @@ BatchProps) => { const handleRadioButton = (event: ChangeEvent): void => { setInspectorMode(event.target.value); + formik.handleChange(event); }; const handleSubmit = (e: React.FormEvent): void => { @@ -131,33 +133,6 @@ BatchProps) => { return ( <> - {proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED ? ( - <$FormSection> - <$GridCell $colSpan={2}> - - - <$GridCell $colSpan={2}> - - - - ) : null} - { } /> +

{t('common:batches.form.headings.decisionDetails')}

<$FormSection> <$GridCell $colSpan={3}> { - {proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED && - inspectorMode === 'ahjo' ? ( - <$FormSection> - <$GridCell $colSpan={3}> - - + {proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED ? ( + <> +

{t('common:batches.form.headings.inspectionDetails')}

+ <$InspectionTypeContainer> + <$FormSection> + <$GridCell $colSpan={2}> + + + - <$GridCell $colSpan={3}> - - - <$GridCell $colSpan={3}> - - - - ) : null} + {inspectorMode === 'ahjo' ? ( + <$FormSection> + <$GridCell $colSpan={3}> + + - {proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED && - inspectorMode === 'p2p' ? ( - <$FormSection css="border-top: 1pox solid #000;"> - <$GridCell $colSpan={3}> - - + <$GridCell $colSpan={3}> + + + <$GridCell $colSpan={3}> + + + + ) : null} + - <$GridCell $colSpan={3}> - - - <$GridCell $colSpan={3}> - - - - ) : null} + <$InspectionTypeContainer> + <$FormSection> + <$GridCell $colSpan={2}> + + + + {inspectorMode === 'p2p' ? ( + <$FormSection css="border-top: 1pox solid #000;"> + <$GridCell $colSpan={3}> + + + <$GridCell $colSpan={3}> + + + <$GridCell $colSpan={3}> + + + + ) : null} + + + ) : null} <$FormSection> <$GridCell $colSpan={3}>