diff --git a/media-store/app-src/.eslintrc.json b/media-store/app-src/.eslintrc.json index 537def27..1dfa1b45 100644 --- a/media-store/app-src/.eslintrc.json +++ b/media-store/app-src/.eslintrc.json @@ -36,6 +36,8 @@ } ], "react/jsx-props-no-spreading": "off", // props spreading, - "no-console": "off" + "no-console": "off", + "consistent-return": "off", + "prefer-destructuring": "off" } } diff --git a/media-store/app-src/package.json b/media-store/app-src/package.json index 28696e9c..a3bd4554 100644 --- a/media-store/app-src/package.json +++ b/media-store/app-src/package.json @@ -5,7 +5,8 @@ "scripts": { "start": "./node_modules/.bin/webpack-dev-server --config ./webpack/webpack-dev-server.js", "watch": "./node_modules/.bin/webpack -w --config ./webpack/webpack.dev.js", - "build": "./node_modules/.bin/webpack --config ./webpack/webpack.prod.js", + "build:dev": "./node_modules/.bin/webpack --config ./webpack/webpack.dev.js", + "build:prod": "./node_modules/.bin/webpack --config ./webpack/webpack.prod.js", "lint": "./node_modules/.bin/eslint" }, "dependencies": { diff --git a/media-store/app-src/src/api/axiosInstance.js b/media-store/app-src/src/api/axiosInstance.js index 45fc04c4..8de8d4f6 100644 --- a/media-store/app-src/src/api/axiosInstance.js +++ b/media-store/app-src/src/api/axiosInstance.js @@ -2,12 +2,17 @@ import axios from 'axios'; import { getUserFromLS, getLocaleFromLS } from '../util/localStorageService'; import { emitter } from '../util/EventEmitter'; +const TIMEOUT = 2000; +const RETRY_COUNT = 1; + /** * This is axios instance */ const axiosInstance = axios.create({ baseURL: process.env.SERVICE_URL, - timeout: 2000, + timeout: TIMEOUT, + retryDelay: TIMEOUT, + retry: RETRY_COUNT, }); /** @@ -41,7 +46,7 @@ function changeLocaleDefaults(locale) { } /** - * Initializing initial data + * Init axios defaults */ const user = getUserFromLS(); const locale = getLocaleFromLS(); @@ -49,7 +54,43 @@ changeUserDefaults(user); changeLocaleDefaults(locale); /** - * Error interceptor for refresh tokens mechanism + * Retry request if response time is too long + * See link below + * {@link https://github.com/axios/axios/issues/164#issuecomment-327837467 GitHub} + * @param {*} err response error object + */ +function axiosRetryInterceptor(err) { + const config = err.config; + // If config does not exist or the retry option is not set, reject + if (config && config.retry) { + // Set the variable for keeping track of the retry count + config.retryCount = config.retryCount || 0; + + // Check if we've maxed out the total number of retries + if (config.retryCount >= config.retry) { + // Reject with the error + return Promise.reject(err); + } + + // Increase the retry count + config.retryCount += 1; + + // Create new promise to handle exponential backoff + const backoff = new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, config.retryDelay || 1); + }); + + // Return the promise in which recalls axios to retry the request + return backoff.then(() => { + return axios(config); + }); + } +} + +/** + * Things below needed for refresh tokens mechanism implementation */ let isRefreshing = false; let subscribers = []; @@ -62,7 +103,14 @@ const refreshTokens = (refreshToken) => { } ); }; -axiosInstance.interceptors.response.use(null, (error) => { + +/** + * Refresh tokens interceptor + * See link below + * {@link https://gist.github.com/mkjiau/650013a99c341c9f23ca00ccb213db1c#gistcomment-3536511 GitHub} + * @param {*} error error response object + */ +function axiosRefreshTokensInterceptor(error) { const originalRequest = error.config; const user = getUserFromLS(); @@ -109,8 +157,12 @@ axiosInstance.interceptors.response.use(null, (error) => { }); }); } +} - return Promise.reject(error); +axiosInstance.interceptors.response.use(null, (error) => { + return ( + axiosRefreshTokensInterceptor(error) || axiosRetryInterceptor(error) || Promise.reject(error) + ); }); export { axiosInstance, changeLocaleDefaults, changeUserDefaults }; diff --git a/media-store/app-src/src/components/Header.jsx b/media-store/app-src/src/components/Header.jsx index 9a509407..7dd719d9 100644 --- a/media-store/app-src/src/components/Header.jsx +++ b/media-store/app-src/src/components/Header.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Menu, Badge, Spin } from 'antd'; +import { Menu, Badge, Spin, message } from 'antd'; import { isEmpty } from 'lodash'; import { CreditCardOutlined, @@ -13,7 +13,7 @@ import { setLocaleToLS } from '../util/localStorageService'; import { changeLocaleDefaults } from '../api/axiosInstance'; import { emitter } from '../util/EventEmitter'; import './Header.css'; -import { requireEmployee, requireCustomer } from '../util/constants'; +import { requireEmployee, requireCustomer, MESSAGE_TIMEOUT } from '../util/constants'; const { SubMenu } = Menu; @@ -24,7 +24,7 @@ const RELOAD_LOCATION_NUMBER = 0; const Header = () => { const history = useHistory(); const location = useLocation(); - const { user, invoicedItems, setInvoicedItems, locale, setLocale, loading } = useAppState(); + const { user, invoicedItems, locale, setLocale, loading } = useAppState(); const currentKey = [keys.find((key) => key === location.pathname)]; const haveInvoicedItems = !isEmpty(invoicedItems); const invoicedItemsLength = invoicedItems.length; @@ -45,7 +45,11 @@ const Header = () => { const onUserLogout = () => { emitter.emit('UPDATE_USER', undefined); - history.go(0); + message.warn( + 'Now you are not authenticated. Log in to use full functionality', + MESSAGE_TIMEOUT + ); + history.push('/'); }; return ( diff --git a/media-store/app/.gitignore b/media-store/app/.gitignore deleted file mode 100644 index 4d29575d..00000000 --- a/media-store/app/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/media-store/app/.vscode/launch.json b/media-store/app/.vscode/launch.json deleted file mode 100644 index d4e0b5d5..00000000 --- a/media-store/app/.vscode/launch.json +++ /dev/null @@ -1,13 +0,0 @@ - -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Chrome", - "type": "chrome", - "request": "launch", - "url": "http://localhost:3000", - "webRoot": "${workspaceRoot}/src" - } - ] -} \ No newline at end of file diff --git a/media-store/package.json b/media-store/package.json index 1bc56dea..334f1a55 100644 --- a/media-store/package.json +++ b/media-store/package.json @@ -10,9 +10,9 @@ "private": true, "dependencies": { "@sap/cds": "^4.2.8", - "@sap/hana-client": "^2.6.61", "bcryptjs": "^2.4.3", "express": "^4", + "hdb": "^0.18.2", "jsonwebtoken": "^8.5.1", "moment": "^2.29.1", "passport": "^0.4.1"