From 23ec2b05ab39fc283669b43b9c72ed98e6f70ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Mod=C3=A9e?= <bjomo323@student.liu.se> Date: Sat, 6 Mar 2021 10:19:15 +0000 Subject: [PATCH] Resolve "Add redux" --- .vs/ProjectSettings.json | 3 + .vs/VSWorkspaceState.json | 6 ++ .vs/slnx.sqlite | Bin 0 -> 90112 bytes .vs/teknikattan-scoring-system/v16/.suo | Bin 0 -> 15360 bytes client/.eslintrc | 47 ++++----- client/Redux-readme.txt | 71 +++++++++++++ client/package-lock.json | 94 ++++++++++++++++-- client/package.json | 6 ++ client/src/actions/Action_Explanation.txt | 8 ++ client/src/actions/communication.js | 62 ++++++++++++ client/src/actions/login.js | 29 ++++++ client/src/actions/types.js | 11 ++ client/src/index.tsx | 33 +++++- .../src/middleware/Middleware_Explanation.txt | 6 ++ client/src/reducers/Reducer_Explanation.txt | 7 ++ client/src/reducers/allReducers.js | 11 ++ client/src/reducers/isLoggedIn.js | 9 ++ 17 files changed, 367 insertions(+), 36 deletions(-) create mode 100644 .vs/ProjectSettings.json create mode 100644 .vs/VSWorkspaceState.json create mode 100644 .vs/slnx.sqlite create mode 100644 .vs/teknikattan-scoring-system/v16/.suo create mode 100644 client/Redux-readme.txt create mode 100644 client/src/actions/Action_Explanation.txt create mode 100644 client/src/actions/communication.js create mode 100644 client/src/actions/login.js create mode 100644 client/src/actions/types.js create mode 100644 client/src/middleware/Middleware_Explanation.txt create mode 100644 client/src/reducers/Reducer_Explanation.txt create mode 100644 client/src/reducers/allReducers.js create mode 100644 client/src/reducers/isLoggedIn.js diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 00000000..f8b48885 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 00000000..6b611411 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,6 @@ +{ + "ExpandedNodes": [ + "" + ], + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..2fd9f25a43f737391cedd7aaffa61ebf778acf2a GIT binary patch literal 90112 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 G83F)E6e}tK literal 0 HcmV?d00001 diff --git a/.vs/teknikattan-scoring-system/v16/.suo b/.vs/teknikattan-scoring-system/v16/.suo new file mode 100644 index 0000000000000000000000000000000000000000..39e2dc63c325f04b906b01016e830aa1112dcaab GIT binary patch literal 15360 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 literal 0 HcmV?d00001 diff --git a/client/.eslintrc b/client/.eslintrc index 7e2cadb0..9234ebf1 100644 --- a/client/.eslintrc +++ b/client/.eslintrc @@ -1,26 +1,27 @@ { - "parser": "@typescript-eslint/parser", - "parserOptions": { - "sourceType": "module", - "project": [ - "tsconfig.json" - ] - }, - "ecmaFeatures": { - "jsx": true - }, - "settings": { - "react": { - "version": "detect" + "parser": "@typescript-eslint/parser", + "parserOptions": { + "sourceType": "module", + "project": [ + "tsconfig.json" + ] + }, + "ecmaFeatures": { + "jsx": true + }, + "settings": { + "react": { + "version": "detect" + } + }, + "extends": [ + "plugin:react/recommended", + "plugin:@typescript-eslint/recommended", + "prettier/@typescript-eslint", + "plugin:prettier/recommended" + ], + "rules": { + "prettier/prettier": ["warn"] } - }, - "extends": [ - "plugin:react/recommended", - "plugin:@typescript-eslint/recommended", - "prettier/@typescript-eslint", - "plugin:prettier/recommended" - ], - "rules": { - "prettier/prettier": ["warn"] } -} \ No newline at end of file + \ No newline at end of file diff --git a/client/Redux-readme.txt b/client/Redux-readme.txt new file mode 100644 index 00000000..7a20ee65 --- /dev/null +++ b/client/Redux-readme.txt @@ -0,0 +1,71 @@ + +This file is a short description of what Redux is, +to learn more about redux, visit https://redux.js.org/ + + +====Install=============================================== +To install Redux type the following in the terminal: + +npm install redux react-redux +npm install @reduxjs/toolkit + +If you have not done so already install axios: + +npm install react-axios +npm install axios + +Also, a good tool to use is the browser plugin. This allows you to se the state in real time. +It even has a useful playback feature. install it here: + +Chrome: +https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd + +Firefox: +https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/ +========================================================= + +What is Redux? + +Redux is a pattern and library for managing and updating +application state, using events called "actions". It serves +as a centralized store for state that needs to be used +across your entire application, with rules ensuring that +the state can only be updated in a predictable fashion. + +The center of every Redux application is the store. +A "store" is a container that holds your application's +global state. + +A store is a JavaScript object with a few special functions +and abilities that make it different than a plain global object: + +- You must never directly modify or change the state that is +kept inside the Redux store + +- Instead, the only way to cause an update to the state is to +create a plain action object that describes "something that +happened in the application", and then dispatch the action to +the store to tell it what happened. + +- When an action is dispatched, the store runs the root reducer +function, and lets it calculate the new state based on the old +state and the action +Finally, the store notifies subscribers that the state has been +updated so the UI can be updated with the new data. + + +Redux uses several types of code: +- Actions are plain objects with a type field, and describe +"what happened" in the app + +- Reducers are functions that calculate a new state value +based on previous state + an action + +- A Redux store runs the root reducer whenever an action +is dispatched + +Cite: https://redux.js.org/tutorials/fundamentals/part-1-overview + + +More useful links on the subject: +https://www.youtube.com/watch?v=CVpUuw9XSjY \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index d6c2bd5b..ca2a06eb 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1895,6 +1895,17 @@ } } }, + "@reduxjs/toolkit": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.5.0.tgz", + "integrity": "sha512-E/FUraRx+8guw9Hlg/Ja8jI/hwCrmIKed8Annt9YsZw3BQp+F24t5I5b2OWR6pkEHY4hn1BgP08FrTZFRKsdaQ==", + "requires": { + "immer": "^8.0.0", + "redux": "^4.0.0", + "redux-thunk": "^2.3.0", + "reselect": "^4.0.0" + } + }, "@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -2312,6 +2323,16 @@ "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==", "dev": true }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", @@ -2414,6 +2435,18 @@ "@types/react": "*" } }, + "@types/react-redux": { + "version": "7.1.16", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.16.tgz", + "integrity": "sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw==", + "dev": true, + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/react-router": { "version": "5.1.11", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.11.tgz", @@ -7844,9 +7877,9 @@ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, "immer": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/immer/-/immer-7.0.9.tgz", - "integrity": "sha512-Vs/gxoM4DqNAYR7pugIxi0Xc8XAun/uy7AQu4fLLqaTBHxjOP9pJ266Q9MWA/ly4z6rAFZbvViOtihxUZ7O28A==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", + "integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==" }, "import-cwd": { "version": "2.1.0", @@ -11033,9 +11066,9 @@ } }, "open": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.0.tgz", - "integrity": "sha512-PGoBCX/lclIWlpS/R2PQuIR4NJoXh6X5AwVzE7WXnWRGvHg7+4TBCgsujUgiPpm0K1y4qvQeWnCWVTpTKZBtvA==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "requires": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" @@ -12771,10 +12804,15 @@ "whatwg-fetch": "^3.4.1" } }, + "react-axios": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-axios/-/react-axios-2.0.4.tgz", + "integrity": "sha512-QsTq7C/NwsjfrSmFVxPo29BdX6DtLpRF0fZTJv5/R4BanOm+c4639B3Xb4lF83ZfAOX5IW8XG7htz4V+WNF+WA==" + }, "react-dev-utils": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.2.tgz", - "integrity": "sha512-xG7GlMoYkrgc2M1kDCHKRywXMDbFnjOB+/VzpytQyYBusEzR8NlGTMmUbvN86k94yyKu5XReHB8eZC2JZrNchQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.3.tgz", + "integrity": "sha512-4lEA5gF4OHrcJLMUV1t+4XbNDiJbsAWCH5Z2uqlTqW6dD7Cf5nEASkeXrCI/Mz83sI2o527oBIFKVMXtRf1Vtg==", "requires": { "@babel/code-frame": "7.10.4", "address": "1.1.2", @@ -12789,7 +12827,7 @@ "global-modules": "2.0.0", "globby": "11.0.1", "gzip-size": "5.1.1", - "immer": "7.0.9", + "immer": "8.0.1", "is-root": "2.1.0", "loader-utils": "2.0.0", "open": "^7.0.2", @@ -12902,6 +12940,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-redux": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.2.tgz", + "integrity": "sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA==", + "requires": { + "@babel/runtime": "^7.12.1", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.13.1" + } + }, "react-refresh": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", @@ -13223,6 +13273,25 @@ "strip-indent": "^3.0.0" } }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "redux-devtools-extension": { + "version": "2.13.8", + "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz", + "integrity": "sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg==" + }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -13449,6 +13518,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "reselect": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==" + }, "resolve": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", diff --git a/client/package.json b/client/package.json index 4d2df9fc..58910bbf 100644 --- a/client/package.json +++ b/client/package.json @@ -6,6 +6,7 @@ "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.57", + "@reduxjs/toolkit": "^1.5.0", "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.6.3", @@ -16,14 +17,19 @@ "axios": "^0.21.1", "formik": "^2.2.6", "react": "^17.0.1", + "react-axios": "^2.0.4", "react-dom": "^17.0.1", + "react-redux": "^7.2.2", "react-router-dom": "^5.2.0", "react-scripts": "4.0.2", + "redux": "^4.0.5", + "redux-devtools-extension": "^2.13.8", "typescript": "^4.1.3", "web-vitals": "^1.1.0", "yup": "^0.32.9" }, "devDependencies": { + "@types/react-redux": "^7.1.16", "@types/react-router-dom": "^5.1.7", "@typescript-eslint/eslint-plugin": "4.2.0", "@typescript-eslint/parser": "4.2.0", diff --git a/client/src/actions/Action_Explanation.txt b/client/src/actions/Action_Explanation.txt new file mode 100644 index 00000000..dec743a1 --- /dev/null +++ b/client/src/actions/Action_Explanation.txt @@ -0,0 +1,8 @@ +An action is a plain JavaScript object that has a type field. +The actions, the events that occur in the app based on user input, +and trigger updates in the state + +You can think of an action as an event that describes something +that happened in the application. + +https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow \ No newline at end of file diff --git a/client/src/actions/communication.js b/client/src/actions/communication.js new file mode 100644 index 00000000..587f431e --- /dev/null +++ b/client/src/actions/communication.js @@ -0,0 +1,62 @@ +import Types from "./types.js"; + +export function axiosPost(path, data, config = undefined, + startCB = undefined, successCB = undefined, errorCB = undefined){ + return { + type: Types.AXIOS_POST, + path, + data, + config, + startCB, + successCB, + errorCB + } +} + +export function axiosPostSuccess(path, data, previousAction){ + return { + type: Types.AXIOS_POST_SUCCESS, + path, + data, + previousAction + } +} + +export function axiosPostError(path, data, previousAction){ + return { + type: Types.AXIOS_POST_ERROR, + path, + data, + previousAction + } +} + +export function axiosGet(path, data, config = undefined, startCB = undefined, successCB = undefined, errorCB = undefined) { + return { + type: Types.AXIOS_GET, + path, + data, + config, + startCB, + successCB, + errorCB + } +} + +export function axiosGetSuccess(path, data, previousAction){ + return { + type: Types.AXIOS_GET_SUCCESS, + path, + data, + previousAction + } +} + +export function axiosGetError(path, data, previousAction){ + return { + type: Types.AXIOS_GET_ERROR, + path, + data, + previousAction + } +} diff --git a/client/src/actions/login.js b/client/src/actions/login.js new file mode 100644 index 00000000..3ad925a1 --- /dev/null +++ b/client/src/actions/login.js @@ -0,0 +1,29 @@ + +export const login = () => { + return{ + type: 'SIGN_IN' + }; +}; + + + + +/* +// Old code that can be used for comparison + +export function login(name, email, id, token) { + return { + type: Types.USER_LOGIN, + name, + email, + id, + token + } +} + +export function logout() { + return { + type: Types.USER_LOGOUT, + } +} +*/ \ No newline at end of file diff --git a/client/src/actions/types.js b/client/src/actions/types.js new file mode 100644 index 00000000..3d640d40 --- /dev/null +++ b/client/src/actions/types.js @@ -0,0 +1,11 @@ +export default { + AXIOS_GET: "AXIOS_GET", + AXIOS_GET_SUCCESS: "AXIOS_GET_SUCCESS", + AXIOS_GET_ERROR: "AXIOS_GET_ERROR", + + AXIOS_POST: "AXIOS_POST", + AXIOS_POST_SUCCESS: "AXIOS_POST_SUCCESS", + AXIOS_POST_ERROR: "AXIOS_POST_ERROR", + + +} diff --git a/client/src/index.tsx b/client/src/index.tsx index e7b11a23..e6048321 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -1,13 +1,40 @@ import React from 'react' import ReactDOM from 'react-dom' +import { Provider } from 'react-redux' +import { compose, createStore } from 'redux' import App from './App' import './index.css' +import allReducers from './reducers/allReducers' import reportWebVitals from './reportWebVitals' +/* + TypeScript does not know the type of the property. + Therefore, you will get the error; Property ‘__REDUX_DEVTOOLS_EXTENSION_COMPOSE__’ + does not exist on type ‘Window’. Hence, you need to add the property to the global window as below. +*/ +declare global { + interface Window { + __REDUX_DEVTOOLS_EXTENSION__: typeof compose + } +} + +// Create an Advanced global store with the name "store" +// const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose // allows Mozilla plugin to view state in a GUI, https://github.com/zalmoxisus/redux-devtools-extension#13-use-redux-devtools-extension-package-from-npm +// const store = createStore(allReducers, composeEnhancers(applyMiddleware())) + +// simple store with plugin +const store = createStore( + allReducers, + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() +) + +// Provider wraps the app component so that it can access store ReactDOM.render( - <React.StrictMode> - <App /> - </React.StrictMode>, + <Provider store={store}> + <React.StrictMode> + <App /> + </React.StrictMode> + </Provider>, document.getElementById('root') ) diff --git a/client/src/middleware/Middleware_Explanation.txt b/client/src/middleware/Middleware_Explanation.txt new file mode 100644 index 00000000..dc4e91ab --- /dev/null +++ b/client/src/middleware/Middleware_Explanation.txt @@ -0,0 +1,6 @@ +Redux middleware provides a third-party extension point between dispatching an action, +and the moment it reaches the reducer. People use Redux middleware for logging, +crash reporting, talking to an asynchronous API, routing, and more. + + +https://redux.js.org/tutorials/fundamentals/part-4-store \ No newline at end of file diff --git a/client/src/reducers/Reducer_Explanation.txt b/client/src/reducers/Reducer_Explanation.txt new file mode 100644 index 00000000..dea1357b --- /dev/null +++ b/client/src/reducers/Reducer_Explanation.txt @@ -0,0 +1,7 @@ +A reducer is a function that receives the current state and an action object, +decides how to update the state if necessary, and returns the new state: +(state, action) => newState. +You can think of a reducer as an event listener which handles events based +on the received action (event) type. + +https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow \ No newline at end of file diff --git a/client/src/reducers/allReducers.js b/client/src/reducers/allReducers.js new file mode 100644 index 00000000..2bfcd5ea --- /dev/null +++ b/client/src/reducers/allReducers.js @@ -0,0 +1,11 @@ +// Combines all the reducers so that we only have to pass "one" reducer to the store in src/index.tsx + + +import { combineReducers } from 'redux'; +import loggedInReducer from './isLoggedIn'; + +const allReducers = combineReducers({ + // name: state + isLoggedIn: loggedInReducer // You can write "loggedInReducer" because its the same as "loggedInReducer: loggedInReducer" +}); +export default allReducers; \ No newline at end of file diff --git a/client/src/reducers/isLoggedIn.js b/client/src/reducers/isLoggedIn.js new file mode 100644 index 00000000..b665894a --- /dev/null +++ b/client/src/reducers/isLoggedIn.js @@ -0,0 +1,9 @@ +const loggedInReducer = (state = false, action) => { // isLoggedIn has an initial state of false + switch (action.type) { + case 'SIGN_IN': + return !state; + default: + return state; + } +} +export default loggedInReducer -- GitLab