diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..07115cdf
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..5668832c
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/wiq_en2b.iml b/.idea/wiq_en2b.iml
new file mode 100644
index 00000000..d6ebd480
--- /dev/null
+++ b/.idea/wiq_en2b.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sonar-project.properties b/sonar-project.properties
index 4ff2cbeb..1724fcb1 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -10,7 +10,7 @@ sonar.host.url=https://sonarcloud.io
sonar.language=js
sonar.projectName=wiq_en2b
-sonar.coverage.exclusions=**/*.test.js
+sonar.coverage.exclusions=**/*.test.js,**/*.test.jsx
sonar.sources=webapp/src/components,users/authservice,users/userservice,gatewayservice
sonar.sourceEncoding=UTF-8
sonar.exclusions=node_modules/**
diff --git a/webapp/jsconfig.json b/webapp/jsconfig.json
new file mode 100644
index 00000000..e93fe659
--- /dev/null
+++ b/webapp/jsconfig.json
@@ -0,0 +1,7 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "checkJs": true,
+ "jsx": "react"
+ }
+}
\ No newline at end of file
diff --git a/webapp/package-lock.json b/webapp/package-lock.json
index bcc358d5..16709cbd 100644
--- a/webapp/package-lock.json
+++ b/webapp/package-lock.json
@@ -15,8 +15,14 @@
"@testing-library/react": "^14.1.2",
"@testing-library/user-event": "^14.5.2",
"axios": "^1.6.5",
+ "dotenv": "^16.4.1",
+ "i18next": "^23.8.2",
+ "i18next-browser-languagedetector": "^7.2.0",
+ "i18next-http-backend": "^2.4.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-router": "^6.21.3",
+ "react-router-dom": "^6.21.3",
"react-scripts": "5.0.1",
"web-vitals": "^3.5.1"
},
@@ -5026,6 +5032,14 @@
"node": ">=12"
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.14.2",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz",
+ "integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -8637,7 +8651,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
"integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
- "dev": true,
"dependencies": {
"node-fetch": "^2.6.12"
}
@@ -9523,11 +9536,14 @@
}
},
"node_modules/dotenv": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
- "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
+ "version": "16.4.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz",
+ "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==",
"engines": {
- "node": ">=10"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/motdotla/dotenv?sponsor=1"
}
},
"node_modules/dotenv-expand": {
@@ -12266,6 +12282,44 @@
"node": ">=10.17.0"
}
},
+ "node_modules/i18next": {
+ "version": "23.8.2",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.8.2.tgz",
+ "integrity": "sha512-Z84zyEangrlERm0ZugVy4bIt485e/H8VecGUZkZWrH7BDePG6jT73QdL9EA1tRTTVVMpry/MgWIP1FjEn0DRXA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ }
+ },
+ "node_modules/i18next-browser-languagedetector": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.2.0.tgz",
+ "integrity": "sha512-U00DbDtFIYD3wkWsr2aVGfXGAj2TgnELzOX9qv8bT0aJtvPV9CRO77h+vgmHFBMe7LAxdwvT/7VkCWGya6L3tA==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ }
+ },
+ "node_modules/i18next-http-backend": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.4.3.tgz",
+ "integrity": "sha512-jo2M03O6n1/DNb51WSQ8PsQ0xEELzLZRdYUTbf17mLw3rVwnJF9hwNgMXvEFSxxb+N8dT+o0vtigA6s5mGWyPA==",
+ "dependencies": {
+ "cross-fetch": "4.0.0"
+ }
+ },
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -19247,7 +19301,6 @@
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
- "dev": true,
"dependencies": {
"whatwg-url": "^5.0.0"
},
@@ -19266,20 +19319,17 @@
"node_modules/node-fetch/node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
- "dev": true
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/node-fetch/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
- "dev": true
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/node-fetch/node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dev": true,
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
@@ -22030,6 +22080,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.21.3",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz",
+ "integrity": "sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==",
+ "dependencies": {
+ "@remix-run/router": "1.14.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.21.3",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.3.tgz",
+ "integrity": "sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==",
+ "dependencies": {
+ "@remix-run/router": "1.14.2",
+ "react-router": "6.21.3"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
@@ -22396,6 +22476,14 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
+ "node_modules/react-scripts/node_modules/dotenv": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+ "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/react-scripts/node_modules/emittery": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz",
diff --git a/webapp/package.json b/webapp/package.json
index 6e59b09b..bed431d9 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -10,8 +10,14 @@
"@testing-library/react": "^14.1.2",
"@testing-library/user-event": "^14.5.2",
"axios": "^1.6.5",
+ "dotenv": "^16.4.1",
+ "i18next": "^23.8.2",
+ "i18next-browser-languagedetector": "^7.2.0",
+ "i18next-http-backend": "^2.4.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-router": "^6.21.3",
+ "react-router-dom": "^6.21.3",
"react-scripts": "5.0.1",
"web-vitals": "^3.5.1"
},
diff --git a/webapp/src/App.js b/webapp/src/App.js
index 1478b910..bb046dad 100644
--- a/webapp/src/App.js
+++ b/webapp/src/App.js
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
-import AddUser from './components/AddUser';
-import Login from './components/Login';
+import AddUser from './pages/Register';
+import Login from './pages/Login';
import CssBaseline from '@mui/material/CssBaseline';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
diff --git a/webapp/src/components/Router.jsx b/webapp/src/components/Router.jsx
new file mode 100644
index 00000000..e6ea557f
--- /dev/null
+++ b/webapp/src/components/Router.jsx
@@ -0,0 +1,24 @@
+import React from "react";
+import {
+ createBrowserRouter
+ } from "react-router-dom";
+import Root from "../pages/Root";
+import Login from "../pages/Login";
+import Register from "../pages/Register";
+
+const router = createBrowserRouter([
+ {
+ path: "/",
+ element: ,
+ },
+ {
+ path: "/login",
+ element:
+ },
+ {
+ path: "/register",
+ element:
+ }
+ ]);
+
+export default router;
\ No newline at end of file
diff --git a/webapp/src/index.js b/webapp/src/index.js
index d563c0fb..363a1b78 100644
--- a/webapp/src/index.js
+++ b/webapp/src/index.js
@@ -3,11 +3,13 @@ import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
+import { RouterProvider } from 'react-router-dom';
+import router from 'components/Router';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
-
+
);
diff --git a/webapp/src/components/Login.js b/webapp/src/pages/Login.jsx
similarity index 100%
rename from webapp/src/components/Login.js
rename to webapp/src/pages/Login.jsx
diff --git a/webapp/src/components/AddUser.js b/webapp/src/pages/Register.jsx
similarity index 95%
rename from webapp/src/components/AddUser.js
rename to webapp/src/pages/Register.jsx
index 00d522a2..ce9bf16e 100644
--- a/webapp/src/components/AddUser.js
+++ b/webapp/src/pages/Register.jsx
@@ -5,7 +5,7 @@ import { Container, Typography, TextField, Button, Snackbar } from '@mui/materia
const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000';
-const AddUser = () => {
+const Register = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
@@ -27,7 +27,7 @@ const AddUser = () => {
return (
- Add User
+ Register
{
onChange={(e) => setPassword(e.target.value)}
/>
{error && (
@@ -57,4 +57,4 @@ const AddUser = () => {
);
};
-export default AddUser;
+export default Register;
diff --git a/webapp/src/pages/Root.jsx b/webapp/src/pages/Root.jsx
new file mode 100644
index 00000000..c334a10c
--- /dev/null
+++ b/webapp/src/pages/Root.jsx
@@ -0,0 +1,5 @@
+import React from "react";
+
+export default function Root() {
+ return Proof of concept
+}
\ No newline at end of file
diff --git a/webapp/src/components/Login.test.js b/webapp/src/tests/Login.test.js
similarity index 98%
rename from webapp/src/components/Login.test.js
rename to webapp/src/tests/Login.test.js
index af102dcf..9fe441a3 100644
--- a/webapp/src/components/Login.test.js
+++ b/webapp/src/tests/Login.test.js
@@ -2,7 +2,7 @@ import React from 'react';
import { render, fireEvent, screen, waitFor, act } from '@testing-library/react';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import Login from './Login';
+import Login from '../pages/Login';
const mockAxios = new MockAdapter(axios);
diff --git a/webapp/src/components/AddUser.test.js b/webapp/src/tests/Register.test.js
similarity index 90%
rename from webapp/src/components/AddUser.test.js
rename to webapp/src/tests/Register.test.js
index 87334886..6bd68eaa 100644
--- a/webapp/src/components/AddUser.test.js
+++ b/webapp/src/tests/Register.test.js
@@ -2,7 +2,7 @@ import React from 'react';
import { render, fireEvent, screen, waitFor } from '@testing-library/react';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import AddUser from './AddUser';
+import AddUser from '../pages/Register';
const mockAxios = new MockAdapter(axios);
@@ -16,7 +16,7 @@ describe('AddUser component', () => {
const usernameInput = screen.getByLabelText(/Username/i);
const passwordInput = screen.getByLabelText(/Password/i);
- const addUserButton = screen.getByRole('button', { name: /Add User/i });
+ const addUserButton = screen.getByRole('button', { name: /Register/i });
// Mock the axios.post request to simulate a successful response
mockAxios.onPost('http://localhost:8000/adduser').reply(200);
@@ -39,7 +39,7 @@ describe('AddUser component', () => {
const usernameInput = screen.getByLabelText(/Username/i);
const passwordInput = screen.getByLabelText(/Password/i);
- const addUserButton = screen.getByRole('button', { name: /Add User/i });
+ const addUserButton = screen.getByRole('button', { name: /Register/i });
// Mock the axios.post request to simulate an error response
mockAxios.onPost('http://localhost:8000/adduser').reply(500, { error: 'Internal Server Error' });