Feat/improve security (#482)
* build(deps): bump org.hibernate.orm.tooling:hibernate-enhance-maven-plugin Bumps [org.hibernate.orm.tooling:hibernate-enhance-maven-plugin](https://github.com/hibernate/hibernate-orm) from 6.6.15.Final to 6.6.16.Final. - [Release notes](https://github.com/hibernate/hibernate-orm/releases) - [Changelog](https://github.com/hibernate/hibernate-orm/blob/6.6.16/changelog.txt) - [Commits](https://github.com/hibernate/hibernate-orm/compare/6.6.15...6.6.16) --- updated-dependencies: - dependency-name: org.hibernate.orm.tooling:hibernate-enhance-maven-plugin dependency-version: 6.6.16.Final dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump com.puppycrawl.tools:checkstyle in /server Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 10.23.1 to 10.24.0. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.23.1...checkstyle-10.24.0) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-version: 10.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump org.springframework.boot:spring-boot-starter-parent Bumps [org.springframework.boot:spring-boot-starter-parent](https://github.com/spring-projects/spring-boot) from 3.4.1 to 3.5.0. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.5.0) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter-parent dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump @vitejs/plugin-react from 4.4.1 to 4.5.0 in /client Bumps [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) from 4.4.1 to 4.5.0. - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@4.5.0/packages/plugin-react) --- updated-dependencies: - dependency-name: "@vitejs/plugin-react" dependency-version: 4.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump react-router from 7.6.0 to 7.6.1 in /client Bumps [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) from 7.6.0 to 7.6.1. - [Release notes](https://github.com/remix-run/react-router/releases) - [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md) - [Commits](https://github.com/remix-run/react-router/commits/react-router@7.6.1/packages/react-router) --- updated-dependencies: - dependency-name: react-router dependency-version: 7.6.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump react-datepicker from 8.3.0 to 8.4.0 in /client Bumps [react-datepicker](https://github.com/Hacker0x01/react-datepicker) from 8.3.0 to 8.4.0. - [Release notes](https://github.com/Hacker0x01/react-datepicker/releases) - [Commits](https://github.com/Hacker0x01/react-datepicker/compare/v8.3.0...v8.4.0) --- updated-dependencies: - dependency-name: react-datepicker dependency-version: 8.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps-dev): bump @stylistic/eslint-plugin in /client Bumps [@stylistic/eslint-plugin](https://github.com/eslint-stylistic/eslint-stylistic/tree/HEAD/packages/eslint-plugin) from 4.2.0 to 4.4.0. - [Release notes](https://github.com/eslint-stylistic/eslint-stylistic/releases) - [Changelog](https://github.com/eslint-stylistic/eslint-stylistic/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint-stylistic/eslint-stylistic/commits/v4.4.0/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@stylistic/eslint-plugin" dependency-version: 4.4.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps-dev): bump globals from 16.1.0 to 16.2.0 in /client Bumps [globals](https://github.com/sindresorhus/globals) from 16.1.0 to 16.2.0. - [Release notes](https://github.com/sindresorhus/globals/releases) - [Commits](https://github.com/sindresorhus/globals/compare/v16.1.0...v16.2.0) --- updated-dependencies: - dependency-name: globals dependency-version: 16.2.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps-dev): bump jasmine-core from 5.6.0 to 5.7.1 in /angular Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 5.6.0 to 5.7.1. - [Release notes](https://github.com/jasmine/jasmine/releases) - [Changelog](https://github.com/jasmine/jasmine/blob/main/RELEASE.md) - [Commits](https://github.com/jasmine/jasmine/compare/v5.6.0...v5.7.1) --- updated-dependencies: - dependency-name: jasmine-core dependency-version: 5.7.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps-dev): bump @angular/cli from 19.2.12 to 19.2.13 in /angular Bumps [@angular/cli](https://github.com/angular/angular-cli) from 19.2.12 to 19.2.13. - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/19.2.12...19.2.13) --- updated-dependencies: - dependency-name: "@angular/cli" dependency-version: 19.2.13 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump @angular/platform-browser-dynamic in /angular Bumps [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) from 19.2.10 to 19.2.13. - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/19.2.13/packages/platform-browser-dynamic) --- updated-dependencies: - dependency-name: "@angular/platform-browser-dynamic" dependency-version: 19.2.13 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump @angular/router from 19.2.10 to 19.2.13 in /angular Bumps [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) from 19.2.10 to 19.2.13. - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/19.2.13/packages/router) --- updated-dependencies: - dependency-name: "@angular/router" dependency-version: 19.2.13 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump @angular/platform-browser in /angular Bumps [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) from 19.2.10 to 19.2.13. - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/19.2.13/packages/platform-browser) --- updated-dependencies: - dependency-name: "@angular/platform-browser" dependency-version: 19.2.13 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * fix: server/Dockerfile to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-DEBIAN12-GCC12-5901316 - https://snyk.io/vuln/SNYK-DEBIAN12-GCC12-5901316 - https://snyk.io/vuln/SNYK-DEBIAN12-GCC12-5901316 - https://snyk.io/vuln/SNYK-DEBIAN12-SHADOW-5879156 - https://snyk.io/vuln/SNYK-DEBIAN12-SHADOW-5879156 * fix: css styles and translations * chore: fix authentication provider * chore: fix line too long * test: update test cases * chore: prefer coalescing operator * chore: prefer nullish coalescing operator --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: snyk-bot <snyk-bot@snyk.io>
This commit is contained in:
committed by
GitHub
co-authored by
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
snyk-bot
parent
a45378685b
commit
fe2803393b
Generated
+163
-43
@@ -12,19 +12,19 @@
|
||||
"@angular/compiler": "^19.2.10",
|
||||
"@angular/core": "^19.2.0",
|
||||
"@angular/forms": "^19.2.10",
|
||||
"@angular/platform-browser": "^19.2.10",
|
||||
"@angular/platform-browser-dynamic": "^19.2.0",
|
||||
"@angular/router": "^19.2.0",
|
||||
"@angular/platform-browser": "^19.2.13",
|
||||
"@angular/platform-browser-dynamic": "^19.2.13",
|
||||
"@angular/router": "^19.2.13",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^19.2.9",
|
||||
"@angular/cli": "^19.2.11",
|
||||
"@angular/cli": "^19.2.13",
|
||||
"@angular/compiler-cli": "^19.2.10",
|
||||
"@types/jasmine": "~5.1.0",
|
||||
"jasmine-core": "~5.6.0",
|
||||
"jasmine-core": "~5.7.1",
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
"karma-coverage": "~2.2.0",
|
||||
@@ -278,13 +278,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@angular-devkit/schematics": {
|
||||
"version": "19.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.12.tgz",
|
||||
"integrity": "sha512-vK5NI/asi1snWFkw02DpmC8tLq6u5ZbUwwXxgALKuVwGl3g1VLzrHrkoSCrcsOO9Nu6GQOPbxax2lR/DICmytg==",
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.13.tgz",
|
||||
"integrity": "sha512-NhSPz3lI9njEo8eMUlZVGtlXl12UcNZv5lWTBZY/FGWUu6P5ciD/9iJINbc1jiaDH5E/DLEicUNuai0Q91X4Nw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": "19.2.12",
|
||||
"@angular-devkit/core": "19.2.13",
|
||||
"jsonc-parser": "3.3.1",
|
||||
"magic-string": "0.30.17",
|
||||
"ora": "5.4.1",
|
||||
@@ -296,6 +296,34 @@
|
||||
"yarn": ">= 1.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": {
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.13.tgz",
|
||||
"integrity": "sha512-iq73hE5Uvms1w3uMUSk4i4NDXDMQ863VAifX8LOTadhG6U0xISjNJ11763egVCxQmaKmg7zbG4rda88wHJATzA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "8.17.1",
|
||||
"ajv-formats": "3.0.1",
|
||||
"jsonc-parser": "3.3.1",
|
||||
"picomatch": "4.0.2",
|
||||
"rxjs": "7.8.1",
|
||||
"source-map": "0.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"chokidar": "^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"chokidar": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@angular-devkit/schematics/node_modules/rxjs": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
@@ -494,18 +522,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/cli": {
|
||||
"version": "19.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.2.12.tgz",
|
||||
"integrity": "sha512-cZkHpM16uh3VouHG1XdWSk0ZWisQRxMVADk5IJlM9jMcPqnFyJwD/UXCS+XTaW3POpNDwsmbh2UB9Xabdgo7rw==",
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.2.13.tgz",
|
||||
"integrity": "sha512-dDRCS73/lrItWx9j4SmwHR56GiZsW8ObNi2q9l/1ny813CG9K43STYFG/wJvGS7ZF3y5hvjIiJOwBx2YIouOIw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular-devkit/architect": "0.1902.12",
|
||||
"@angular-devkit/core": "19.2.12",
|
||||
"@angular-devkit/schematics": "19.2.12",
|
||||
"@angular-devkit/architect": "0.1902.13",
|
||||
"@angular-devkit/core": "19.2.13",
|
||||
"@angular-devkit/schematics": "19.2.13",
|
||||
"@inquirer/prompts": "7.3.2",
|
||||
"@listr2/prompt-adapter-inquirer": "2.0.18",
|
||||
"@schematics/angular": "19.2.12",
|
||||
"@schematics/angular": "19.2.13",
|
||||
"@yarnpkg/lockfile": "1.1.0",
|
||||
"ini": "5.0.0",
|
||||
"jsonc-parser": "3.3.1",
|
||||
@@ -527,6 +555,60 @@
|
||||
"yarn": ">= 1.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/cli/node_modules/@angular-devkit/architect": {
|
||||
"version": "0.1902.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1902.13.tgz",
|
||||
"integrity": "sha512-ZMj+PjK22Ph2U8usG6L7LqEfvWlbaOvmiWXSrEt9YiC9QJt6rsumCkOgUIsmHQtucm/lK+9CMtyYdwH2fYycjg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": "19.2.13",
|
||||
"rxjs": "7.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/cli/node_modules/@angular-devkit/core": {
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.13.tgz",
|
||||
"integrity": "sha512-iq73hE5Uvms1w3uMUSk4i4NDXDMQ863VAifX8LOTadhG6U0xISjNJ11763egVCxQmaKmg7zbG4rda88wHJATzA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "8.17.1",
|
||||
"ajv-formats": "3.0.1",
|
||||
"jsonc-parser": "3.3.1",
|
||||
"picomatch": "4.0.2",
|
||||
"rxjs": "7.8.1",
|
||||
"source-map": "0.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"chokidar": "^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"chokidar": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/cli/node_modules/rxjs": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/common": {
|
||||
"version": "19.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@angular/common/-/common-19.2.10.tgz",
|
||||
@@ -667,9 +749,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/platform-browser": {
|
||||
"version": "19.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.2.10.tgz",
|
||||
"integrity": "sha512-MYX4av0UvCmtUyCo6vW2RjOT2nbZsChhNjKr70DrWcCRMhYYv4cB4PMr6PnyGKJb7QZSSdzbqbbGtvvaB/quqw==",
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.2.13.tgz",
|
||||
"integrity": "sha512-YeuRfGbo8qFepoAUoubk/1079wOown5Qgr9eAhgCXxoXb2rt87xbJF3YCSSim38SP3kK1rJQqP+Sr8n7ef+n5Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
@@ -678,9 +760,9 @@
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/animations": "19.2.10",
|
||||
"@angular/common": "19.2.10",
|
||||
"@angular/core": "19.2.10"
|
||||
"@angular/animations": "19.2.13",
|
||||
"@angular/common": "19.2.13",
|
||||
"@angular/core": "19.2.13"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@angular/animations": {
|
||||
@@ -689,9 +771,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/platform-browser-dynamic": {
|
||||
"version": "19.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.2.10.tgz",
|
||||
"integrity": "sha512-ETyTBTL/Kt17BjTDGXoUJVfjx1ZI0ryg3gvEvvtiMfBcmT/ohiIstYfaoF1QSPVMtbiTRLbCtdE439e4B7YoaQ==",
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.2.13.tgz",
|
||||
"integrity": "sha512-qbIPwnqkqQZ1sK56cbb2k/qtg+BKYicU6aS/YKfRrEfM9zFNyxfSCdKOwL7hogKGZKJulFfFKpi44wJcdW13rg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
@@ -700,16 +782,16 @@
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "19.2.10",
|
||||
"@angular/compiler": "19.2.10",
|
||||
"@angular/core": "19.2.10",
|
||||
"@angular/platform-browser": "19.2.10"
|
||||
"@angular/common": "19.2.13",
|
||||
"@angular/compiler": "19.2.13",
|
||||
"@angular/core": "19.2.13",
|
||||
"@angular/platform-browser": "19.2.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/router": {
|
||||
"version": "19.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@angular/router/-/router-19.2.10.tgz",
|
||||
"integrity": "sha512-bmt3ws3L4pYTlI8FW5L1ShyOeUQobXA7wy6TbcIToEonZk+i8uj3xlTD9Ymnjkb9wbNXrD1qoNSpP86c7C1rWQ==",
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular/router/-/router-19.2.13.tgz",
|
||||
"integrity": "sha512-BZObWQtGkDv2WHyLVRRecGbLwalbI8kOXKaVgN5dqP4z/t5bpzYXZixPO9e0E1Ff0+m4tQalhTc84j8X7XZuTw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
@@ -718,9 +800,9 @@
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "19.2.10",
|
||||
"@angular/core": "19.2.10",
|
||||
"@angular/platform-browser": "19.2.10",
|
||||
"@angular/common": "19.2.13",
|
||||
"@angular/core": "19.2.13",
|
||||
"@angular/platform-browser": "19.2.13",
|
||||
"rxjs": "^6.5.3 || ^7.4.0"
|
||||
}
|
||||
},
|
||||
@@ -4860,14 +4942,14 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@schematics/angular": {
|
||||
"version": "19.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.2.12.tgz",
|
||||
"integrity": "sha512-6S6tclFctLrjMvhpi8eVvswIpXqlybRpZLCTWyVeWIC6PHYLEyFmFoOhuhcSmOdtnwudvzOt6xWnWEVb3qXZbQ==",
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.2.13.tgz",
|
||||
"integrity": "sha512-SOpK4AwH0isXo7Y2SkgXLyGLMw4GxWPAun6sCLiprmop4KlqKGGALn4xIW0yjq0s5GS0Vx0FFjz8bBfPkgnawA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": "19.2.12",
|
||||
"@angular-devkit/schematics": "19.2.12",
|
||||
"@angular-devkit/core": "19.2.13",
|
||||
"@angular-devkit/schematics": "19.2.13",
|
||||
"jsonc-parser": "3.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -4876,6 +4958,44 @@
|
||||
"yarn": ">= 1.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@schematics/angular/node_modules/@angular-devkit/core": {
|
||||
"version": "19.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.13.tgz",
|
||||
"integrity": "sha512-iq73hE5Uvms1w3uMUSk4i4NDXDMQ863VAifX8LOTadhG6U0xISjNJ11763egVCxQmaKmg7zbG4rda88wHJATzA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "8.17.1",
|
||||
"ajv-formats": "3.0.1",
|
||||
"jsonc-parser": "3.3.1",
|
||||
"picomatch": "4.0.2",
|
||||
"rxjs": "7.8.1",
|
||||
"source-map": "0.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"chokidar": "^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"chokidar": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@schematics/angular/node_modules/rxjs": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sigstore/bundle": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.1.0.tgz",
|
||||
@@ -9071,9 +9191,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jasmine-core": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.6.0.tgz",
|
||||
"integrity": "sha512-niVlkeYVRwKFpmfWg6suo6H9CrNnydfBLEqefM5UjibYS+UoTjZdmvPJSiuyrRLGnFj1eYRhFd/ch+5hSlsFVA==",
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.7.1.tgz",
|
||||
"integrity": "sha512-QnurrtpKsPoixxG2R3d1xP0St/2kcX5oTZyDyQJMY+Vzi/HUlu1kGm+2V8Tz+9lV991leB1l0xcsyz40s9xOOw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
||||
@@ -14,19 +14,19 @@
|
||||
"@angular/compiler": "^19.2.10",
|
||||
"@angular/core": "^19.2.0",
|
||||
"@angular/forms": "^19.2.10",
|
||||
"@angular/platform-browser": "^19.2.10",
|
||||
"@angular/platform-browser-dynamic": "^19.2.0",
|
||||
"@angular/router": "^19.2.0",
|
||||
"@angular/platform-browser": "^19.2.13",
|
||||
"@angular/platform-browser-dynamic": "^19.2.13",
|
||||
"@angular/router": "^19.2.13",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^19.2.9",
|
||||
"@angular/cli": "^19.2.11",
|
||||
"@angular/cli": "^19.2.13",
|
||||
"@angular/compiler-cli": "^19.2.10",
|
||||
"@types/jasmine": "~5.1.0",
|
||||
"jasmine-core": "~5.6.0",
|
||||
"jasmine-core": "~5.7.1",
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
"karma-coverage": "~2.2.0",
|
||||
|
||||
Generated
+28
-21
@@ -12,7 +12,7 @@
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@types/node": "^22.15.21",
|
||||
"@types/react-dom": "^19.1.5",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"@vitejs/plugin-react": "^4.5.0",
|
||||
"bootstrap": "^5.3.6",
|
||||
"dompurify": "^3.2.6",
|
||||
"i18next": "^25.2.0",
|
||||
@@ -20,11 +20,11 @@
|
||||
"react-bootstrap": "^2.10.10",
|
||||
"react-bootstrap-icons": "^1.11.6",
|
||||
"react-charts": "^3.0.0-beta.57",
|
||||
"react-datepicker": "^8.3.0",
|
||||
"react-datepicker": "^8.4.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-i18next": "^15.5.2",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-router": "^7.6.0",
|
||||
"react-router": "^7.6.1",
|
||||
"react-router-bootstrap": "^0.26.3",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.3.5"
|
||||
@@ -33,7 +33,7 @@
|
||||
"@eslint/compat": "^1.2.9",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "^9.27.0",
|
||||
"@stylistic/eslint-plugin": "^4.2.0",
|
||||
"@stylistic/eslint-plugin": "^4.4.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
@@ -48,7 +48,7 @@
|
||||
"eslint-plugin-n": "^17.18.0",
|
||||
"eslint-plugin-promise": "^7.2.1",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^16.1.0",
|
||||
"globals": "^16.2.0",
|
||||
"jsdom": "^26.1.0",
|
||||
"prettier": "^3.5.3",
|
||||
"sass": "^1.89.0",
|
||||
@@ -1123,6 +1123,12 @@
|
||||
"react": ">=16.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/pluginutils": {
|
||||
"version": "1.0.0-beta.9",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz",
|
||||
"integrity": "sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz",
|
||||
@@ -1164,13 +1170,13 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.2.0.tgz",
|
||||
"integrity": "sha512-8hXezgz7jexGHdo5WN6JBEIPHCSFyyU4vgbxevu4YLVS5vl+sxqAAGyXSzfNDyR6xMNSH5H1x67nsXcYMOHtZA==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.4.0.tgz",
|
||||
"integrity": "sha512-bIh/d9X+OQLCAMdhHtps+frvyjvAM4B1YlSJzcEEhl7wXLIqPar3ngn9DrHhkBOrTA/z9J0bUMtctAspe0dxdQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/utils": "^8.23.0",
|
||||
"@typescript-eslint/utils": "^8.32.1",
|
||||
"eslint-visitor-keys": "^4.2.0",
|
||||
"espree": "^10.3.0",
|
||||
"estraverse": "^5.3.0",
|
||||
@@ -1867,14 +1873,15 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@vitejs/plugin-react": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz",
|
||||
"integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==",
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.5.0.tgz",
|
||||
"integrity": "sha512-JuLWaEqypaJmOJPLWwO335Ig6jSgC1FTONCWAxnqcQthLTK/Yc9aH6hr9z/87xciejbQcnP3GnA1FWUSWeXaeg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.26.10",
|
||||
"@babel/plugin-transform-react-jsx-self": "^7.25.9",
|
||||
"@babel/plugin-transform-react-jsx-source": "^7.25.9",
|
||||
"@rolldown/pluginutils": "1.0.0-beta.9",
|
||||
"@types/babel__core": "^7.20.5",
|
||||
"react-refresh": "^0.17.0"
|
||||
},
|
||||
@@ -4320,9 +4327,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "16.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
|
||||
"integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz",
|
||||
"integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -7064,9 +7071,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-datepicker": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-8.3.0.tgz",
|
||||
"integrity": "sha512-DhfrIJnTPJTUVRtXU7c7zooug40rD6q+Fc8UTCt19dYEotLpDQgTN98MfocY6Rc4S99oOFFEoxyanOM/TKauuw==",
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-8.4.0.tgz",
|
||||
"integrity": "sha512-6nPDnj8vektWCIOy9ArS3avus9Ndsyz5XgFCJ7nBxXASSpBdSL6lG9jzNNmViPOAOPh6T5oJyGaXuMirBLECag==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "^0.27.3",
|
||||
@@ -7166,9 +7173,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.0.tgz",
|
||||
"integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==",
|
||||
"version": "7.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.1.tgz",
|
||||
"integrity": "sha512-hPJXXxHJZEsPFNVbtATH7+MMX43UDeOauz+EAU4cgqTn7ojdI9qQORqS8Z0qmDlL1TclO/6jLRYUEtbWidtdHQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie": "^1.0.1",
|
||||
|
||||
+5
-5
@@ -15,7 +15,7 @@
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@types/node": "^22.15.21",
|
||||
"@types/react-dom": "^19.1.5",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"@vitejs/plugin-react": "^4.5.0",
|
||||
"bootstrap": "^5.3.6",
|
||||
"dompurify": "^3.2.6",
|
||||
"i18next": "^25.2.0",
|
||||
@@ -23,11 +23,11 @@
|
||||
"react-bootstrap": "^2.10.10",
|
||||
"react-bootstrap-icons": "^1.11.6",
|
||||
"react-charts": "^3.0.0-beta.57",
|
||||
"react-datepicker": "^8.3.0",
|
||||
"react-datepicker": "^8.4.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-i18next": "^15.5.2",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-router": "^7.6.0",
|
||||
"react-router": "^7.6.1",
|
||||
"react-router-bootstrap": "^0.26.3",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.3.5"
|
||||
@@ -63,7 +63,7 @@
|
||||
"@eslint/compat": "^1.2.9",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "^9.27.0",
|
||||
"@stylistic/eslint-plugin": "^4.2.0",
|
||||
"@stylistic/eslint-plugin": "^4.4.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
@@ -78,7 +78,7 @@
|
||||
"eslint-plugin-n": "^17.18.0",
|
||||
"eslint-plugin-promise": "^7.2.1",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^16.1.0",
|
||||
"globals": "^16.2.0",
|
||||
"jsdom": "^26.1.0",
|
||||
"prettier": "^3.5.3",
|
||||
"sass": "^1.89.0",
|
||||
|
||||
@@ -24,12 +24,14 @@ describe('ContentHeader test cases', () => {
|
||||
expect(getByText(headerProps.h2GreenText)).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render all the text elements', () => {
|
||||
it('should render all the text elements for home', () => {
|
||||
const { getByText } = render(
|
||||
<MemoryRouter>
|
||||
<ContentHeader
|
||||
{ ...headerProps }
|
||||
isHomeComponent={true}
|
||||
newTaskI18n="New task"
|
||||
newNoteI18n="New note"
|
||||
/>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
@@ -35,33 +35,25 @@ describe('Portuguese Utils unit tests', () => {
|
||||
it('should translate all server responses to pt_br', () => {
|
||||
const keys: string[] = Object.keys(serverResponses);
|
||||
|
||||
expect(translateServerResponse(keys[0], 'pt_br'))
|
||||
.toBe('Senha fraca: Senha deve possuir pelo menos 8 letras, 1 maiúscula, 1 caracter especial');
|
||||
expect(translateServerResponse(keys[1], 'pt_br'))
|
||||
.toBe('Senha fraca: Senha deve possuir pelo menos 1 maiúscula, 1 caracter especial');
|
||||
expect(translateServerResponse(keys[2], 'pt_br'))
|
||||
.toBe('Senha fraca: Senha deve possuir pelo menos 1 caracter especial');
|
||||
expect(translateServerResponse(keys[3], 'pt_br'))
|
||||
.toBe('E-mail já cadastrado!');
|
||||
expect(translateServerResponse(keys[4], 'pt_br'))
|
||||
.toBe('Proibido! Acesso negado');
|
||||
expect(translateServerResponse(keys[5], 'pt_br'))
|
||||
.toBe('Erro Interno do Servidor!');
|
||||
expect(translateServerResponse(keys[6], 'pt_br'))
|
||||
.toBe('Limite máximo de tentativas atingido. Por favor aguarde 30 minutos');
|
||||
expect(translateServerResponse(keys[7], 'pt_br'))
|
||||
.toBe('Por ravor, preencha todos os campos');
|
||||
expect(translateServerResponse(keys[8], 'pt_br'))
|
||||
.toBe('Por favor, informe seu e-mail e senha!');
|
||||
expect(translateServerResponse(keys[9], 'pt_br'))
|
||||
.toBe('Por favor, digite pelo menos 3 letras');
|
||||
expect(translateServerResponse(keys[10], 'pt_br'))
|
||||
.toBe('O tamanho máximo do texto é 2000');
|
||||
expect(translateServerResponse(keys[11], 'pt_br'))
|
||||
.toBe('Erro desconhecido');
|
||||
expect(translateServerResponse(keys[12], 'pt_br'))
|
||||
.toBe('Informação errada ou incompleta!');
|
||||
expect(translateServerResponse(keys[13], 'pt_br'))
|
||||
.toBe('E-mail ou senha inválidos!');
|
||||
expect(translateServerResponse(keys[0], 'pt_br')).toBe('Senha fraca: Senha deve possuir pelo menos 8 letras, 1 maiúscula, 1 caracter especial');
|
||||
expect(translateServerResponse(keys[1], 'pt_br')).toBe('Senha fraca: Senha deve possuir pelo menos 1 maiúscula, 1 caracter especial');
|
||||
expect(translateServerResponse(keys[2], 'pt_br')).toBe('Senha fraca: Senha deve possuir pelo menos 1 caracter especial');
|
||||
expect(translateServerResponse(keys[3], 'pt_br')).toBe('E-mail já cadastrado!');
|
||||
expect(translateServerResponse(keys[4], 'pt_br')).toBe('Proibido! Acesso negado');
|
||||
expect(translateServerResponse(keys[5], 'pt_br')).toBe('Se o endereço de e-mail informado estiver associado a uma conta, você receberá um link para resetar a senha em breve.');
|
||||
expect(translateServerResponse(keys[6], 'pt_br')).toBe('Erro Interno do Servidor!');
|
||||
expect(translateServerResponse(keys[7], 'pt_br')).toBe('Limite máximo de tentativas atingido. Por favor aguarde 30 minutos');
|
||||
expect(translateServerResponse(keys[8], 'pt_br')).toBe('Erro de rede ao tentar obter recursos.');
|
||||
expect(translateServerResponse(keys[9], 'pt_br')).toBe('Por favor, confirme seu e-mail antes de continuar');
|
||||
expect(translateServerResponse(keys[10], 'pt_br')).toBe('Por ravor, preencha todos os campos');
|
||||
expect(translateServerResponse(keys[11], 'pt_br')).toBe('Por favor, informe seu e-mail');
|
||||
expect(translateServerResponse(keys[12], 'pt_br')).toBe('Por favor, informe seu e-mail e senha!');
|
||||
expect(translateServerResponse(keys[13], 'pt_br')).toBe('Por favor, informe a nova senha');
|
||||
expect(translateServerResponse(keys[14], 'pt_br')).toBe('Por favor, digite pelo menos 3 letras');
|
||||
expect(translateServerResponse(keys[15], 'pt_br')).toBe('O tamanho máximo do texto é 2000');
|
||||
expect(translateServerResponse(keys[16], 'pt_br')).toBe('Erro desconhecido');
|
||||
expect(translateServerResponse(keys[17], 'pt_br')).toBe('Identificação incorreta ou faltando');
|
||||
expect(translateServerResponse(keys[18], 'pt_br')).toBe('Informação errada ou incompleta!');
|
||||
expect(translateServerResponse(keys[19], 'pt_br')).toBe('E-mail ou senha inválidos!');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
|
||||
import { translateTimeMessage, translateServerResponse } from '../../utils/TranslatorUtils';
|
||||
import { serverResponses } from '../../constants/serverResponses';
|
||||
|
||||
describe('Portuguese Utils unit tests', () => {
|
||||
describe('Russian Utils unit tests', () => {
|
||||
it('should translate all time ago messages to ru', () => {
|
||||
expect(translateTimeMessage('2 years ago', 'ru')).toBe('2 года назад');
|
||||
expect(translateTimeMessage('1 year ago', 'ru')).toBe('1 год назад');
|
||||
@@ -56,33 +56,25 @@ describe('Portuguese Utils unit tests', () => {
|
||||
it('should translate all server responses to ru', () => {
|
||||
const keys: string[] = Object.keys(serverResponses);
|
||||
|
||||
expect(translateServerResponse(keys[0], 'ru'))
|
||||
.toBe('Неправильный пароль: Пароль должен содержать не менее 8 символов, 1 заглавную букву, 1 специальный символ.');
|
||||
expect(translateServerResponse(keys[1], 'ru'))
|
||||
.toBe('Неправильный пароль: Пароль должен содержать как минимум 1 заглавную букву и 1 специальный символ.');
|
||||
expect(translateServerResponse(keys[2], 'ru'))
|
||||
.toBe('Неправильный пароль: Пароль должен содержать хотя бы 1 специальный символ.');
|
||||
expect(translateServerResponse(keys[3], 'ru'))
|
||||
.toBe('Электронная почта уже используется!');
|
||||
expect(translateServerResponse(keys[4], 'ru'))
|
||||
.toBe('Доступ запрещен!');
|
||||
expect(translateServerResponse(keys[5], 'ru'))
|
||||
.toBe('Внутренняя ошибка сервера!');
|
||||
expect(translateServerResponse(keys[6], 'ru'))
|
||||
.toBe('Достигнут максимальный лимит попыток входа. Пожалуйста, подождите 30 минут');
|
||||
expect(translateServerResponse(keys[7], 'ru'))
|
||||
.toBe('Пожалуйста, заполните все поля');
|
||||
expect(translateServerResponse(keys[8], 'ru'))
|
||||
.toBe('Пожалуйста, введите свое имя пользователя и пароль!');
|
||||
expect(translateServerResponse(keys[9], 'ru'))
|
||||
.toBe('Пожалуйста, введите не менее 3 символов');
|
||||
expect(translateServerResponse(keys[10], 'ru'))
|
||||
.toBe('Максимальная длина текста — 2000 символов.');
|
||||
expect(translateServerResponse(keys[11], 'ru'))
|
||||
.toBe('Неизвестная ошибка');
|
||||
expect(translateServerResponse(keys[12], 'ru'))
|
||||
.toBe('Неверная или отсутствующая информация!');
|
||||
expect(translateServerResponse(keys[13], 'ru'))
|
||||
.toBe('Неправильный пользователь или пароль');
|
||||
expect(translateServerResponse(keys[0], 'ru')).toBe('Неправильный пароль: Пароль должен содержать не менее 8 символов, 1 заглавную букву, 1 специальный символ.');
|
||||
expect(translateServerResponse(keys[1], 'ru')).toBe('Неправильный пароль: Пароль должен содержать как минимум 1 заглавную букву и 1 специальный символ.');
|
||||
expect(translateServerResponse(keys[2], 'ru')).toBe('Неправильный пароль: Пароль должен содержать хотя бы 1 специальный символ.');
|
||||
expect(translateServerResponse(keys[3], 'ru')).toBe('Электронная почта уже используется!');
|
||||
expect(translateServerResponse(keys[4], 'ru')).toBe('Доступ запрещен!');
|
||||
expect(translateServerResponse(keys[5], 'ru')).toBe('Если введенный вами адрес электронной почты связан с учетной записью, вы вскоре получите ссылку для сброса пароля.');
|
||||
expect(translateServerResponse(keys[6], 'ru')).toBe('Внутренняя ошибка сервера!');
|
||||
expect(translateServerResponse(keys[7], 'ru')).toBe('Достигнут максимальный лимит попыток входа. Пожалуйста, подождите 30 минут');
|
||||
expect(translateServerResponse(keys[8], 'ru')).toBe('Ошибка сети при попытке получить ресурс.');
|
||||
expect(translateServerResponse(keys[9], 'ru')).toBe('Пожалуйста, подтвердите свой адрес электронной почты, прежде чем продолжить');
|
||||
expect(translateServerResponse(keys[10], 'ru')).toBe('Пожалуйста, заполните все поля');
|
||||
expect(translateServerResponse(keys[11], 'ru')).toBe('Пожалуйста, введите свой адрес электронной почты');
|
||||
expect(translateServerResponse(keys[12], 'ru')).toBe('Пожалуйста, введите свое имя пользователя и пароль!');
|
||||
expect(translateServerResponse(keys[13], 'ru')).toBe('Пожалуйста, введите новый пароль');
|
||||
expect(translateServerResponse(keys[14], 'ru')).toBe('Пожалуйста, введите не менее 3 символов');
|
||||
expect(translateServerResponse(keys[15], 'ru')).toBe('Максимальная длина текста — 2000 символов.');
|
||||
expect(translateServerResponse(keys[16], 'ru')).toBe('Неизвестная ошибка');
|
||||
expect(translateServerResponse(keys[17], 'ru')).toBe('Неправильная или отсутствующая идентификация');
|
||||
expect(translateServerResponse(keys[18], 'ru')).toBe('Неверная или отсутствующая информация!');
|
||||
expect(translateServerResponse(keys[19], 'ru')).toBe('Неправильный пользователь или пароль');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
|
||||
import { translateTimeMessage, translateServerResponse } from '../../utils/TranslatorUtils';
|
||||
import { serverResponses } from '../../constants/serverResponses';
|
||||
|
||||
describe('Portuguese Utils unit tests', () => {
|
||||
describe('Spanish Utils unit tests', () => {
|
||||
it('should translate all time ago messages to es', () => {
|
||||
expect(translateTimeMessage('2 years ago', 'es')).toBe('Hace 2 años');
|
||||
expect(translateTimeMessage('1 year ago', 'es')).toBe('Hace 1 año');
|
||||
@@ -35,33 +35,24 @@ describe('Portuguese Utils unit tests', () => {
|
||||
it('should translate all server responses to es', () => {
|
||||
const keys: string[] = Object.keys(serverResponses);
|
||||
|
||||
expect(translateServerResponse(keys[0], 'es'))
|
||||
.toBe('Contraseña inválida: La contraseña debe tener al menos 8 caracteres, 1 mayúscula y 1 carácter especial');
|
||||
expect(translateServerResponse(keys[1], 'es'))
|
||||
.toBe('Contraseña inválida: La contraseña debe tener al menos 1 mayúscula y 1 carácter especial');
|
||||
expect(translateServerResponse(keys[2], 'es'))
|
||||
.toBe('Contraseña inválida: La contraseña debe tener al menos 1 carácter especial');
|
||||
expect(translateServerResponse(keys[3], 'es'))
|
||||
.toBe('¡El correo ya está registrado!');
|
||||
expect(translateServerResponse(keys[4], 'es'))
|
||||
.toBe('¡Prohibido! Acceso denegado');
|
||||
expect(translateServerResponse(keys[5], 'es'))
|
||||
.toBe('¡Error interno del servidor!');
|
||||
expect(translateServerResponse(keys[6], 'es'))
|
||||
.toBe('Has alcanzado el límite máximo de intentos de inicio de sesión. Por favor, espera 30 minutos');
|
||||
expect(translateServerResponse(keys[7], 'es'))
|
||||
.toBe('Por favor, completa todos los campos');
|
||||
expect(translateServerResponse(keys[8], 'es'))
|
||||
.toBe('¡Por favor, ingresa tu nombre de usuario y contraseña!');
|
||||
expect(translateServerResponse(keys[9], 'es'))
|
||||
.toBe('¡Por favor, escriba al menos 3 caracteres!');
|
||||
expect(translateServerResponse(keys[10], 'es'))
|
||||
.toBe('La longitud máxima del texto es 2000');
|
||||
expect(translateServerResponse(keys[11], 'es'))
|
||||
.toBe('Error desconocido');
|
||||
expect(translateServerResponse(keys[12], 'es'))
|
||||
.toBe('¡Información incorrecta o incompleta!');
|
||||
expect(translateServerResponse(keys[13], 'es'))
|
||||
.toBe('¡Usuario o contraseña incorrectos!');
|
||||
expect(translateServerResponse(keys[0], 'es')).toBe('Contraseña inválida: La contraseña debe tener al menos 8 caracteres, 1 mayúscula y 1 carácter especial');
|
||||
expect(translateServerResponse(keys[1], 'es')).toBe('Contraseña inválida: La contraseña debe tener al menos 1 mayúscula y 1 carácter especial');
|
||||
expect(translateServerResponse(keys[2], 'es')).toBe('Contraseña inválida: La contraseña debe tener al menos 1 carácter especial');
|
||||
expect(translateServerResponse(keys[3], 'es')).toBe('¡El correo ya está registrado!');
|
||||
expect(translateServerResponse(keys[4], 'es')).toBe('¡Prohibido! Acceso denegado');
|
||||
expect(translateServerResponse(keys[5], 'es')).toBe('Si la dirección de correo electrónico ingresada está asociada a una cuenta, recibirá un enlace para restablecer su contraseña en breve.');
|
||||
expect(translateServerResponse(keys[6], 'es')).toBe('¡Error interno del servidor!');
|
||||
expect(translateServerResponse(keys[7], 'es')).toBe('Has alcanzado el límite máximo de intentos de inicio de sesión. Por favor, espera 30 minutos');
|
||||
expect(translateServerResponse(keys[8], 'es')).toBe('Error de red al intentar obtener el recurso.');
|
||||
expect(translateServerResponse(keys[9], 'es')).toBe('Por favor, confirme su correo electrónico antes de continuar');
|
||||
expect(translateServerResponse(keys[10], 'es')).toBe('Por favor, completa todos los campos');
|
||||
expect(translateServerResponse(keys[11], 'es')).toBe('Por favor, ingresa tu correo electronico');
|
||||
expect(translateServerResponse(keys[12], 'es')).toBe('¡Por favor, ingresa tu correo electronico y contraseña!');
|
||||
expect(translateServerResponse(keys[13], 'es')).toBe('Por favor, rellene la nueva contraseña');
|
||||
expect(translateServerResponse(keys[14], 'es')).toBe('¡Por favor, escriba al menos 3 caracteres!');
|
||||
expect(translateServerResponse(keys[15], 'es')).toBe('La longitud máxima del texto es 2000');
|
||||
expect(translateServerResponse(keys[16], 'es')).toBe('Error desconocido');
|
||||
expect(translateServerResponse(keys[17], 'es')).toBe('Identificación incorrecta o faltante');
|
||||
expect(translateServerResponse(keys[18], 'es')).toBe('¡Información incorrecta o incompleta!');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@ describe('EmailConfirmation Component', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('❌ Oops!')).toBeDefined();
|
||||
expect(screen.getByText('Wrong or missing identification.')).toBeDefined();
|
||||
expect(screen.getByTestId('email-confirm-error-msg')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('EmailConfirmation Component', () => {
|
||||
renderFn();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('✅ Email Confirmed')).toBeDefined();
|
||||
expect(screen.getByTestId('email-confirm-success-msg')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -83,9 +83,9 @@ describe('EmailConfirmation Component', () => {
|
||||
renderFn();
|
||||
|
||||
await waitFor(() => {
|
||||
const successMessage = screen.getByText('✅ Email Confirmed');
|
||||
const successMessage = screen.getByTestId('email-confirm-success-msg');
|
||||
expect(successMessage).toBeDefined();
|
||||
expect(successMessage.classList.contains('mb-3')).toBe(true);
|
||||
expect(successMessage.classList.contains('mb-4')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -105,7 +105,7 @@ describe('EmailConfirmation Component', () => {
|
||||
renderFn();
|
||||
|
||||
await waitFor(() => {
|
||||
const loginButton = screen.getByText('Go to Login');
|
||||
const loginButton = screen.getByText('Login');
|
||||
expect(loginButton).toBeDefined();
|
||||
expect(loginButton.classList.contains('btn-success')).toBe(true);
|
||||
});
|
||||
|
||||
@@ -178,7 +178,7 @@ describe('Home Component', () => {
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('content-header')).toBeDefined();
|
||||
expect(screen.getByPlaceholderText('Filter tasks & notes')).toBeDefined();
|
||||
expect(screen.getByPlaceholderText('home_input_filter')).toBeDefined();
|
||||
|
||||
// Check that API calls were made
|
||||
expect(api.getJSON).toHaveBeenCalledTimes(3);
|
||||
@@ -206,7 +206,7 @@ describe('Home Component', () => {
|
||||
expect(screen.getAllByTestId('note-title').length).toBe(2);
|
||||
});
|
||||
|
||||
const searchInput = screen.getByPlaceholderText('Filter tasks & notes');
|
||||
const searchInput = screen.getByPlaceholderText('home_input_filter');
|
||||
|
||||
// Test filtering by entering text
|
||||
await act(async () => {
|
||||
@@ -238,7 +238,7 @@ describe('Home Component', () => {
|
||||
});
|
||||
|
||||
// Select "Only Tasks" radio button
|
||||
const onlyTasksRadio = screen.getByLabelText('Tasks');
|
||||
const onlyTasksRadio = screen.getByLabelText('home_radio_tasks');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(onlyTasksRadio);
|
||||
@@ -251,7 +251,7 @@ describe('Home Component', () => {
|
||||
});
|
||||
|
||||
// Select "Only Notes" radio button
|
||||
const onlyNotesRadio = screen.getByLabelText('Notes');
|
||||
const onlyNotesRadio = screen.getByLabelText('home_radio_notes');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(onlyNotesRadio);
|
||||
|
||||
@@ -10,6 +10,8 @@ type Props = {
|
||||
h2BlackText: string;
|
||||
h2GreenText: string;
|
||||
isHomeComponent?: boolean;
|
||||
newTaskI18n?: string;
|
||||
newNoteI18n?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -54,7 +56,7 @@ const ContentHeader: React.FC<Props> = (props: Props): React.ReactNode => {
|
||||
type="button"
|
||||
className="home-new-item w-45 mb-2"
|
||||
>
|
||||
New task
|
||||
{props.newTaskI18n}
|
||||
</button>
|
||||
</NavLink>
|
||||
<NavLink to="/notes/new" onClick={() => setNewPage('/notes/new')}>
|
||||
@@ -62,7 +64,7 @@ const ContentHeader: React.FC<Props> = (props: Props): React.ReactNode => {
|
||||
type="button"
|
||||
className="home-new-item w-45 ms-2"
|
||||
>
|
||||
New note
|
||||
{props.newNoteI18n}
|
||||
</button>
|
||||
</NavLink>
|
||||
</Col>
|
||||
|
||||
@@ -21,6 +21,9 @@ interface Props {
|
||||
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
onChangeDate?: (date: Date | null) => void;
|
||||
data_testid?: string;
|
||||
pwdHideText?: string;
|
||||
pwdShowText?: string;
|
||||
pwdHelperTxt?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +69,7 @@ function FormInput(props: React.PropsWithChildren<Props>): React.ReactNode {
|
||||
{props.type && props.type === 'password' && (
|
||||
<small>
|
||||
<a href="#" onClick={toggleShowPassword}>
|
||||
{showingPwd ? ' (Hide)' : ' (Show)'}
|
||||
{showingPwd ? ` (${props.pwdHideText})` : ` (${props.pwdShowText})`}
|
||||
</a>
|
||||
</small>
|
||||
)}
|
||||
@@ -109,15 +112,22 @@ function FormInput(props: React.PropsWithChildren<Props>): React.ReactNode {
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<Form.Control
|
||||
required={props.required}
|
||||
type={formType}
|
||||
name={props.name}
|
||||
placeholder={props.placeholder ? props.placeholder : ''}
|
||||
value={props?.value}
|
||||
onChange={props.onChange}
|
||||
data-testid={props.data_testid}
|
||||
/>
|
||||
<>
|
||||
<Form.Control
|
||||
required={props.required}
|
||||
type={formType}
|
||||
name={props.name}
|
||||
placeholder={props.placeholder ? props.placeholder : ''}
|
||||
value={props?.value}
|
||||
onChange={props.onChange}
|
||||
data-testid={props.data_testid}
|
||||
/>
|
||||
{props.type && props.type === 'password' && (
|
||||
<Form.Text id="passwordHelpBlock" muted>
|
||||
{props.pwdHelperTxt}
|
||||
</Form.Text>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</InputGroup>
|
||||
</Form.Group>
|
||||
|
||||
@@ -63,8 +63,11 @@ function LoginForm({ prefix }: { prefix: string }): React.ReactNode {
|
||||
const form = event.currentTarget;
|
||||
if (form.checkValidity() === false) {
|
||||
setFormInvalid(true);
|
||||
if (prefix !== 'reset') {
|
||||
setErrorMessage(translateServerResponse('Please fill in your username and password!', i18n.language));
|
||||
if (prefix === 'complete_reset') {
|
||||
setErrorMessage(translateServerResponse('Please fill in the new password', i18n.language));
|
||||
}
|
||||
else if (prefix !== 'reset') {
|
||||
setErrorMessage(translateServerResponse('Please fill in your username and password!' + prefix, i18n.language));
|
||||
}
|
||||
else {
|
||||
setErrorMessage(translateServerResponse('Please fill in your email', i18n.language));
|
||||
@@ -88,13 +91,13 @@ function LoginForm({ prefix }: { prefix: string }): React.ReactNode {
|
||||
// Do not clear the email, because user might request to resend
|
||||
setPassword('');
|
||||
setPasswordAgain('');
|
||||
setSuccessMessage('Please confirm your email before proceeding.');
|
||||
setSuccessMessage(translateServerResponse('Please confirm your email before proceeding', i18n.language));
|
||||
setSecondsLeft(30);
|
||||
setIsResendEnabled(false);
|
||||
}
|
||||
else if (prefix === 'reset') {
|
||||
await api.postJSON(ApiConfig.resetPwdUrl, { email });
|
||||
setSuccessMessage('If the email address you entered is associated with an account, you will receive a password reset link shortly.');
|
||||
setSuccessMessage(translateServerResponse('If the email address you entered is associated with an account, you will receive a password reset link shortly.', i18n.language));
|
||||
}
|
||||
else if (prefix === 'complete_reset') {
|
||||
const token = searchParams.get('token');
|
||||
@@ -103,11 +106,14 @@ function LoginForm({ prefix }: { prefix: string }): React.ReactNode {
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
setFormInvalid(true);
|
||||
if (typeof e === 'string') {
|
||||
console.log('string');
|
||||
setErrorMessage(translateServerResponse(e, i18n.language));
|
||||
}
|
||||
else if (e instanceof Error) {
|
||||
console.log(e.message);
|
||||
setErrorMessage(translateServerResponse(e.message, i18n.language));
|
||||
}
|
||||
}
|
||||
@@ -174,7 +180,7 @@ function LoginForm({ prefix }: { prefix: string }): React.ReactNode {
|
||||
onClick={handleResend}
|
||||
disabled={!isResendEnabled}
|
||||
>
|
||||
{isResendEnabled ? 'Resend Confirmation Email' : `Resend in ${secondsLeft}s`}
|
||||
{isResendEnabled ? `${t('register_resent_email')}` : `${t('register_resent_email_secs')} ${secondsLeft}`}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
@@ -189,7 +195,7 @@ function LoginForm({ prefix }: { prefix: string }): React.ReactNode {
|
||||
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
||||
{prefix !== 'complete_reset' && (
|
||||
<FormInput
|
||||
labelText="Email"
|
||||
labelText={t(`${prefix}_email_label`)}
|
||||
iconName="At"
|
||||
required={true}
|
||||
name="email"
|
||||
@@ -204,12 +210,16 @@ function LoginForm({ prefix }: { prefix: string }): React.ReactNode {
|
||||
|
||||
{prefix !== 'reset' && (
|
||||
<FormInput
|
||||
labelText="Password"
|
||||
labelText={t(`${prefix}_password_label`)}
|
||||
iconName="Lock"
|
||||
required={true}
|
||||
type="password"
|
||||
name="password"
|
||||
placeholder={t(`${prefix}_password_placeholder`)}
|
||||
value={password}
|
||||
pwdShowText={t('password_show_txt')}
|
||||
pwdHideText={t('password_hide_txt')}
|
||||
pwdHelperTxt={t('password_helper')}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setPassword(e.target.value);
|
||||
}}
|
||||
@@ -219,12 +229,16 @@ function LoginForm({ prefix }: { prefix: string }): React.ReactNode {
|
||||
|
||||
{(prefix === 'register' || prefix === 'complete_reset') && (
|
||||
<FormInput
|
||||
labelText="Repeat password"
|
||||
labelText={t('register_password_repeat_label')}
|
||||
iconName="Lock"
|
||||
required={true}
|
||||
type="password"
|
||||
name="passwordAgain"
|
||||
placeholder={t('login_password_placeholder')}
|
||||
value={passwordAgain}
|
||||
pwdShowText={t('password_show_txt')}
|
||||
pwdHideText={t('password_hide_txt')}
|
||||
pwdHelperTxt={t('password_helper')}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setPasswordAgain(e.target.value);
|
||||
}}
|
||||
@@ -256,7 +270,7 @@ function LoginForm({ prefix }: { prefix: string }): React.ReactNode {
|
||||
<div className="text-center mt-3">
|
||||
{prefix === 'login' && (
|
||||
<Link to="/reset-password" className="text-decoration-none ms-2">
|
||||
Forgot your password?
|
||||
{t('login_forgot_password')}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -7,32 +7,41 @@ const enTranslations = {
|
||||
landing_btn_portuguese: 'Português (BR)',
|
||||
landing_btn_spanish: 'Español',
|
||||
landing_btn_russian: 'Русский',
|
||||
landing_languages: 'You can choose one of these languages',
|
||||
|
||||
password_show_txt: 'Show',
|
||||
password_hide_txt: 'Hide',
|
||||
password_helper: 'The password must be at least 8 characters long and include a number, a capital letter, and a special character',
|
||||
|
||||
login_title: 'Login',
|
||||
login_email_label: 'Email',
|
||||
login_email_placeholder: 'Type your email',
|
||||
login_email_placeholder: 'you@example.com',
|
||||
login_password_label: 'Password',
|
||||
login_password_placeholder: 'Type your password',
|
||||
login_password_placeholder: 'Your password',
|
||||
login_btn_submit: 'Login',
|
||||
login_account: 'Don\'t have an account yet?',
|
||||
login_go_other: 'Create account',
|
||||
login_back_home: 'Back to home',
|
||||
login_forgot_password: 'Forgot your password?',
|
||||
|
||||
register_title: 'Create account',
|
||||
register_email_label: 'Email',
|
||||
register_email_placeholder: 'Type your email',
|
||||
register_email_placeholder: 'you@example.com',
|
||||
register_password_label: 'Password',
|
||||
register_password_placeholder: 'Type your password',
|
||||
register_password_placeholder: 'Your password',
|
||||
register_password_repeat_label: 'Repeat password',
|
||||
register_btn_submit: 'Create account',
|
||||
register_account: 'Already have an account?',
|
||||
register_go_other: 'Login',
|
||||
register_back_home: 'Back to home',
|
||||
register_resent_email: 'Resend confirmation email',
|
||||
register_resent_email_secs: 'Resend in ',
|
||||
|
||||
reset_title: 'Reset your password',
|
||||
reset_email_label: 'Email',
|
||||
reset_email_placeholder: 'Type your email',
|
||||
reset_email_placeholder: 'you@example.com',
|
||||
reset_password_label: 'Password',
|
||||
reset_password_placeholder: 'Type your password',
|
||||
reset_password_placeholder: 'Your password',
|
||||
reset_btn_submit: 'Send confirmation email',
|
||||
reset_account: 'Have you remembered your password?',
|
||||
reset_go_other: 'Login',
|
||||
@@ -46,12 +55,24 @@ const enTranslations = {
|
||||
complete_reset_go_other: 'Login',
|
||||
complete_reset_back_home: 'Back to home',
|
||||
|
||||
email_confirmation_loading: 'Confirming your email address...',
|
||||
email_confirmation_success: '✅ Email confirmed',
|
||||
email_confirmation_success_text: 'Thank you! Your email address has been successfully confirmed. You can now return to the TaskNote app and log in.',
|
||||
email_confirmation_btn: 'Login',
|
||||
|
||||
home_nav_home: 'Home',
|
||||
home_nav_tasks: 'Tasks',
|
||||
home_nav_notes: 'Notes',
|
||||
home_nav_about: 'About',
|
||||
home_welcome_title: 'Hello, ',
|
||||
home_card_task_title: 'Tasks Summary',
|
||||
home_welcome_subtitle: 'Welcome to TaskNote! Get ready to complete your pending tasks',
|
||||
home_welcome_start: 'Start Your Day, Be',
|
||||
home_welcome_productive: 'Productive',
|
||||
home_input_filter: 'Filter tasks & notes',
|
||||
home_radio_everything: 'Everything',
|
||||
home_radio_tasks: 'Tasks',
|
||||
home_radio_notes: 'Notes',
|
||||
home_card_task_title: 'Tasks Summary', // remove
|
||||
home_card_task_pending: 'Pending tasks',
|
||||
home_card_task_empty: 'No pending tasks',
|
||||
home_card_task_done: 'done tasks!',
|
||||
|
||||
@@ -67,45 +67,63 @@ export const serverResponsesTranslations: Record<string, string> = {
|
||||
BAD_PASSWORD_3_pt_br: 'Senha fraca: Senha deve possuir pelo menos 8 letras, 1 maiúscula, 1 caracter especial',
|
||||
BAD_PASSWORD_2_pt_br: 'Senha fraca: Senha deve possuir pelo menos 1 maiúscula, 1 caracter especial',
|
||||
BAD_PASSWORD_1_pt_br: 'Senha fraca: Senha deve possuir pelo menos 1 caracter especial',
|
||||
CONFIRM_EMAIL_TO_GO_ON_pt_br: 'Por favor, confirme seu e-mail antes de continuar',
|
||||
EMAIL_EXISTS_pt_br: 'E-mail já cadastrado!',
|
||||
FORBIDDEN_pt_br: 'Proibido! Acesso negado',
|
||||
INTERNAL_ERROR_pt_br: 'Erro Interno do Servidor!',
|
||||
INVALID_CREDENTIALS_pt_br: 'E-mail ou senha inválidos!',
|
||||
MAX_LOGIN_ATTEMPT_pt_br: 'Limite máximo de tentativas atingido. Por favor aguarde 30 minutos',
|
||||
NETWORK_ERROR_pt_br: 'Erro de rede ao tentar obter recursos.',
|
||||
FILL_ALL_FIELDS_pt_br: 'Por ravor, preencha todos os campos',
|
||||
FILL_NEW_PASSWORD_pt_br: 'Por favor, informe a nova senha',
|
||||
FILL_USER_pt_br: 'Por favor, informe seu e-mail',
|
||||
FILL_USER_AND_PASS_pt_br: 'Por favor, informe seu e-mail e senha!',
|
||||
FILL_AT_LEAST_3_pt_br: 'Por favor, digite pelo menos 3 letras',
|
||||
MAX_TEXT_LENGTH_2000_pt_br: 'O tamanho máximo do texto é 2000',
|
||||
RECOVER_PASSWORD_pt_br: 'Se o endereço de e-mail informado estiver associado a uma conta, você receberá um link para resetar a senha em breve.',
|
||||
UNKNOWN_pt_br: 'Erro desconhecido',
|
||||
WRONG_IDENTIFICATION_pt_br: 'Identificação incorreta ou faltando',
|
||||
WRONG_OR_MISSING_INFO_pt_br: 'Informação errada ou incompleta!',
|
||||
|
||||
BAD_PASSWORD_3_es: 'Contraseña inválida: La contraseña debe tener al menos 8 caracteres, 1 mayúscula y 1 carácter especial',
|
||||
BAD_PASSWORD_2_es: 'Contraseña inválida: La contraseña debe tener al menos 1 mayúscula y 1 carácter especial',
|
||||
BAD_PASSWORD_1_es: 'Contraseña inválida: La contraseña debe tener al menos 1 carácter especial',
|
||||
CONFIRM_EMAIL_TO_GO_ON_es: 'Por favor, confirme su correo electrónico antes de continuar',
|
||||
EMAIL_EXISTS_es: '¡El correo ya está registrado!',
|
||||
FORBIDDEN_es: '¡Prohibido! Acceso denegado',
|
||||
INTERNAL_ERROR_es: '¡Error interno del servidor!',
|
||||
INVALID_CREDENTIALS_es: '¡Usuario o contraseña incorrectos!',
|
||||
MAX_LOGIN_ATTEMPT_es: 'Has alcanzado el límite máximo de intentos de inicio de sesión. Por favor, espera 30 minutos',
|
||||
NETWORK_ERROR_es: 'Error de red al intentar obtener el recurso.',
|
||||
FILL_ALL_FIELDS_es: 'Por favor, completa todos los campos',
|
||||
FILL_USER_AND_PASS_es: '¡Por favor, ingresa tu nombre de usuario y contraseña!',
|
||||
FILL_NEW_PASSWORD_es: 'Por favor, rellene la nueva contraseña',
|
||||
FILL_USER_es: 'Por favor, ingresa tu correo electronico',
|
||||
FILL_USER_AND_PASS_es: '¡Por favor, ingresa tu correo electronico y contraseña!',
|
||||
FILL_AT_LEAST_3_es: '¡Por favor, escriba al menos 3 caracteres!',
|
||||
MAX_TEXT_LENGTH_2000_es: 'La longitud máxima del texto es 2000',
|
||||
RECOVER_PASSWORD_es: 'Si la dirección de correo electrónico ingresada está asociada a una cuenta, recibirá un enlace para restablecer su contraseña en breve.',
|
||||
UNKNOWN_es: 'Error desconocido',
|
||||
WRONG_IDENTIFICATION_es: 'Identificación incorrecta o faltante',
|
||||
WRONG_OR_MISSING_INFO_es: '¡Información incorrecta o incompleta!',
|
||||
|
||||
BAD_PASSWORD_3_ru: 'Неправильный пароль: Пароль должен содержать не менее 8 символов, 1 заглавную букву, 1 специальный символ.',
|
||||
BAD_PASSWORD_2_ru: 'Неправильный пароль: Пароль должен содержать как минимум 1 заглавную букву и 1 специальный символ.',
|
||||
BAD_PASSWORD_1_ru: 'Неправильный пароль: Пароль должен содержать хотя бы 1 специальный символ.',
|
||||
CONFIRM_EMAIL_TO_GO_ON_ru: 'Пожалуйста, подтвердите свой адрес электронной почты, прежде чем продолжить',
|
||||
EMAIL_EXISTS_ru: 'Электронная почта уже используется!',
|
||||
FORBIDDEN_ru: 'Доступ запрещен!',
|
||||
INTERNAL_ERROR_ru: 'Внутренняя ошибка сервера!',
|
||||
INVALID_CREDENTIALS_ru: 'Неправильный пользователь или пароль',
|
||||
MAX_LOGIN_ATTEMPT_ru: 'Достигнут максимальный лимит попыток входа. Пожалуйста, подождите 30 минут',
|
||||
NETWORK_ERROR_ru: 'Ошибка сети при попытке получить ресурс.',
|
||||
FILL_ALL_FIELDS_ru: 'Пожалуйста, заполните все поля',
|
||||
FILL_NEW_PASSWORD_ru: 'Пожалуйста, введите новый пароль',
|
||||
FILL_USER_ru: 'Пожалуйста, введите свой адрес электронной почты',
|
||||
FILL_USER_AND_PASS_ru: 'Пожалуйста, введите свое имя пользователя и пароль!',
|
||||
FILL_AT_LEAST_3_ru: 'Пожалуйста, введите не менее 3 символов',
|
||||
MAX_TEXT_LENGTH_2000_ru: 'Максимальная длина текста — 2000 символов.',
|
||||
RECOVER_PASSWORD_ru: 'Если введенный вами адрес электронной почты связан с учетной записью, вы вскоре получите ссылку для сброса пароля.',
|
||||
UNKNOWN_ru: 'Неизвестная ошибка',
|
||||
WRONG_IDENTIFICATION_ru: 'Неправильная или отсутствующая идентификация',
|
||||
WRONG_OR_MISSING_INFO_ru: 'Неверная или отсутствующая информация!'
|
||||
};
|
||||
|
||||
@@ -7,6 +7,11 @@ const ptBrTranslations = {
|
||||
landing_btn_portuguese: 'Português (BR)',
|
||||
landing_btn_spanish: 'Español',
|
||||
landing_btn_russian: 'Русский',
|
||||
landing_languages: 'Você pode escolher um destes idiomas',
|
||||
|
||||
password_show_txt: 'Mostrar',
|
||||
password_hide_txt: 'Esconder',
|
||||
password_helper: 'A senha deve ter no mínimo 8 caracteres e incluir um número, uma letra maiúscula, e um caracter especial',
|
||||
|
||||
login_title: 'Entrar',
|
||||
login_email_label: 'E-mail',
|
||||
@@ -17,22 +22,56 @@ const ptBrTranslations = {
|
||||
login_account: 'Não possui uma conta ainda?',
|
||||
login_go_other: 'Criar conta',
|
||||
login_back_home: 'Voltar para o início',
|
||||
login_forgot_password: 'Esqueceu sua senha?',
|
||||
|
||||
register_title: 'Criar conta',
|
||||
register_email_label: 'E-mail',
|
||||
register_email_placeholder: 'Digite seu e-mail',
|
||||
register_password_label: 'Senha',
|
||||
register_password_placeholder: 'Digite sua senha',
|
||||
register_password_repeat_label: 'Repetir senha',
|
||||
register_btn_submit: 'Criar conta',
|
||||
register_account: 'Já possui conta?',
|
||||
register_go_other: 'Entrar',
|
||||
register_back_home: 'Voltar para o início',
|
||||
register_resent_email: 'Re-enviar e-mail de confirmação',
|
||||
register_resent_email_secs: 'Re-enviar em ',
|
||||
|
||||
reset_title: 'Resete sua senha',
|
||||
reset_email_label: 'E-mail',
|
||||
reset_email_placeholder: 'Digite seu e-mail',
|
||||
reset_password_label: 'Senha',
|
||||
reset_password_placeholder: 'Digite sua senha',
|
||||
reset_btn_submit: 'Enviar e-mail de confirmação',
|
||||
reset_account: 'Lembrou da sua senha?',
|
||||
reset_go_other: 'Entrar',
|
||||
reset_back_home: 'Voltar para o início',
|
||||
|
||||
complete_reset_title: 'Crie sua nova senha',
|
||||
complete_reset_password_label: 'Senha',
|
||||
complete_reset_password_placeholder: 'Digite sua senha',
|
||||
complete_reset_btn_submit: 'Resetar',
|
||||
complete_reset_account: 'Lembrou da sua senha?',
|
||||
complete_reset_go_other: 'Login',
|
||||
complete_reset_back_home: 'Voltar para o início',
|
||||
|
||||
email_confirmation_loading: 'Confirmando seu endereço de e-mail...',
|
||||
email_confirmation_success: '✅ E-mail confirmado',
|
||||
email_confirmation_success_text: 'Obrigado! Seu endereço de e-mail foi confirmado com sucesso. Agora você pode voltar ao app TaskNote e entrar.',
|
||||
email_confirmation_btn: 'Entrar',
|
||||
|
||||
home_nav_home: 'Início',
|
||||
home_nav_tasks: 'Tarefas',
|
||||
home_nav_notes: 'Notas',
|
||||
home_nav_about: 'Sobre',
|
||||
home_welcome_title: 'Olá, ',
|
||||
home_welcome_subtitle: 'Bem vindo ao TaskNote! Se prepare para completar suas tarefas pendentes',
|
||||
home_welcome_start: 'Comece Seu Dia, Seja',
|
||||
home_welcome_productive: 'Produtivo(a)',
|
||||
home_input_filter: 'Filtrar tarefas e notas',
|
||||
home_radio_everything: 'Tudo',
|
||||
home_radio_tasks: 'Tarefas',
|
||||
home_radio_notes: 'Notas',
|
||||
home_card_task_title: 'Resumo de Tarefas',
|
||||
home_card_task_pending: 'Tarefa(s) pendente(s)',
|
||||
home_card_task_empty: 'Nenhuma tarefa pendente',
|
||||
|
||||
@@ -7,6 +7,11 @@ const ruTranslations = {
|
||||
landing_btn_portuguese: 'Português (BR)',
|
||||
landing_btn_spanish: 'Español',
|
||||
landing_btn_russian: 'Русский',
|
||||
landing_languages: 'Вы можете выбрать один из этих языков',
|
||||
|
||||
password_show_txt: 'Показать',
|
||||
password_hide_txt: 'Скрыть',
|
||||
password_helper: 'Пароль должен быть длиной не менее 8 символов и включать цифру, заглавную букву и специальный символ',
|
||||
|
||||
login_title: 'Войти',
|
||||
login_email_label: 'Электронная почта',
|
||||
@@ -17,22 +22,56 @@ const ruTranslations = {
|
||||
login_account: 'Ещё нет аккаунта?',
|
||||
login_go_other: 'Создать аккаунт',
|
||||
login_back_home: 'Вернуться на главную',
|
||||
login_forgot_password: 'Забыли пароль?',
|
||||
|
||||
register_title: 'Создать аккаунт',
|
||||
register_email_label: 'Электронная почта',
|
||||
register_email_placeholder: 'Введите вашу электронную почту',
|
||||
register_password_label: 'Пароль',
|
||||
register_password_placeholder: 'Введите ваш пароль',
|
||||
register_password_repeat_label: 'Повторите пароль',
|
||||
register_btn_submit: 'Создать аккаунт',
|
||||
register_account: 'Уже есть аккаунт?',
|
||||
register_go_other: 'Войти',
|
||||
register_back_home: 'Вернуться на главную',
|
||||
register_resent_email: 'Повторно отправить письмо с подтверждением',
|
||||
register_resent_email_secs: 'Повторно отправить в ',
|
||||
|
||||
reset_title: 'Сбросьте свой пароль',
|
||||
reset_email_label: 'Электронная почта',
|
||||
reset_email_placeholder: 'Введите вашу электронную почту',
|
||||
reset_password_label: 'Пароль',
|
||||
reset_password_placeholder: 'Введите ваш пароль',
|
||||
reset_btn_submit: 'Отправить подтверждение по электронной почте',
|
||||
reset_account: 'Вы вспомнили свой пароль?',
|
||||
reset_go_other: 'Войти',
|
||||
reset_back_home: 'Вернуться на главную',
|
||||
|
||||
complete_reset_title: 'Создайте новый пароль',
|
||||
complete_reset_password_label: 'Пароль',
|
||||
complete_reset_password_placeholder: 'Введите ваш пароль',
|
||||
complete_reset_btn_submit: 'Reset',
|
||||
complete_reset_account: 'Вы вспомнили свой пароль?',
|
||||
complete_reset_go_other: 'Войти',
|
||||
complete_reset_back_home: 'Вернуться на главную',
|
||||
|
||||
email_confirmation_loading: 'Подтверждение вашего адреса электронной почты...',
|
||||
email_confirmation_success: '✅ Электронная почта подтверждена',
|
||||
email_confirmation_success_text: 'Спасибо! Ваш адрес электронной почты успешно подтвержден. Теперь вы можете вернуться в приложение TaskNote и войти в систему.',
|
||||
email_confirmation_btn: 'Войти',
|
||||
|
||||
home_nav_home: 'Главная',
|
||||
home_nav_tasks: 'Задачи',
|
||||
home_nav_notes: 'Заметки',
|
||||
home_nav_about: 'О приложении',
|
||||
home_welcome_title: 'Привет, ',
|
||||
home_welcome_subtitle: 'Добро пожаловать в TaskNote! Приготовьтесь завершить свои отложенные задачи',
|
||||
home_welcome_start: 'Начните свой день, будьте',
|
||||
home_welcome_productive: 'Продуктивный',
|
||||
home_input_filter: 'Фильтровать задачи и заметки',
|
||||
home_radio_everything: 'Все',
|
||||
home_radio_tasks: 'Задачи',
|
||||
home_radio_notes: 'Заметки',
|
||||
home_card_task_title: 'Обзор задач',
|
||||
home_card_task_pending: 'Незавершённые задачи',
|
||||
home_card_task_empty: 'Нет незавершённых задач',
|
||||
|
||||
@@ -4,13 +4,19 @@ export const serverResponses: Record<string, string> = {
|
||||
'Bad password: Password must have at least 1 special character': 'BAD_PASSWORD_1',
|
||||
'Email already exists!': 'EMAIL_EXISTS',
|
||||
'Forbidden! Access denied!': 'FORBIDDEN',
|
||||
'If the email address you entered is associated with an account, you will receive a password reset link shortly.': 'RECOVER_PASSWORD',
|
||||
'Internal Server Error!': 'INTERNAL_ERROR',
|
||||
'Max login attempt limit reached. Please wait 30 minutes': 'MAX_LOGIN_ATTEMPT',
|
||||
'NetworkError when attempting to fetch resource.': 'NETWORK_ERROR',
|
||||
'Please confirm your email before proceeding': 'CONFIRM_EMAIL_TO_GO_ON',
|
||||
'Please fill in all the fields': 'FILL_ALL_FIELDS',
|
||||
'Please fill in your email': 'FILL_USER',
|
||||
'Please fill in your username and password!': 'FILL_USER_AND_PASS',
|
||||
'Please fill in the new password': 'FILL_NEW_PASSWORD',
|
||||
'Please type at least 3 characters': 'FILL_AT_LEAST_3',
|
||||
'The maximum text length is 2000': 'MAX_TEXT_LENGTH_2000',
|
||||
'Unknown error': 'UNKNOWN',
|
||||
'Wrong or missing identification': 'WRONG_IDENTIFICATION',
|
||||
'Wrong or missing information!': 'WRONG_OR_MISSING_INFO',
|
||||
'Invalid credentials': 'INVALID_CREDENTIALS'
|
||||
};
|
||||
|
||||
@@ -7,6 +7,11 @@ const esTranslations = {
|
||||
landing_btn_portuguese: 'Português (BR)',
|
||||
landing_btn_spanish: 'Español',
|
||||
landing_btn_russian: 'Русский',
|
||||
landing_languages: 'Puedes elegir uno de estos idiomas',
|
||||
|
||||
password_show_txt: 'Mostrar',
|
||||
password_hide_txt: 'Ocultar',
|
||||
password_helper: 'La contraseña debe tener al menos 8 caracteres e incluir un número, una letra mayúscula y un carácter especial',
|
||||
|
||||
login_title: 'Acceso',
|
||||
login_email_label: 'Correo electrónico',
|
||||
@@ -17,22 +22,56 @@ const esTranslations = {
|
||||
login_account: '¿No tienes una cuenta?',
|
||||
login_go_other: 'Regístrate aquí',
|
||||
login_back_home: 'Volver a inicio',
|
||||
login_forgot_password: '¿Olvidaste tu contraseña?',
|
||||
|
||||
register_title: 'Crear cuenta',
|
||||
register_email_label: 'Correo electrónico',
|
||||
register_email_placeholder: 'Escribe tu correo aquí',
|
||||
register_password_label: 'Contraseña',
|
||||
register_password_placeholder: 'Escribe tu contraseña aquí',
|
||||
register_password_repeat_label: 'Repita la contraseña',
|
||||
register_btn_submit: 'Crear cuenta',
|
||||
register_account: '¿Ya tienes una cuenta?',
|
||||
register_go_other: 'Ir a iniciar sesión',
|
||||
register_back_home: 'Volver a inicio',
|
||||
register_resent_email: 'Reenviar correo electrónico de confirmación',
|
||||
register_resent_email_secs: 'Reenviar en ',
|
||||
|
||||
home_nav_home: 'Inicio',
|
||||
reset_title: 'Restablecer su contraseña',
|
||||
reset_email_label: 'Correo electrónico',
|
||||
reset_email_placeholder: 'Escribe tu correo aquí',
|
||||
reset_password_label: 'Contraseña',
|
||||
reset_password_placeholder: 'Escribe tu contraseña aquí',
|
||||
reset_btn_submit: 'Enviar correo electrónico de confirmación',
|
||||
reset_account: '¿Has recordado tu contraseña?',
|
||||
reset_go_other: 'Ir a iniciar sesión',
|
||||
reset_back_home: 'Volver a inicio',
|
||||
|
||||
complete_reset_title: 'Crea tu nueva contraseña',
|
||||
complete_reset_password_label: 'Contraseña',
|
||||
complete_reset_password_placeholder: 'Escribe tu contraseña aquí',
|
||||
complete_reset_btn_submit: 'Reiniciar',
|
||||
complete_reset_account: '¿Has recordado tu contraseña?',
|
||||
complete_reset_go_other: 'Ir a iniciar sesión',
|
||||
complete_reset_back_home: 'Volver a inicio',
|
||||
|
||||
email_confirmation_loading: 'Confirmando su dirección de correo electrónico...',
|
||||
email_confirmation_success: '✅ Correo electrónico confirmado',
|
||||
email_confirmation_success_text: '¡Gracias! Tu dirección de correo electrónico se ha confirmado correctamente. Ya puedes volver a la app TaskNote e iniciar sesión.',
|
||||
email_confirmation_btn: 'Iniciar sesión',
|
||||
|
||||
home_nav_home: 'Início',
|
||||
home_nav_tasks: 'Tareas',
|
||||
home_nav_notes: 'Notas',
|
||||
home_nav_about: 'Acerca de',
|
||||
home_welcome_title: 'Hola, ',
|
||||
home_welcome_subtitle: '¡Bienvenido a TaskNote! Prepárate para completar tus tareas pendientes.',
|
||||
home_welcome_start: 'Comienza Tu Día, Sé',
|
||||
home_welcome_productive: 'Productivo(a)',
|
||||
home_input_filter: 'Filtrar tareas y notas',
|
||||
home_radio_everything: 'Todo',
|
||||
home_radio_tasks: 'Tareas',
|
||||
home_radio_notes: 'Notas',
|
||||
home_card_task_title: 'Resumen de Tareas',
|
||||
home_card_task_pending: 'Tarea(s) pendiente(s)',
|
||||
home_card_task_empty: 'No tienes tareas pendientes',
|
||||
|
||||
@@ -11,6 +11,15 @@ a, .btn-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:focus-visible,
|
||||
.btn:hover,
|
||||
.btn:active,
|
||||
:not(.btn-check) + .btn:active {
|
||||
background-color: var(--bs-primary);
|
||||
border-color: var(--bs-primary);
|
||||
box-shadow: var(--bs-primary);
|
||||
}
|
||||
|
||||
a:hover, .btn-link:hover {
|
||||
color: var(--bs-primary);
|
||||
}
|
||||
@@ -265,13 +274,43 @@ code {
|
||||
}
|
||||
|
||||
.input-group-text {
|
||||
border-right: none !important;
|
||||
padding: 0.375rem 0.10rem 0.375rem 0.75rem;
|
||||
}
|
||||
|
||||
.input-group > .form-control,
|
||||
.react-datepicker__input-container > .form-control {
|
||||
border-left: none !important;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border-color: var(--bs-border-color);
|
||||
}
|
||||
|
||||
.form-control:invalid {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border-color: var(--bs-border-color);
|
||||
}
|
||||
|
||||
.form-control:invalid:focus {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border-color: var(--bs-border-color);
|
||||
}
|
||||
|
||||
.was-validated .form-control:invalid:focus {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border-color: var(--bs-border-color);
|
||||
}
|
||||
|
||||
.was-validated .form-control:valid,
|
||||
.was-validated .form-control:valid:focus {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border-color: var(--bs-border-color);
|
||||
}
|
||||
|
||||
.dropdown-toggle.btn.btn-success {
|
||||
@@ -280,17 +319,6 @@ code {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border-color: var(--bs-border-color); /* optional – prevents border from changing on focus */
|
||||
}
|
||||
|
||||
.form-control:invalid {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.home-filter {
|
||||
all: unset;
|
||||
font-size: 12px;
|
||||
|
||||
@@ -85,8 +85,8 @@ function Account(): React.ReactNode {
|
||||
* Resets the input fields to their default values.
|
||||
*/
|
||||
const resetInputs = (userUpdated: UserResponse): void => {
|
||||
setUserName(userUpdated.name ? userUpdated.name : '');
|
||||
setUserEmail(userUpdated.email);
|
||||
setUserName('');
|
||||
setUserEmail('');
|
||||
updateUser(userUpdated);
|
||||
|
||||
setValidated(false);
|
||||
@@ -96,6 +96,7 @@ function Account(): React.ReactNode {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setValidated(true);
|
||||
setErrorMessage('');
|
||||
|
||||
const form = event.currentTarget;
|
||||
|
||||
@@ -106,6 +107,12 @@ function Account(): React.ReactNode {
|
||||
passwordAgain: userPasswordAgain
|
||||
};
|
||||
|
||||
const sizeOfPayload = JSON.stringify(patchPayload).length;
|
||||
if (sizeOfPayload === 57) {
|
||||
setErrorMessage('Nothing to update!');
|
||||
return;
|
||||
}
|
||||
|
||||
const updated: UserResponse | undefined = await patchUserInfo(patchPayload);
|
||||
if (updated) {
|
||||
form.reset();
|
||||
@@ -145,7 +152,7 @@ function Account(): React.ReactNode {
|
||||
iconName="Person"
|
||||
required={false}
|
||||
name="name"
|
||||
placeholder={user?.name ? user.name : ''}
|
||||
placeholder={user?.name ?? 'Your name'}
|
||||
value={userName}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setUserName(e.target.value);
|
||||
|
||||
@@ -2,19 +2,23 @@ import React, { useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import api from '../../api-service/api';
|
||||
import ApiConfig from '../../api-service/apiConfig';
|
||||
import { translateServerResponse } from '../../utils/TranslatorUtils';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { handleDefaultLang } from '../../lang-service/LangHandler';
|
||||
|
||||
type Status = 'loading' | 'success' | 'error';
|
||||
|
||||
const EmailConfirmation: React.FC = () => {
|
||||
const [status, setStatus] = useState<Status>('loading');
|
||||
const [errorMessage, setErrorMessage] = useState<string>('');
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const confirmEmail = async (): Promise<void> => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const id = urlParams.get('identification');
|
||||
if (!id) {
|
||||
setStatus('error');
|
||||
setErrorMessage('Wrong or missing identification.');
|
||||
setErrorMessage(translateServerResponse('Wrong or missing identification', i18n.language));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,6 +42,10 @@ const EmailConfirmation: React.FC = () => {
|
||||
confirmEmail();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
handleDefaultLang();
|
||||
}, [i18n.language]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="d-flex flex-column align-items-center justify-content-center min-vh-100 px-3 text-center"
|
||||
@@ -52,25 +60,22 @@ const EmailConfirmation: React.FC = () => {
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<div className="p-4 bg-white rounded-3 shadow" style={{ maxWidth: '500px', width: '100%' }}>
|
||||
<div className="p-5 bg-white rounded-3 shadow" style={{ maxWidth: '500px', width: '100%' }}>
|
||||
|
||||
{status === 'loading' && (
|
||||
<>
|
||||
<div className="spinner-border text-success mb-3"></div>
|
||||
<p>Confirming your email address...</p>
|
||||
<p>{t('email_confirmation_loading')}</p>
|
||||
</>
|
||||
)}
|
||||
|
||||
{status === 'success' && (
|
||||
<>
|
||||
<h1 className="mb-3">✅ Email Confirmed</h1>
|
||||
<h1 className="mb-4" data-testid="email-confirm-success-msg">{t('email_confirmation_success')}</h1>
|
||||
|
||||
<p className="mb-4">
|
||||
Thank you! Your email address has been successfully confirmed.
|
||||
You can now return to the TaskNote app and log in.
|
||||
</p>
|
||||
<p className="mb-4">{t('email_confirmation_success_text')}</p>
|
||||
<Link to="/login" className="btn btn-success px-4 py-2"style={{ fontWeight: 'bold', borderRadius: '6px' }}>
|
||||
Go to Login
|
||||
{t('email_confirmation_btn')}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
@@ -78,7 +83,7 @@ const EmailConfirmation: React.FC = () => {
|
||||
{status === 'error' && (
|
||||
<>
|
||||
<h1 className="mb-3">❌ Oops!</h1>
|
||||
<p className="mb-4">
|
||||
<p className="mb-4" data-testid="email-confirm-error-msg">
|
||||
{ errorMessage }
|
||||
</p>
|
||||
</>
|
||||
|
||||
@@ -264,7 +264,7 @@ function Home(): React.ReactNode {
|
||||
|
||||
useEffect(() => {
|
||||
handleDefaultLang();
|
||||
setName(user?.name ? user?.name : 'User');
|
||||
setName(user?.name ?? 'User');
|
||||
loadTags();
|
||||
loadAllTasks();
|
||||
loadAllNotes();
|
||||
@@ -275,10 +275,12 @@ function Home(): React.ReactNode {
|
||||
<ContentHeader
|
||||
h1TextRegular={t('home_welcome_title')}
|
||||
h1TextBold={name}
|
||||
subtitle="Welcome to TaskNote! Get ready to complete your pending tasks"
|
||||
h2BlackText="Start Your Day, Be"
|
||||
h2GreenText="Productive"
|
||||
subtitle={t('home_welcome_subtitle')}
|
||||
h2BlackText={t('home_welcome_start')}
|
||||
h2GreenText={t('home_welcome_productive')}
|
||||
isHomeComponent
|
||||
newTaskI18n={t('task_form_title')}
|
||||
newNoteI18n={t('note_form_title')}
|
||||
/>
|
||||
|
||||
<AlertError
|
||||
@@ -295,7 +297,7 @@ function Home(): React.ReactNode {
|
||||
id="search_term"
|
||||
size="lg"
|
||||
name="search_term"
|
||||
placeholder="Filter tasks & notes"
|
||||
placeholder={t('home_input_filter')}
|
||||
value={filterText}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => filterTasksAndNotes(e.target.value, selectedOption)}
|
||||
/>
|
||||
@@ -309,7 +311,7 @@ function Home(): React.ReactNode {
|
||||
<Form.Check
|
||||
inline
|
||||
type="radio"
|
||||
label="Everything"
|
||||
label={t('home_radio_everything')}
|
||||
name="radioGroup"
|
||||
id="everything"
|
||||
value="everything"
|
||||
@@ -323,7 +325,7 @@ function Home(): React.ReactNode {
|
||||
<Form.Check
|
||||
inline
|
||||
type="radio"
|
||||
label="Tasks"
|
||||
label={t('home_radio_tasks')}
|
||||
name="radioGroup"
|
||||
id="onlyTasks"
|
||||
value="onlyTasks"
|
||||
@@ -337,7 +339,7 @@ function Home(): React.ReactNode {
|
||||
<Form.Check
|
||||
inline
|
||||
type="radio"
|
||||
label="Notes"
|
||||
label={t('home_radio_notes')}
|
||||
name="radioGroup"
|
||||
id="onlyNotes"
|
||||
value="onlyNotes"
|
||||
|
||||
@@ -46,7 +46,7 @@ function Landing(): React.ReactNode {
|
||||
<Link to="/register" className="login">{t('landing_btn_register')}</Link>
|
||||
|
||||
<aside>
|
||||
<h3>You can choose one of these languages</h3>
|
||||
<h3>{t('landing_languages')}</h3>
|
||||
{languages.map((lang: LangAvailable) => (
|
||||
<Button
|
||||
key={lang.key}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ RUN ./mvnw -B package -Pnative -DskipTests
|
||||
|
||||
|
||||
### Deployer
|
||||
FROM debian:12.10-slim AS deploy
|
||||
FROM debian:12.11-slim AS deploy
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
ca-certificates \
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.5.0</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<jacoco.output.data>${project.build.directory}/coverage-reports</jacoco.output.data>
|
||||
<timestamp>${maven.build.timestamp}</timestamp>
|
||||
<maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
|
||||
<hibernate.version>6.6.15.Final</hibernate.version>
|
||||
<hibernate.version>6.6.16.Final</hibernate.version>
|
||||
<sonar.organization>ricardo-campos-org</sonar.organization>
|
||||
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
|
||||
</properties>
|
||||
@@ -423,7 +423,7 @@
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>10.23.1</version>
|
||||
<version>10.24.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
|
||||
@@ -80,8 +80,8 @@ public class SecurityConfig {
|
||||
*/
|
||||
@Bean
|
||||
public AuthenticationProvider authenticationProvider() {
|
||||
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||
authProvider.setUserDetailsService(userService.userDetailsService());
|
||||
DaoAuthenticationProvider authProvider =
|
||||
new DaoAuthenticationProvider(userService.userDetailsService());
|
||||
authProvider.setPasswordEncoder(passwordEncoder());
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user