diff --git a/media-store/README.md b/media-store/README.md
index a75fab77..e93c0d68 100644
--- a/media-store/README.md
+++ b/media-store/README.md
@@ -4,18 +4,18 @@ Welcome to your new project.
It contains these folders and files, following our recommended project layout:
-| File or Folder | Purpose |
-| -------------- | ------------------------------------ |
-| `app/` | will contain compiled front bundles |
-| `app-src/` | contains frontend app on react |
-| `deployers/` | contains deployment staff |
-| `db/` | your domain models and data go here |
-| `srv/` | your service models and code go here |
-| `test/` | your services tests |
-| `package.json` | project metadata and configuration |
-| `mta.yaml` | deployment config |
-| `readme.md` | this getting started guide |
-| `server.js` | initial server set up |
+| File or Folder | Purpose |
+|------------------|--------------------------------------|
+| `app/` | will contain compiled front bundles |
+| `app/react/` | contains frontend app on react |
+| `app/deployers/` | contains deployment staff |
+| `db/` | your domain models and data go here |
+| `srv/` | your service models and code go here |
+| `test/` | your services tests |
+| `package.json` | project metadata and configuration |
+| `mta.yaml` | deployment config |
+| `readme.md` | this getting started guide |
+| `server.js` | initial server set up |
## Development
@@ -31,7 +31,7 @@ npm run deploy
cds watch
```
-- Open `app-src` folder and run next commands. This will install dependencies and run frontend src files watcher. When you will change src files your bundles in app directory will re-compiled. Now you can enjoy development:
+- Open `app/react` folder and run next commands. This will install dependencies and run frontend src files watcher. When you will change src files your bundles in app directory will re-compiled. Now you can enjoy development:
```json
npm install
@@ -62,14 +62,14 @@ npm run watch
cf login
```
-- Open `app-src` folder and run the following commands. This will create frontend production bundles in app subfolder:
+- Open `app/react` folder and run the following commands. This will create frontend production bundles in app subfolder:
```json
npm install
npm run build
```
-- Clean up deployers/html5Deployer/resources folder from the previous frontend build
+- Clean up app/deployers/html5Deployer/resources folder from the previous frontend build
- From root directory run:
diff --git a/media-store/app-src/.babelrc b/media-store/app-src/.babelrc
deleted file mode 100644
index d3472902..00000000
--- a/media-store/app-src/.babelrc
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "presets": ["@babel/preset-react", "@babel/preset-env"],
- "plugins": ["@babel/plugin-transform-runtime", "babel-plugin-syntax-dynamic-import"]
-}
-
\ No newline at end of file
diff --git a/media-store/app-src/.eslintrc.json b/media-store/app-src/.eslintrc.json
deleted file mode 100644
index 1dfa1b45..00000000
--- a/media-store/app-src/.eslintrc.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "env": {
- "browser": true,
- "es2020": true
- },
- "extends": ["plugin:react/recommended", "airbnb", "prettier"],
- "parserOptions": {
- "ecmaFeatures": {
- "jsx": true
- },
- "ecmaVersion": 11,
- "sourceType": "module"
- },
- "plugins": ["react", "prettier"],
- "rules": {
- "prettier/prettier": ["error", { "parser": "flow", "endOfLine": "auto" }],
- "linebreak-style": [0, "error", "windows"],
- "import/prefer-default-export": "off",
- "no-shadow": "off",
- "react/forbid-prop-types": "off",
- "no-alert": "off",
- "jsx-a11y/label-has-associated-control": [
- "error",
- {
- "required": {
- "some": ["nesting", "id"]
- }
- }
- ],
- "jsx-a11y/label-has-for": [
- "error",
- {
- "required": {
- "some": ["nesting", "id"]
- }
- }
- ],
- "react/jsx-props-no-spreading": "off", // props spreading,
- "no-console": "off",
- "consistent-return": "off",
- "prefer-destructuring": "off"
- }
-}
diff --git a/media-store/app-src/.gitignore b/media-store/app-src/.gitignore
deleted file mode 100644
index 4d29575d..00000000
--- a/media-store/app-src/.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-src/.prettierrc b/media-store/app-src/.prettierrc
deleted file mode 100644
index 5ac85e27..00000000
--- a/media-store/app-src/.prettierrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "printWidth": 100,
- "singleQuote": true
-}
diff --git a/media-store/app-src/.vscode/launch.json b/media-store/app-src/.vscode/launch.json
deleted file mode 100644
index d4e0b5d5..00000000
--- a/media-store/app-src/.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/app-src/README.md b/media-store/app-src/README.md
deleted file mode 100644
index 269c0546..00000000
--- a/media-store/app-src/README.md
+++ /dev/null
@@ -1 +0,0 @@
-"# Media store UI"
diff --git a/media-store/app-src/package.json b/media-store/app-src/package.json
deleted file mode 100644
index 457556aa..00000000
--- a/media-store/app-src/package.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
- "name": "mediastore",
- "version": "0.1.0",
- "private": false,
- "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: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": {
- "@testing-library/jest-dom": "^4.2.4",
- "@testing-library/react": "^9.3.2",
- "@testing-library/user-event": "^7.1.2",
- "@umijs/hooks": "^1.9.3",
- "antd": "^4.8.2",
- "@ant-design/icons": "4.3.0",
- "axios": "^0.20.0",
- "clean-webpack-plugin": "^3.0.0",
- "copy-webpack-plugin": "^6.3.2",
- "css-minimizer-webpack-plugin": "^1.1.5",
- "events": "^3.2.0",
- "html-webpack-plugin": "^4.5.0",
- "lodash": "^4.17.20",
- "mini-css-extract-plugin": "^1.3.1",
- "moment": "^2.29.1",
- "prop-types": "^15.7.2",
- "react": "^16.14.0",
- "react-dev-utils": "^11.0.1",
- "react-dom": "^16.14.0",
- "react-router-dom": "^5.2.0",
- "terser-webpack-plugin": "^5.0.3",
- "webpack": "5.8.0",
- "webpack-dev-server": "^3.11.0",
- "webpack-merge": "^5.4.0"
- },
- "devDependencies": {
- "@babel/core": "^7.12.9",
- "@babel/plugin-transform-runtime": "^7.12.1",
- "@babel/polyfill": "^7.12.1",
- "@babel/preset-env": "^7.12.7",
- "@babel/preset-react": "^7.12.7",
- "@babel/runtime": "^7.12.5",
- "babel-loader": "^8.2.2",
- "babel-plugin-syntax-dynamic-import": "^6.18.0",
- "cowsay": "^1.4.0",
- "css-loader": "^5.0.1",
- "eslint": "^7.14.0",
- "eslint-config-airbnb": "^18.2.1",
- "eslint-config-prettier": "^6.15.0",
- "eslint-plugin-import": "^2.22.1",
- "eslint-plugin-jsx-a11y": "^6.4.1",
- "eslint-plugin-prettier": "^3.1.4",
- "eslint-plugin-react": "^7.21.5",
- "eslint-plugin-react-hooks": "^4.2.0",
- "prettier": "^2.2.1",
- "style-loader": "^2.0.0",
- "url-loader": "^4.1.1",
- "webpack-cli": "^3.3.12"
- },
- "eslintConfig": {
- "extends": "react-app"
- }
-}
diff --git a/media-store/app-src/public/index.html b/media-store/app-src/public/index.html
deleted file mode 100644
index e2722955..00000000
--- a/media-store/app-src/public/index.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
- React App
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/media-store/app-src/public/logo192.png b/media-store/app-src/public/logo192.png
deleted file mode 100644
index fc44b0a3..00000000
Binary files a/media-store/app-src/public/logo192.png and /dev/null differ
diff --git a/media-store/app-src/public/logo512.png b/media-store/app-src/public/logo512.png
deleted file mode 100644
index a4e47a65..00000000
Binary files a/media-store/app-src/public/logo512.png and /dev/null differ
diff --git a/media-store/app-src/public/manifest.json b/media-store/app-src/public/manifest.json
deleted file mode 100644
index 45979ace..00000000
--- a/media-store/app-src/public/manifest.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "short_name": "React App",
- "name": "Create React App Sample",
- "icons": [
- {
- "src": "favicon.ico",
- "sizes": "64x64 32x32 24x24 16x16",
- "type": "image/x-icon"
- },
- {
- "src": "logo192.png",
- "type": "image/png",
- "sizes": "192x192"
- },
- {
- "src": "logo512.png",
- "type": "image/png",
- "sizes": "512x512"
- }
- ],
- "start_url": ".",
- "display": "standalone",
- "theme_color": "#000000",
- "background_color": "#ffffff",
- "sap.app": {
- "id": "mediastore",
- "applicationVersion": {
- "version": "1.0.0"
- }
- }
-}
diff --git a/media-store/app-src/public/robots.txt b/media-store/app-src/public/robots.txt
deleted file mode 100644
index e9e57dc4..00000000
--- a/media-store/app-src/public/robots.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-# https://www.robotstxt.org/robotstxt.html
-User-agent: *
-Disallow:
diff --git a/media-store/app-src/public/xs-app.json b/media-store/app-src/public/xs-app.json
deleted file mode 100644
index 930c40ee..00000000
--- a/media-store/app-src/public/xs-app.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "welcomeFile": "/index.html",
- "routes": [
- {
- "source": "^(.*)",
- "target": "$1",
- "service": "html5-apps-repo-rt"
- }
- ]
-}
\ No newline at end of file
diff --git a/media-store/app-src/src/App.css b/media-store/app-src/src/App.css
deleted file mode 100644
index 1ec8f2fe..00000000
--- a/media-store/app-src/src/App.css
+++ /dev/null
@@ -1,57 +0,0 @@
-@import "~antd/dist/antd.css";
-
-html {
- overflow: hidden;
-}
-#root {
- height: 100%;
-}
-section.ant-layout {
- height: 100vh;
- overflow: auto;
-}
-
-/* Layout
-*/
-.site-layout .site-layout-background {
- background: #fff;
-}
-
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
-
-.App-link {
- color: #61dafb;
-}
-
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/media-store/app-src/src/App.jsx b/media-store/app-src/src/App.jsx
deleted file mode 100644
index d1657522..00000000
--- a/media-store/app-src/src/App.jsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react';
-import 'antd/dist/antd.css';
-import './App.css';
-import { Layout } from 'antd';
-import { MyRouter } from './components/Router';
-import { AppStateContextProvider } from './contexts/AppStateContext';
-
-const App = () => {
- return (
-
-
-
-
-
- );
-};
-
-export default App;
diff --git a/media-store/app-src/src/api/axiosInstance.js b/media-store/app-src/src/api/axiosInstance.js
deleted file mode 100644
index 2be83d03..00000000
--- a/media-store/app-src/src/api/axiosInstance.js
+++ /dev/null
@@ -1,168 +0,0 @@
-import axios from 'axios';
-import { getUserFromLS, getLocaleFromLS } from '../util/localStorageService';
-import { emitter } from '../util/EventEmitter';
-
-const TIMEOUT = 2000;
-const RETRY_COUNT = 3;
-
-/**
- * This is axios instance
- */
-const axiosInstance = axios.create({
- baseURL: process.env.SERVICE_URL,
- timeout: TIMEOUT,
- retryDelay: TIMEOUT,
- retry: RETRY_COUNT,
-});
-
-/**
- * Changing user axios default params,
- * which are used in api call functions (calls.js)
- * @param {*} currentUser current user from react state and local storage
- */
-function changeUserDefaults(currentUser) {
- if (currentUser) {
- axiosInstance.defaults.headers.common.Authorization = `Basic ${currentUser.accessToken}`;
- axiosInstance.defaults.userID = currentUser.ID;
- if (currentUser.roles.includes('customer')) {
- axiosInstance.defaults.userEntity = `Customers/${currentUser.ID}`;
- axiosInstance.defaults.tracksEntity = 'MarkedTracks';
- } else {
- axiosInstance.defaults.userEntity = `Employees/${currentUser.ID}`;
- axiosInstance.defaults.tracksEntity = 'Tracks';
- }
- } else {
- axiosInstance.defaults.tracksEntity = 'Tracks';
- }
-}
-/**
- * This func changing axios instance default params
- * @param {*} locale current locale from react state and local storage
- */
-function changeLocaleDefaults(locale) {
- if (locale) {
- axiosInstance.defaults.headers.common['Accept-language'] = locale;
- }
-}
-
-/**
- * Init axios defaults
- */
-const user = getUserFromLS();
-const locale = getLocaleFromLS();
-changeUserDefaults(user);
-changeLocaleDefaults(locale);
-
-/**
- * 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 = [];
-const refreshTokens = (refreshToken) => {
- return axiosInstance.post(
- 'users/refreshTokens',
- { refreshToken },
- {
- headers: { 'content-type': 'application/json' },
- }
- );
-};
-
-/**
- * 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();
-
- if (error.response && error.response.status === 401 && !!user) {
- if (originalRequest.url === 'users/login') {
- return Promise.reject(error);
- }
-
- // if users/refreshTokens request failed
- if (isRefreshing && originalRequest.url === 'users/refreshTokens') {
- subscribers.forEach((request) => request.reject(error));
- subscribers = [];
- isRefreshing = false;
- return Promise.reject(error);
- }
-
- // if got a 401 error we sending users/refreshTokens request
- if (!isRefreshing) {
- isRefreshing = true;
-
- refreshTokens(user.refreshToken)
- .then((response) => {
- emitter.emit('UPDATE_USER', response.data);
- subscribers.forEach((request) => request.resolve(response.data.accessToken));
- subscribers = [];
- isRefreshing = false;
- })
- .catch(() => {
- emitter.emit('UPDATE_USER', undefined);
- });
- }
-
- // holding requests which should be sended after users/refreshTokens complete
- // otherwise if users/refreshTokens failed an error will be thrown
- return new Promise((resolve, reject) => {
- subscribers.push({
- resolve: (newAccessToken) => {
- originalRequest.headers.Authorization = `Basic ${newAccessToken}`;
- resolve(axiosInstance(originalRequest));
- },
- reject: (err) => {
- reject(err);
- },
- });
- });
- }
-}
-
-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/api/calls.js b/media-store/app-src/src/api/calls.js
deleted file mode 100644
index 10b6abb5..00000000
--- a/media-store/app-src/src/api/calls.js
+++ /dev/null
@@ -1,164 +0,0 @@
-import { isEmpty } from 'lodash';
-import { axiosInstance } from './axiosInstance';
-
-const BROWSE_TRACKS_SERVICE = 'browse-tracks';
-const INVOICES_SERVICE = 'browse-invoices';
-const USER_SERVICE = 'users';
-const MANAGE_STORE = 'manage-store';
-
-const constructGenresQuery = (genreIds) => {
- return !isEmpty(genreIds)
- ? ` and ${genreIds.map((value) => `genre_ID eq ${value}`).join(' or ')}`
- : '';
-};
-
-const fetchTacks = ({ $top = 20, $skip = 0, genreIds = [], substr = '' } = {}) => {
- const serializeTracksUrl = () => {
- return `$expand=genre,album($expand=artist)&$top=${$top}&$skip=${$skip}&$filter=${`contains(name,'${substr}')${constructGenresQuery(
- genreIds
- )}`}`;
- };
-
- return axiosInstance.get(`${BROWSE_TRACKS_SERVICE}/${axiosInstance.defaults.tracksEntity}`, {
- params: {},
- paramsSerializer: () => serializeTracksUrl(),
- });
-};
-
-const countTracks = ({ genreIds = [], substr = '' } = {}) => {
- const { tracksEntity } = axiosInstance.defaults;
-
- return axiosInstance.get(
- `${BROWSE_TRACKS_SERVICE}/${tracksEntity}/$count?$filter=${`contains(name,'${substr}')${constructGenresQuery(
- genreIds
- )}`}`
- );
-};
-
-const fetchGenres = () => {
- return axiosInstance.get(`${BROWSE_TRACKS_SERVICE}/Genres`);
-};
-
-const invoice = (tracks) => {
- return axiosInstance.post(
- `${INVOICES_SERVICE}/invoice`,
- {
- tracks,
- },
- {
- headers: { 'content-type': 'application/json' },
- }
- );
-};
-
-const fetchPerson = () => {
- return axiosInstance.get(`${USER_SERVICE}/${axiosInstance.defaults.userEntity}`);
-};
-
-const confirmPerson = (person) => {
- return axiosInstance.put(
- `${USER_SERVICE}/${axiosInstance.defaults.userEntity}`,
- {
- ...person,
- },
- {
- headers: { 'content-type': 'application/json' },
- }
- );
-};
-
-const fetchInvoices = () => {
- return axiosInstance.get(
- `${INVOICES_SERVICE}/Invoices?$expand=invoiceItems($expand=track($expand=album($expand=artist)))`
- );
-};
-
-const cancelInvoice = (ID) => {
- return axiosInstance.post(
- `${INVOICES_SERVICE}/cancelInvoice`,
- {
- ID,
- },
- {
- headers: { 'content-type': 'application/json' },
- }
- );
-};
-
-const fetchAlbumsByName = (substr = '', top) => {
- return axiosInstance.get(
- `${BROWSE_TRACKS_SERVICE}/Albums?$filter=${`contains(title,'${substr}')&$top=${top}`}`
- );
-};
-
-const addTrack = (data) => {
- return axiosInstance.post(`${MANAGE_STORE}/Tracks`, data, {
- headers: { 'content-type': 'application/json;IEEE754Compatible=true' },
- });
-};
-
-const addArtist = (data) => {
- return axiosInstance.post(`${MANAGE_STORE}/Artists`, data, {
- headers: { 'content-type': 'application/json' },
- });
-};
-
-const addAlbum = (data) => {
- return axiosInstance.post(`${MANAGE_STORE}/Albums`, data, {
- headers: { 'content-type': 'application/json' },
- });
-};
-
-const fetchArtistsByName = (substr = '', top) => {
- return axiosInstance.get(
- `${MANAGE_STORE}/Artists?$filter=${`contains(name,'${substr}')&$top=${top}`}`
- );
-};
-
-const login = (data) => {
- return axiosInstance.post(`${USER_SERVICE}/login`, data, {
- headers: { 'content-type': 'application/json' },
- });
-};
-
-const updateTrack = (track) => {
- return axiosInstance.put(
- `${MANAGE_STORE}/Tracks/${track.ID}`,
- {
- ...track,
- },
- {
- headers: { 'content-type': 'application/json;IEEE754Compatible=true' },
- }
- );
-};
-
-const getTrack = (ID) => {
- return axiosInstance.get(
- `${BROWSE_TRACKS_SERVICE}/${axiosInstance.defaults.tracksEntity}/${ID}?$expand=genre,album($expand=artist)`
- );
-};
-
-const deleteTrack = (ID) => {
- return axiosInstance.delete(`${MANAGE_STORE}/Tracks(${ID})`);
-};
-
-export {
- fetchTacks,
- countTracks,
- fetchGenres,
- invoice,
- fetchPerson,
- confirmPerson,
- fetchInvoices,
- cancelInvoice,
- fetchAlbumsByName,
- addTrack,
- addArtist,
- addAlbum,
- fetchArtistsByName,
- login,
- updateTrack,
- getTrack,
- deleteTrack,
-};
diff --git a/media-store/app-src/src/components/ErrorPage.jsx b/media-store/app-src/src/components/ErrorPage.jsx
deleted file mode 100644
index e39c7f52..00000000
--- a/media-store/app-src/src/components/ErrorPage.jsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import React from 'react';
-import { useHistory } from 'react-router-dom';
-import { isEmpty } from 'lodash';
-import { Result, Button } from 'antd';
-import { useAppState } from '../hooks/useAppState';
-
-const ErrorPage = () => {
- const { error, setError } = useAppState();
- const history = useHistory();
-
- const onGoHome = () => {
- setError({});
- history.push('/');
- };
-
- const goLoginPage = () => {
- setError({});
- history.push('/login');
- };
-
- const goHomeButton = (
-
- );
- const goLoginButton = (
-
- );
-
- const errorResultProps = isEmpty(error)
- ? {
- status: 404,
- title: 'Not found',
- subTitle: 'Sorry, the page you visited does not exist.',
- extra: goHomeButton,
- }
- : {
- status: [404, 403, 500].includes(error.status) ? error.status : 'error',
- title: error.statusText,
- subTitle: error.message,
- extra: error.status === 401 ? [goHomeButton, goLoginButton] : goHomeButton,
- };
-
- return ;
-};
-
-export default ErrorPage;
diff --git a/media-store/app-src/src/components/Header.css b/media-store/app-src/src/components/Header.css
deleted file mode 100644
index 3d78184d..00000000
--- a/media-store/app-src/src/components/Header.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.ant-menu-item .anticon {
- margin: 0;
-}
diff --git a/media-store/app-src/src/components/Header.jsx b/media-store/app-src/src/components/Header.jsx
deleted file mode 100644
index a965ff8c..00000000
--- a/media-store/app-src/src/components/Header.jsx
+++ /dev/null
@@ -1,141 +0,0 @@
-import React from 'react';
-import { Menu, Badge, Spin, message } from 'antd';
-import { isEmpty } from 'lodash';
-import {
- CreditCardOutlined,
- LogoutOutlined,
- LoginOutlined,
- LoadingOutlined,
-} from '@ant-design/icons';
-import { useHistory, useLocation } from 'react-router-dom';
-import { useAppState } from '../hooks/useAppState';
-import { setLocaleToLS } from '../util/localStorageService';
-import { changeLocaleDefaults } from '../api/axiosInstance';
-import { emitter } from '../util/EventEmitter';
-import './Header.css';
-import { requireEmployee, requireCustomer, MESSAGE_TIMEOUT } from '../util/constants';
-
-const { SubMenu } = Menu;
-
-const keys = ['/', '/person', '/login', '/manage', '/invoice', '/invoices'];
-const AVAILABLE_LOCALES = ['en', 'fr', 'de'];
-const RELOAD_LOCATION_NUMBER = 0;
-
-const Header = () => {
- const history = useHistory();
- const location = useLocation();
- const { user, invoicedItems, locale, setLocale, loading } = useAppState();
- const currentKey = [keys.find((key) => key === location.pathname)];
- const haveInvoicedItems = !isEmpty(invoicedItems);
- const invoicedItemsLength = invoicedItems.length;
-
- const onChangeLocale = (value) => {
- setLocaleToLS(value);
- changeLocaleDefaults(value);
- setLocale(value);
- history.go(RELOAD_LOCATION_NUMBER);
- };
- const localeElements = AVAILABLE_LOCALES.filter((localeName) => localeName !== locale).map(
- (curLocale) => (
- onChangeLocale(curLocale)}>
- {curLocale}
-
- )
- );
-
- const onUserLogout = () => {
- emitter.emit('UPDATE_USER', undefined);
- message.warn(
- 'Now you are not authenticated. Log in to use full functionality',
- MESSAGE_TIMEOUT
- );
- history.push('/');
- };
-
- return (
-
-
-
-
-
- );
-};
-
-export default Header;
diff --git a/media-store/app-src/src/components/InvoicePage.jsx b/media-store/app-src/src/components/InvoicePage.jsx
deleted file mode 100644
index 505ccd9a..00000000
--- a/media-store/app-src/src/components/InvoicePage.jsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import React from 'react';
-import { Table, Button, message } from 'antd';
-import { useHistory } from 'react-router-dom';
-import { useAppState } from '../hooks/useAppState';
-import { invoice } from '../api/calls';
-import { useErrors } from '../hooks/useErrors';
-import { MESSAGE_TIMEOUT } from '../util/constants';
-
-const columns = [
- {
- title: 'Name',
- dataIndex: 'name',
- },
- {
- title: 'Artist',
- dataIndex: 'artist',
- },
- {
- title: 'Album',
- dataIndex: 'albumTitle',
- },
- {
- title: 'Price',
- dataIndex: 'unitPrice',
- },
-];
-
-const InvoicePage = () => {
- const history = useHistory();
- const { handleError } = useErrors();
- const { user, invoicedItems, setInvoicedItems, setLoading } = useAppState();
-
- const data = invoicedItems.map(({ ID, ...otherProps }) => ({
- key: `invoiceItem${ID}`,
- ...otherProps,
- }));
-
- const onBuy = () => {
- setLoading(true);
- invoice(
- invoicedItems.map(({ ID }) => ({
- ID,
- }))
- )
- .then(() => {
- setInvoicedItems([]);
- message.success('Invoice successfully completed', MESSAGE_TIMEOUT);
- history.push('/invoices');
- })
- .catch(handleError)
- .finally(() => setLoading(false));
- };
- const onCancel = () => {
- setInvoicedItems([]);
- history.push('/');
- };
- const goLogin = () => {
- history.push('/login');
- };
-
- return (
-
-
(
-
- {user ? (
- <>
-
-
- >
- ) : (
-
-
- to buy selected
-
- )}
-
- )}
- />
-
- );
-};
-
-export default InvoicePage;
diff --git a/media-store/app-src/src/components/Login.jsx b/media-store/app-src/src/components/Login.jsx
deleted file mode 100644
index 91ca97e8..00000000
--- a/media-store/app-src/src/components/Login.jsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import React from 'react';
-import { Form, Input, Button, Checkbox, message } from 'antd';
-import { useHistory } from 'react-router-dom';
-import { login } from '../api/calls';
-import { useAppState } from '../hooks/useAppState';
-import { useErrors } from '../hooks/useErrors';
-import { MESSAGE_TIMEOUT } from '../util/constants';
-import { emitter } from '../util/EventEmitter';
-
-const layout = {
- labelCol: {
- span: 8,
- },
- wrapperCol: {
- span: 8,
- },
-};
-const tailLayout = {
- wrapperCol: {
- offset: 8,
- span: 8,
- },
-};
-
-const Login = () => {
- const [form] = Form.useForm();
- const history = useHistory();
- const { setLoading, setInvoicedItems } = useAppState();
- const { handleError } = useErrors();
-
- const onFinish = (values) => {
- setLoading(true);
- login({ email: values.email, password: values.password })
- .then(({ data: user }) => {
- emitter.emit('UPDATE_USER', user);
- if (user.roles.includes('employee')) {
- setInvoicedItems([]);
- }
- history.push('/');
- })
- .catch((error) => {
- console.log(error);
- if (error.response && error.response.status === 401) {
- form.resetFields();
- message.error('Invalid credentials!', MESSAGE_TIMEOUT);
- } else {
- handleError(error);
- }
- })
- .finally(() => setLoading(false));
- };
-
- const onFinishFailed = (errorInfo) => {
- console.log('Validation Failed:', errorInfo);
- };
-
- return (
-
-
-
-
-
-
-
-
-
- Remember me
-
-
-
-
-
-
- );
-};
-
-export default Login;
diff --git a/media-store/app-src/src/components/ManageStore.jsx b/media-store/app-src/src/components/ManageStore.jsx
deleted file mode 100644
index 71167a7c..00000000
--- a/media-store/app-src/src/components/ManageStore.jsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import React, { useState, useMemo, useEffect } from 'react';
-import { Form, Radio, Button, message } from 'antd';
-import { TrackForm } from './manage-store/TrackForm';
-import { AddArtistForm } from './manage-store/AddArtistForm';
-import { AddAlbumForm } from './manage-store/AddAlbumForm';
-import { useErrors } from '../hooks/useErrors';
-import { useAppState } from '../hooks/useAppState';
-import { addTrack, addArtist, addAlbum } from '../api/calls';
-import { MESSAGE_TIMEOUT } from '../util/constants';
-
-const FORM_TYPES = {
- track: 'track',
- artist: 'artist',
- album: 'album',
- playlist: '',
-};
-
-const chooseForm = (type) => {
- return (
- (type === 'track' && ) ||
- (type === 'artist' && ) ||
- (type === 'album' && )
- );
-};
-
-const ManageStore = () => {
- const [form] = Form.useForm();
- const { handleError } = useErrors();
- const { setLoading } = useAppState();
- const [formType, setFormType] = useState('track');
-
- useEffect(() => {
- form.resetFields();
- }, [formType]);
-
- const formElement = useMemo(() => {
- return chooseForm(formType);
- }, [formType]);
-
- const onChangeForm = (event) => {
- setFormType(event.target.value);
- };
-
- const sendCreateRequest = ({ type, ...data }) => {
- setLoading(true);
-
- let promise;
- switch (type) {
- case FORM_TYPES.track:
- promise = addTrack({
- name: data.name,
- composer: data.composer,
- album: { ID: data.albumID },
- genre: { ID: data.genreID },
- unitPrice: data.unitPrice.toString(),
- });
- break;
- case FORM_TYPES.artist:
- promise = addArtist(data);
- break;
- case FORM_TYPES.album:
- promise = addAlbum({ title: data.name, artist: { ID: data.artistID } });
- break;
- default:
- }
-
- promise
- .then(() => {
- message.success('Entity successfully created', MESSAGE_TIMEOUT);
- form.resetFields();
- })
- .catch(handleError)
- .finally(() => setLoading(false));
- };
-
- return (
-
-
- Track
- Album
- Artist
-
-
- {formElement}
-
-
-
-
- );
-};
-
-export default ManageStore;
diff --git a/media-store/app-src/src/components/MyInvoicesPage.jsx b/media-store/app-src/src/components/MyInvoicesPage.jsx
deleted file mode 100644
index bb490282..00000000
--- a/media-store/app-src/src/components/MyInvoicesPage.jsx
+++ /dev/null
@@ -1,170 +0,0 @@
-import React, { useState, useEffect, useMemo, useCallback } from 'react';
-import PropTypes from 'prop-types';
-import { Button, message, Tag, Collapse, Table, Spin } from 'antd';
-import moment from 'moment';
-import { useErrors } from '../hooks/useErrors';
-import { useAppState } from '../hooks/useAppState';
-import { cancelInvoice, fetchInvoices } from '../api/calls';
-import { MESSAGE_TIMEOUT } from '../util/constants';
-
-const { Panel } = Collapse;
-const INVOICE_STATUS = {
- 2: {
- tagTitle: 'Shipped',
- color: 'green',
- },
- 1: {
- tagTitle: 'Submitted',
- color: 'processing',
- canCancel: true,
- },
- '-1': {
- tagTitle: 'Cancelled',
- color: 'default',
- },
-};
-const CANCELLED_STATUS = -1;
-const DATE_TIME_FORMAT_PATTERN = 'LLLL';
-const UTC_DATE_TIME_FORMAT = 'YYYY-MM-DDThh:mm:ss';
-const INVOICE_ITEMS_COLUMNS = [
- {
- title: 'Track name',
- dataIndex: 'name',
- },
- {
- title: 'Artist',
- dataIndex: 'artistName',
- },
- {
- title: 'Album',
- dataIndex: 'albumTitle',
- },
- {
- title: 'Price',
- dataIndex: 'unitPrice',
- },
-];
-const LEVERAGE_DURATION = 1; // in hours
-const STATUSES = { submitted: 1, shipped: 2, canceled: -1 };
-
-const isLeverageTimeExpired = (utcNowTimestamp, invoiceDate) => {
- const duration = moment.duration(moment(utcNowTimestamp).diff(moment(invoiceDate).valueOf()));
- return duration.asHours() > LEVERAGE_DURATION;
-};
-
-const chooseStatus = (utcNowTimestamp, invoiceDate, statusFromDb) => {
- if (isLeverageTimeExpired(utcNowTimestamp, invoiceDate) && statusFromDb !== STATUSES.canceled) {
- return INVOICE_STATUS[STATUSES.shipped];
- }
- return INVOICE_STATUS[statusFromDb];
-};
-
-const ExtraHeader = ({ ID, invoiceDate, status: initialStatus }) => {
- const { loading, setLoading } = useAppState();
- const { handleError } = useErrors();
- const [loadingHeaderId, setLoadingHeaderId] = useState();
- const [status, setStatus] = useState(initialStatus);
-
- const statusConfig = useMemo(() => {
- const utcNowTimestamp = moment(moment().utc().format(UTC_DATE_TIME_FORMAT)).valueOf();
- return chooseStatus(utcNowTimestamp, invoiceDate, status);
- }, [status]);
-
- const onCancelInvoice = (event, ID) => {
- event.stopPropagation();
- setLoading(true);
- setLoadingHeaderId(ID);
- cancelInvoice(ID)
- .then(() => {
- message.success('Invoice successfully cancelled', MESSAGE_TIMEOUT);
- setLoadingHeaderId(undefined);
- setStatus(CANCELLED_STATUS);
- })
- .catch(handleError)
- .finally(() => setLoading(false));
- };
-
- return (
-
- {statusConfig.tagTitle}
- {statusConfig.canCancel && (
-
- )}
-
- );
-};
-ExtraHeader.propTypes = {
- ID: PropTypes.number.isRequired,
- status: PropTypes.number.isRequired,
- invoiceDate: PropTypes.string.isRequired,
-};
-
-const MyInvoicesPage = () => {
- const { handleError } = useErrors();
- const { setLoading } = useAppState();
- const [invoices, setInvoices] = useState([]);
-
- useEffect(() => {
- setLoading(true);
- fetchInvoices()
- .then(({ data: { value } }) => setInvoices(value))
- .catch(handleError)
- .finally(() => setLoading(false));
- }, []);
-
- const genExtra = useCallback(
- (ID, status, invoiceDate) => ,
- []
- );
- const invoiceElements = useMemo(() => {
- return invoices.map(({ ID, status, invoiceDate, total, invoiceItems }) => {
- const invoiceItemsData = invoiceItems.map(
- ({
- ID,
- track: {
- name,
- unitPrice,
- album: {
- title: albumTitle,
- artist: { name: artistName },
- },
- },
- }) => ({
- key: ID,
- ID,
- name,
- unitPrice,
- albumTitle,
- artistName,
- })
- );
-
- return (
-
-
-
{`Total price: ${total}`}}
- />
-
-
- );
- });
- }, [invoices]);
-
- return (
- {invoiceElements && {invoiceElements}}
- );
-};
-
-export default MyInvoicesPage;
diff --git a/media-store/app-src/src/components/PersonPage.jsx b/media-store/app-src/src/components/PersonPage.jsx
deleted file mode 100644
index d312a233..00000000
--- a/media-store/app-src/src/components/PersonPage.jsx
+++ /dev/null
@@ -1,108 +0,0 @@
-import React, { useState } from 'react';
-import { Form, Button, message, Input } from 'antd';
-import { omit, map } from 'lodash';
-import { fetchPerson, confirmPerson } from '../api/calls';
-import { useErrors } from '../hooks/useErrors';
-import { useAppState } from '../hooks/useAppState';
-import { MESSAGE_TIMEOUT } from '../util/constants';
-import { useAbortableEffect } from '../hooks/useAbortableEffect';
-
-const PERSON_PROP = {
- address: 'Address ',
- city: 'City ',
- country: 'Country ',
- fax: 'Fax: ',
- firstName: 'First name: ',
- lastName: 'Last name: ',
- phone: 'Phone: ',
- postalCode: 'Postal code: ',
- state: 'State',
- email: 'email',
- company: 'Company: ',
-};
-
-const PersonPage = () => {
- const { setLoading } = useAppState();
- const { handleError } = useErrors();
- const [form] = Form.useForm();
- const [person, setPerson] = useState({
- lastName: '',
- firstName: '',
- city: '',
- state: '',
- address: '',
- country: '',
- phone: '',
- postalCode: '',
- fax: '',
- email: '',
- company: '',
- });
-
- useAbortableEffect((status) => {
- setLoading(true);
-
- fetchPerson()
- .then(({ data }) => {
- const personData = omit(data, '@odata.context', 'ID');
- if (!status.aborted) {
- setPerson(personData);
- }
- })
- .catch(handleError)
- .finally(() => setLoading(false));
- }, []);
-
- const onConfirmChanges = (newPerson) => {
- setLoading(true);
- confirmPerson(newPerson)
- .then(() => {
- message.success('Person successfully updated', MESSAGE_TIMEOUT);
- })
- .catch(handleError)
- .finally(() => setLoading(false));
- };
-
- const personProperties = map(Object.keys(person), (currentKey) => (
-
-
-
-
-
- ));
-
- return (
- <>
- {person.lastName !== '' && (
-
-
-
-
- )}
- >
- );
-};
-
-export default PersonPage;
diff --git a/media-store/app-src/src/components/Router.jsx b/media-store/app-src/src/components/Router.jsx
deleted file mode 100644
index e0cf5d4f..00000000
--- a/media-store/app-src/src/components/Router.jsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import React from 'react';
-import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
-import { isEmpty } from 'lodash';
-import TracksContainer from './TracksPage';
-import Header from './Header';
-import PersonPage from './PersonPage';
-import ErrorPage from './ErrorPage';
-import InvoicePage from './InvoicePage';
-import ManageStore from './ManageStore';
-import MyInvoicesPage from './MyInvoicesPage';
-import Login from './Login';
-import { withRestrictions } from '../hocs/withRestrictions';
-import { requireEmployee } from '../util/constants';
-
-const RestrictedLogin = withRestrictions(Login, ({ user }) => !user);
-const RestrictedInvoicePage = withRestrictions(
- InvoicePage,
- ({ user, invoicedItems }) => !requireEmployee(user) && !isEmpty(invoicedItems)
-);
-const RestrictedPersonPage = withRestrictions(PersonPage, ({ user }) => !!user);
-const RestrictedManageStore = withRestrictions(ManageStore, ({ user }) => requireEmployee(user));
-
-const MyRouter = () => {
- return (
-
-
-
- Loading...
}>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export { MyRouter };
diff --git a/media-store/app-src/src/components/TracksPage.css b/media-store/app-src/src/components/TracksPage.css
deleted file mode 100644
index c3855497..00000000
--- a/media-store/app-src/src/components/TracksPage.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.ant-select > div.ant-select-selector {
- padding: 5px;
- min-width: 300px;
-}
diff --git a/media-store/app-src/src/components/TracksPage.jsx b/media-store/app-src/src/components/TracksPage.jsx
deleted file mode 100644
index ed6c9835..00000000
--- a/media-store/app-src/src/components/TracksPage.jsx
+++ /dev/null
@@ -1,215 +0,0 @@
-import React, { useState } from 'react';
-import { debounce } from 'lodash';
-import { Input, Col, Row, Select, Pagination } from 'antd';
-import { Track } from './tracks/Track';
-import { ManagedTrack } from './tracks/ManagedTrack';
-import { useAppState } from '../hooks/useAppState';
-import { useErrors } from '../hooks/useErrors';
-import { fetchTacks, countTracks, fetchGenres } from '../api/calls';
-import { useAbortableEffect } from '../hooks/useAbortableEffect';
-import { requireEmployee } from '../util/constants';
-import './TracksPage.css';
-
-const { Search } = Input;
-const { Option } = Select;
-
-const DEBOUNCE_TIMER = 500;
-const DEBOUNCE_OPTIONS = {
- leading: true,
- trailing: false,
-};
-
-const renderGenres = (genres) =>
- genres.map(({ ID, name }) => (
-
- ));
-
-const TracksContainer = () => {
- const { setLoading, user } = useAppState();
- const { handleError } = useErrors();
- const [state, setState] = useState({
- tracks: [],
- genres: [],
- pagination: {
- currentPage: 1,
- totalItems: 0,
- pageSize: 20,
- },
- searchOptions: {
- substr: '',
- genreIds: [],
- },
- });
-
- useAbortableEffect((status) => {
- setLoading(true);
-
- const countTracksReq = countTracks();
- const getTracksRequest = fetchTacks();
- const getGenresReq = fetchGenres();
-
- Promise.all([countTracksReq, getTracksRequest, getGenresReq])
- .then(
- ([
- { data: totalItems },
- {
- data: { value: tracks },
- },
- {
- data: { value: genres },
- },
- ]) => {
- if (!status.aborted) {
- setState({
- ...state,
- tracks,
- genres,
- pagination: { ...state.pagination, totalItems },
- });
- }
- }
- )
- .catch(handleError)
- .finally(() => setLoading(false));
- }, []);
-
- const onSearch = debounce(
- () => {
- setLoading(true);
- const options = {
- $top: state.pagination.pageSize,
- substr: state.searchOptions.substr.replace(`'`, `''`),
- genreIds: state.searchOptions.genreIds,
- };
-
- Promise.all([
- fetchTacks(options),
- countTracks({
- substr: options.substr,
- genreIds: options.genreIds,
- }),
- ])
- .then(([{ data: { value: tracks } }, { data: totalItems }]) =>
- setState({
- ...state,
- tracks,
- pagination: { ...state.pagination, totalItems },
- })
- )
- .catch(handleError)
- .finally(() => setLoading(false));
- },
- DEBOUNCE_TIMER,
- DEBOUNCE_OPTIONS
- );
- const onSelectChange = (genres) => {
- setState({
- ...state,
- searchOptions: {
- ...state.searchOptions,
- genreIds: genres.map((value) => parseInt(value, 10)),
- },
- });
- };
- const onSearchChange = (event) => {
- setState({
- ...state,
- searchOptions: { ...state.searchOptions, substr: event.target.value },
- });
- };
- const onChangePage = (pageNumber) => {
- document.querySelector('section.ant-layout').scrollTo({ top: 0, left: 0, behavior: 'smooth' });
- setLoading(true);
-
- const options = {
- $top: state.pagination.pageSize,
- substr: state.searchOptions.substr,
- genreIds: state.searchOptions.genreIds,
- $skip: (pageNumber - 1) * state.pagination.pageSize,
- };
- fetchTacks(options)
- .then((response) =>
- setState({
- ...state,
- tracks: response.data.value,
- pagination: { ...state.pagination, currentPage: pageNumber },
- })
- )
- .catch(handleError)
- .finally(() => setLoading(false));
- };
- const deleteTrack = (ID) => {
- setState({
- ...state,
- tracks: state.tracks.filter(({ ID: curID }) => curID !== ID),
- });
- };
- const renderTracks = (tracks) => {
- const isEmployee = requireEmployee(user);
- const TrackComponent = isEmployee ? ManagedTrack : Track;
- return tracks.map((track) => {
- const isAlreadyOrdered = !isEmployee && track.alreadyOrdered;
- const onDeleteTrack = isEmployee && ((ID) => deleteTrack(ID));
- return (
-
-
-
- );
- });
- };
-
- const trackElements = renderTracks(state.tracks);
- const genreElements = renderGenres(state.genres);
-
- return (
- <>
-
-
-
-
-
- {trackElements}
-
-
- >
- );
-};
-
-export default TracksContainer;
diff --git a/media-store/app-src/src/components/manage-store/AddAlbumForm.jsx b/media-store/app-src/src/components/manage-store/AddAlbumForm.jsx
deleted file mode 100644
index 0a4978ae..00000000
--- a/media-store/app-src/src/components/manage-store/AddAlbumForm.jsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import React, { useEffect } from 'react';
-import { Form, Input, Select } from 'antd';
-import { useSearch } from '@umijs/hooks';
-import { useErrors } from '../../hooks/useErrors';
-import { fetchArtistsByName } from '../../api/calls';
-
-const REQUIRED = [
- {
- required: true,
- message: 'This filed is required!',
- },
-];
-const ARTISTS_LIMIT = 10;
-
-const getArtists = function (value) {
- return fetchArtistsByName(value, ARTISTS_LIMIT)
- .then((response) => response.data.value)
- .catch(this.handleError);
-};
-
-const AddAlbumForm = () => {
- const { handleError } = useErrors();
- const {
- data: artists,
- loading: isArtistsLoading,
- onChange: onChangeArtistInput,
- cancel: onArtistCancel,
- } = useSearch(getArtists.bind({ handleError }));
-
- useEffect(() => {
- onChangeArtistInput();
- }, []);
-
- return (
- <>
- Add album
-
-
-
-
-
-
- >
- );
-};
-
-export { AddAlbumForm };
diff --git a/media-store/app-src/src/components/manage-store/AddArtistForm.jsx b/media-store/app-src/src/components/manage-store/AddArtistForm.jsx
deleted file mode 100644
index 3cc7567f..00000000
--- a/media-store/app-src/src/components/manage-store/AddArtistForm.jsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import { Form, Input } from 'antd';
-
-const REQUIRED = [
- {
- required: true,
- message: 'This filed is required!',
- },
-];
-
-const AddArtistForm = () => {
- return (
- <>
- Add artist
-
-
-
- >
- );
-};
-
-export { AddArtistForm };
diff --git a/media-store/app-src/src/components/manage-store/TrackForm.jsx b/media-store/app-src/src/components/manage-store/TrackForm.jsx
deleted file mode 100644
index 47a7d9fe..00000000
--- a/media-store/app-src/src/components/manage-store/TrackForm.jsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import PropTypes from 'prop-types';
-import { Form, Input, Select, InputNumber } from 'antd';
-import { head } from 'lodash';
-import { useSearch } from '@umijs/hooks';
-import { useAppState } from '../../hooks/useAppState';
-import { fetchAlbumsByName, fetchGenres } from '../../api/calls';
-import { useErrors } from '../../hooks/useErrors';
-
-const ALBUMS_LIMIT = 10;
-const REQUIRED = [
- {
- required: true,
- message: 'This filed is required!',
- },
-];
-
-function getAlbums(value) {
- return fetchAlbumsByName(value, ALBUMS_LIMIT)
- .then((response) => response.data.value)
- .catch(this.handleError);
-}
-
-const TrackForm = ({ initialAlbumTitle }) => {
- const { handleError } = useErrors();
- const {
- data: albums,
- loading: isAlbumsLoading,
- onChange: onChangeAlbumInput,
- cancel: onAlbumCancel,
- } = useSearch(getAlbums.bind({ handleError }));
- const { setLoading } = useAppState();
- const [genres, setGenres] = useState([]);
-
- useEffect(() => {
- setLoading(true);
- Promise.all([fetchGenres(), onChangeAlbumInput(initialAlbumTitle)])
- .then((responses) => setGenres(head(responses).data.value))
- .catch(handleError)
- .finally(() => setLoading(false));
- }, []);
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- value.replace(/\$\s?|(,*)/g, '')}
- />
-
-
- );
-};
-
-TrackForm.propTypes = {
- initialAlbumTitle: PropTypes.string,
-};
-TrackForm.defaultProps = {
- initialAlbumTitle: undefined,
-};
-
-export { TrackForm };
diff --git a/media-store/app-src/src/components/tracks/DeleteAction.jsx b/media-store/app-src/src/components/tracks/DeleteAction.jsx
deleted file mode 100644
index 948fc7ab..00000000
--- a/media-store/app-src/src/components/tracks/DeleteAction.jsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import React, { useState } from 'react';
-import PropTypes from 'prop-types';
-import { Modal, message } from 'antd';
-import { DeleteOutlined } from '@ant-design/icons';
-import { deleteTrack } from '../../api/calls';
-import { useErrors } from '../../hooks/useErrors';
-import { MESSAGE_TIMEOUT } from '../../util/constants';
-
-const DeleteAction = ({ ID, onDeleteTrack }) => {
- const [modalVisible, setModalVisible] = useState(false);
- const { handleError } = useErrors();
-
- const onOk = () => {
- setModalVisible(false);
- deleteTrack(ID)
- .then(() => {
- onDeleteTrack();
- setModalVisible(false);
- message.success('Track successfully deleted!', MESSAGE_TIMEOUT);
- })
- .catch(handleError);
- };
-
- const onCancel = () => setModalVisible(false);
- const onOpenModal = () => {
- setModalVisible(true);
- };
-
- return (
- <>
- Delete
-
- Are You really want to delete this track?
-
- >
- );
-};
-
-DeleteAction.propTypes = {
- ID: PropTypes.number.isRequired,
- onDeleteTrack: PropTypes.func.isRequired,
-};
-
-export { DeleteAction };
diff --git a/media-store/app-src/src/components/tracks/EditAction.jsx b/media-store/app-src/src/components/tracks/EditAction.jsx
deleted file mode 100644
index 1c8c42e6..00000000
--- a/media-store/app-src/src/components/tracks/EditAction.jsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { Button, Modal, Form, message } from 'antd';
-import { EditOutlined, LoadingOutlined } from '@ant-design/icons';
-import { useErrors } from '../../hooks/useErrors';
-import { TrackForm } from '../manage-store/TrackForm';
-import { updateTrack, getTrack } from '../../api/calls';
-import { MESSAGE_TIMEOUT } from '../../util/constants';
-
-const EditAction = ({ ID, name, composer, genre, unitPrice, album, afterTrackUpdate }) => {
- const [visible, setVisible] = React.useState(false);
- const [confirmLoading, setConfirmLoading] = React.useState(false);
- const [updateLoading, setUpdateLoading] = React.useState(false);
- const [form] = Form.useForm();
- const { handleError } = useErrors();
-
- const onShowModal = () => {
- setVisible(true);
- };
-
- const afterCloseModal = () => {
- setUpdateLoading(true);
- getTrack(ID)
- .then((response) => {
- afterTrackUpdate(response.data);
- setUpdateLoading(false);
- })
- .catch(handleError);
- };
-
- const onFinish = (value) => {
- setConfirmLoading(true);
- updateTrack({
- ID,
- name: value.name,
- composer: value.composer,
- album: { ID: value.albumID },
- genre: { ID: value.genreID },
- unitPrice: value.unitPrice.toString(),
- })
- .then(() => {
- message.success('Track successfully updated!', MESSAGE_TIMEOUT);
- setConfirmLoading(false);
- setVisible(false);
- afterCloseModal();
- })
- .catch(handleError);
- };
-
- const handleOk = () => {
- form.submit();
- };
-
- const handleCancel = () => {
- setVisible(false);
- };
-
- return (
- <>
- {updateLoading ? : }
-
- Cancel
- ,
- ,
- ]}
- >
-
-
- >
- );
-};
-
-EditAction.propTypes = {
- ID: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- composer: PropTypes.string.isRequired,
- genre: PropTypes.object.isRequired,
- unitPrice: PropTypes.number.isRequired,
- album: PropTypes.object.isRequired,
- afterTrackUpdate: PropTypes.func.isRequired,
-};
-
-export { EditAction };
diff --git a/media-store/app-src/src/components/tracks/ManagedTrack.css b/media-store/app-src/src/components/tracks/ManagedTrack.css
deleted file mode 100644
index e2107b16..00000000
--- a/media-store/app-src/src/components/tracks/ManagedTrack.css
+++ /dev/null
@@ -1,7 +0,0 @@
-span > span.anticon.anticon-delete:hover {
- color: #ff4d4f;
-}
-
-.card-element {
- transition: opacity 0.5s ease-in-out;
-}
diff --git a/media-store/app-src/src/components/tracks/ManagedTrack.jsx b/media-store/app-src/src/components/tracks/ManagedTrack.jsx
deleted file mode 100644
index 42bea8c8..00000000
--- a/media-store/app-src/src/components/tracks/ManagedTrack.jsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import React, { useState, useRef } from 'react';
-import { Card } from 'antd';
-import PropTypes from 'prop-types';
-import { EditAction } from './EditAction';
-import { DeleteAction } from './DeleteAction';
-import { TrackCardBody } from './TrackCardBody';
-import './ManagedTrack.css';
-
-const ManagedTrack = ({ initialTrack, onDeleteTrack }) => {
- const trackElement = useRef();
- const [track, setTrack] = useState(initialTrack);
-
- return (
-
- {
- trackElement.current.style.opacity = 0;
- setTimeout(() => onDeleteTrack(track.ID), 500);
- }}
- />,
- setTrack(value)}
- />,
- ]}
- title={track.name}
- bordered={false}
- >
-
-
-
- );
-};
-
-ManagedTrack.propTypes = {
- initialTrack: PropTypes.object.isRequired,
- onDeleteTrack: PropTypes.func.isRequired,
-};
-
-export { ManagedTrack };
diff --git a/media-store/app-src/src/components/tracks/Track.jsx b/media-store/app-src/src/components/tracks/Track.jsx
deleted file mode 100644
index 3fb90950..00000000
--- a/media-store/app-src/src/components/tracks/Track.jsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React, { useState, useRef } from 'react';
-import PropTypes from 'prop-types';
-import { Card, Button } from 'antd';
-import { PlusOutlined, MinusOutlined } from '@ant-design/icons';
-import { useAppState } from '../../hooks/useAppState';
-import { TrackCardBody } from './TrackCardBody';
-
-const Track = ({ initialTrack, isAlreadyOrdered }) => {
- const trackElement = useRef();
- const { setInvoicedItems, invoicedItems } = useAppState();
- const [isJustInvoiced, setIsJustInvoiced] = useState(
- invoicedItems.find((curTrack) => curTrack.ID === initialTrack.ID)
- );
-
- const onChangedStatus = () => {
- const newIsJustInvoiced = !isJustInvoiced;
- if (newIsJustInvoiced) {
- setInvoicedItems([
- ...invoicedItems,
- {
- ID: initialTrack.ID,
- name: initialTrack.name,
- artist: initialTrack.album.artist.name,
- albumTitle: initialTrack.album.title,
- unitPrice: initialTrack.unitPrice,
- },
- ]);
- } else {
- setInvoicedItems(invoicedItems.filter(({ ID: curID }) => curID !== initialTrack.ID));
- }
- setIsJustInvoiced(newIsJustInvoiced);
- };
-
- return (
-
-
- {!isAlreadyOrdered && (
-
- )}
- >,
- ]}
- title={initialTrack.name}
- bordered={false}
- >
-
-
-
- );
-};
-
-Track.propTypes = {
- initialTrack: PropTypes.object.isRequired,
- isAlreadyOrdered: PropTypes.bool,
-};
-Track.defaultProps = {
- isAlreadyOrdered: undefined,
-};
-
-export { Track };
diff --git a/media-store/app-src/src/components/tracks/TrackCardBody.jsx b/media-store/app-src/src/components/tracks/TrackCardBody.jsx
deleted file mode 100644
index 7587c99a..00000000
--- a/media-store/app-src/src/components/tracks/TrackCardBody.jsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-const TrackCardBody = ({ track }) => {
- return (
- <>
-
- Artist:
- {track.album.artist.name}
-
-
- Album:
- {track.album.title}
-
-
- Genre:
- {track.genre.name}
-
-
- {track.composer && (
-
- Compositor:
- {track.composer}
-
- )}
-
-
-
- Price:
- {track.unitPrice}
-
-
- >
- );
-};
-
-TrackCardBody.propTypes = {
- track: PropTypes.object.isRequired,
-};
-
-export { TrackCardBody };
diff --git a/media-store/app-src/src/contexts/AppStateContext.jsx b/media-store/app-src/src/contexts/AppStateContext.jsx
deleted file mode 100644
index 5b5dd180..00000000
--- a/media-store/app-src/src/contexts/AppStateContext.jsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import React, { useMemo, createContext, useState, useEffect } from 'react';
-import PropTypes from 'prop-types';
-import { getUserFromLS, getLocaleFromLS, setUserToLS } from '../util/localStorageService';
-import { changeUserDefaults } from '../api/axiosInstance';
-import { emitter } from '../util/EventEmitter';
-
-const globalContext = {
- error: {},
- loading: true,
- user: {
- ID: undefined,
- roles: [],
- email: undefined,
- accessToken: undefined,
- refreshToken: undefined,
- },
- locale: undefined,
- invoicedItems: [],
- notifications: [],
-};
-const AppStateContext = createContext(globalContext);
-
-const AppStateContextProvider = ({ children }) => {
- const [invoicedItems, setInvoicedItems] = useState([]);
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState({});
- const [user, setUser] = useState(getUserFromLS());
- const [locale, setLocale] = useState(getLocaleFromLS());
-
- useEffect(() => {
- const updateUser = (newUser) => {
- console.log('USER_UPDATE WAS TRIGGERED');
- changeUserDefaults(newUser);
- setUserToLS(newUser);
- setUser(newUser);
- };
- emitter.on('UPDATE_USER', updateUser);
- return () => {
- emitter.removeListener('UPDATE_USER', updateUser);
- };
- }, []);
-
- const value = useMemo(
- () => ({
- error,
- loading,
- invoicedItems,
- user,
- locale,
- setLoading,
- setError,
- setInvoicedItems,
- setUser,
- setLocale,
- }),
- [locale, user, loading, error, invoicedItems]
- );
-
- return {children};
-};
-
-AppStateContextProvider.propTypes = {
- children: PropTypes.element.isRequired,
-};
-
-export { AppStateContextProvider, AppStateContext };
diff --git a/media-store/app-src/src/hocs/withRestrictions.jsx b/media-store/app-src/src/hocs/withRestrictions.jsx
deleted file mode 100644
index 26eedba3..00000000
--- a/media-store/app-src/src/hocs/withRestrictions.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import React from 'react';
-import { Redirect } from 'react-router-dom';
-import { useAppState } from '../hooks/useAppState';
-
-const withRestrictions = (Component, isUserMeetRestrictions) => {
- return (props) => {
- const { user, invoicedItems } = useAppState();
- return isUserMeetRestrictions({ user, invoicedItems }) ? (
-
- ) : (
-
- );
- };
-};
-
-export { withRestrictions };
diff --git a/media-store/app-src/src/hooks/useAbortableEffect.js b/media-store/app-src/src/hooks/useAbortableEffect.js
deleted file mode 100644
index 648d923d..00000000
--- a/media-store/app-src/src/hooks/useAbortableEffect.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import { useEffect } from 'react';
-
-function useAbortableEffect(effect, dependencies) {
- const status = {}; // mutable status object
- useEffect(() => {
- status.aborted = false;
- // pass the mutable object to the effect callback
- // store the returned value for cleanup
- const cleanUpFn = effect(status);
- return () => {
- // mutate the object to signal the consumer
- // this effect is cleaning up
- status.aborted = true;
- if (typeof cleanUpFn === 'function') {
- // run the cleanup function
- cleanUpFn();
- }
- };
- }, [...dependencies]);
-}
-
-export { useAbortableEffect };
diff --git a/media-store/app-src/src/hooks/useAppState.js b/media-store/app-src/src/hooks/useAppState.js
deleted file mode 100644
index 831ae73d..00000000
--- a/media-store/app-src/src/hooks/useAppState.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { useContext } from 'react';
-import { AppStateContext } from '../contexts/AppStateContext';
-
-const useAppState = () => useContext(AppStateContext);
-
-export { useAppState };
diff --git a/media-store/app-src/src/hooks/useErrors.js b/media-store/app-src/src/hooks/useErrors.js
deleted file mode 100644
index 4ccdd694..00000000
--- a/media-store/app-src/src/hooks/useErrors.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { useHistory } from 'react-router-dom';
-import { useAppState } from './useAppState';
-
-const useErrors = () => {
- const history = useHistory();
- const { setError } = useAppState();
-
- const handleError = (error) => {
- console.error('Error', error);
-
- if (error.response) {
- const { status, statusText, data } = error.response;
- setError({
- status,
- statusText,
- message: data.error ? data.error.message : data,
- });
- } else {
- setError({
- status: '',
- statusText: 'Error',
- message: 'Something went wrong. Seems like request is too long',
- });
- }
-
- history.push('/error');
- };
-
- return {
- handleError,
- };
-};
-
-export { useErrors };
diff --git a/media-store/app-src/src/index.jsx b/media-store/app-src/src/index.jsx
deleted file mode 100644
index 8110e69e..00000000
--- a/media-store/app-src/src/index.jsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import App from './App';
-// import * as serviceWorker from './serviceWorker';
-
-ReactDOM.render(, document.getElementById('root'));
-
-// If you want your app to work offline and load faster, you can change
-// unregister() to register() below. Note this comes with some pitfalls.
-// Learn more about service workers: https://bit.ly/CRA-PWA
-// serviceWorker.unregister();
diff --git a/media-store/app-src/src/logo.svg b/media-store/app-src/src/logo.svg
deleted file mode 100644
index 6b60c104..00000000
--- a/media-store/app-src/src/logo.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/media-store/app-src/src/serviceWorker.js b/media-store/app-src/src/serviceWorker.js
deleted file mode 100644
index e69de29b..00000000
diff --git a/media-store/app-src/src/setupTests.js b/media-store/app-src/src/setupTests.js
deleted file mode 100644
index 74b1a275..00000000
--- a/media-store/app-src/src/setupTests.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// jest-dom adds custom jest matchers for asserting on DOM nodes.
-// allows you to do things like:
-// expect(element).toHaveTextContent(/react/i)
-// learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom/extend-expect';
diff --git a/media-store/app-src/src/util/EventEmitter.js b/media-store/app-src/src/util/EventEmitter.js
deleted file mode 100644
index b28a45af..00000000
--- a/media-store/app-src/src/util/EventEmitter.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import EventEmitter from 'events';
-
-const emitter = new EventEmitter();
-
-export { emitter };
diff --git a/media-store/app-src/src/util/constants.js b/media-store/app-src/src/util/constants.js
deleted file mode 100644
index 4b9b4460..00000000
--- a/media-store/app-src/src/util/constants.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export const AVAILABLE_LOCALES = ['en', 'fr', 'de'];
-
-export const MESSAGE_TIMEOUT = 2;
-
-export const requireEmployee = (user) => !!user && user.roles.includes('employee');
-
-export const requireCustomer = (user) => !!user && user.roles.includes('customer');
diff --git a/media-store/app-src/src/util/localStorageService.js b/media-store/app-src/src/util/localStorageService.js
deleted file mode 100644
index 853b4817..00000000
--- a/media-store/app-src/src/util/localStorageService.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { isValidUser } from './validateUser';
-import { AVAILABLE_LOCALES } from './constants';
-
-const setUserToLS = (user) => {
- if (user) {
- localStorage.setItem('user', JSON.stringify(user));
- } else {
- localStorage.removeItem('user');
- }
-};
-
-const getUserFromLS = () => {
- let userFromLS;
- try {
- userFromLS = JSON.parse(localStorage.getItem('user'));
- if (isValidUser(userFromLS)) {
- return userFromLS;
- }
- } catch (e) {
- console.error('User from local storage are not valid');
- }
- return undefined;
-};
-
-const getLocaleFromLS = () => {
- const localeFromLS = localStorage.getItem('locale');
- return localeFromLS && localeFromLS !== 'undefined' && AVAILABLE_LOCALES.includes(localeFromLS)
- ? localeFromLS
- : 'en';
-};
-
-const setLocaleToLS = (locale) => {
- localStorage.setItem('locale', locale);
-};
-
-export { setLocaleToLS, getLocaleFromLS, getUserFromLS, setUserToLS };
diff --git a/media-store/app-src/src/util/validateUser.js b/media-store/app-src/src/util/validateUser.js
deleted file mode 100644
index b2d52b29..00000000
--- a/media-store/app-src/src/util/validateUser.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import { isArray, isEmpty, isString, isNumber } from 'lodash';
-
-const CUSTOMER_ROLE = 'customer';
-const EMPLOYEE_ROLE = 'employee';
-
-const isValidUser = (user) => {
- return (
- !isEmpty(user) &&
- isNumber(user.ID) &&
- isArray(user.roles) &&
- !!user.roles.some((role) => role === CUSTOMER_ROLE || role === EMPLOYEE_ROLE) &&
- isString(user.email) &&
- isString(user.accessToken) &&
- isString(user.refreshToken)
- );
-};
-
-export { isValidUser };
diff --git a/media-store/app-src/webpack/common-plugins.js b/media-store/app-src/webpack/common-plugins.js
deleted file mode 100644
index 9ae39a04..00000000
--- a/media-store/app-src/webpack/common-plugins.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const path = require('path');
-const webpack = require('webpack');
-const { CleanWebpackPlugin } = require('clean-webpack-plugin');
-const HtmlWebpackPlugin = require('html-webpack-plugin');
-const CopyPlugin = require('copy-webpack-plugin');
-const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
-
-module.exports = {
- plugins: [
- new CleanWebpackPlugin(),
- new HtmlWebpackPlugin({
- template: path.join(__dirname, '../public/index.html'),
- filename: path.join(__dirname, '../../app/index.html'),
- publicPath: '/static/', // for js bundles path
- }),
- new InterpolateHtmlPlugin(HtmlWebpackPlugin, {
- PUBLIC_URL: '',
- }),
- new CopyPlugin({
- patterns: [
- {
- from: path.join(__dirname, '../public'),
- to: path.join(__dirname, '../../app'),
- globOptions: {
- dot: true,
- ignore: ['**/index.html'],
- },
- },
- ],
- }),
- new webpack.ProgressPlugin(),
- ],
-};
diff --git a/media-store/app-src/webpack/common-rules.js b/media-store/app-src/webpack/common-rules.js
deleted file mode 100644
index 1afcc25e..00000000
--- a/media-store/app-src/webpack/common-rules.js
+++ /dev/null
@@ -1,18 +0,0 @@
-module.exports = {
- rules: [
- {
- test: /\.(js|jsx)$/,
- exclude: /(node_modules)/,
- use: {
- loader: 'babel-loader',
- options: {
- presets: ['@babel/preset-env', '@babel/preset-react'],
- },
- },
- },
- {
- test: /\.(png|jpg)$/,
- use: [{ loader: 'url-loader' }],
- },
- ],
-};
diff --git a/media-store/app-src/webpack/webpack-dev-server.js b/media-store/app-src/webpack/webpack-dev-server.js
deleted file mode 100644
index f0efb72e..00000000
--- a/media-store/app-src/webpack/webpack-dev-server.js
+++ /dev/null
@@ -1,56 +0,0 @@
-const path = require('path');
-const webpack = require('webpack');
-const HtmlWebpackPlugin = require('html-webpack-plugin');
-const { CleanWebpackPlugin } = require('clean-webpack-plugin');
-const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
-const { rules } = require('./common-rules');
-
-module.exports = {
- mode: 'development',
- devtool: 'inline-source-map',
- entry: {
- index: './src/index.jsx',
- },
- devServer: {
- contentBase: './dist',
- compress: true, // compress files to gzip to increase download speed
- port: 3000,
- disableHostCheck: false, // by default true, it is not recomended,
- // because it makes app vulnerable to DNS rebinding attacks
- headers: {
- 'X-Custom-header': 'custom', // this requires apps with authentication
- // useful config obj
- },
- open: true, // open the browser after server had been started
- hot: true, // hot module replacement
- historyApiFallback: true, // needs for react-router-dom
- },
- plugins: [
- new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
- new HtmlWebpackPlugin({
- template: path.join(__dirname, '../public/index.html'),
- }),
- new InterpolateHtmlPlugin(HtmlWebpackPlugin, {
- PUBLIC_URL: '',
- }),
- new webpack.ProgressPlugin(),
- new webpack.DefinePlugin({
- 'process.env.SERVICE_URL': JSON.stringify('http://localhost:4004/'),
- }),
- // new webpack.HotModuleReplacementPlugin(), // for hot module replacement option of devServer
- ],
- output: {
- filename: '[name].[fullhash].js',
- path: path.resolve(__dirname, 'dist'),
- },
- module: {
- rules: [
- ...rules,
- {
- test: /\.css$/,
- use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
- },
- ],
- },
- resolve: { extensions: ['*', '.js', '.jsx'] },
-};
diff --git a/media-store/app-src/webpack/webpack.common.js b/media-store/app-src/webpack/webpack.common.js
deleted file mode 100644
index 83b11f1f..00000000
--- a/media-store/app-src/webpack/webpack.common.js
+++ /dev/null
@@ -1,25 +0,0 @@
-const path = require('path');
-
-module.exports = {
- entry: {
- app: './src/index.jsx', // Bundle with our code
- react: ['react', 'react-dom'],
- lodash: ['lodash'],
- moment: ['moment'],
- events: ['events'],
- axios: ['axios'],
- antd: ['antd'],
- },
- output: {
- // [name] - name of the entry (bundle),
- // [checksum] or [hash] - to cache different bundles
- // from update when developing (doing changes in the files)
- filename: '[name].[fullhash].js',
- // in this folder path bundles will be placed
- path: path.resolve(__dirname, '../../app/static'),
- // where you uploaded your bundled files. (Relative to server root)
- // needs for react-router-dom
- publicPath: '/static/',
- },
- resolve: { extensions: ['*', '.js', '.jsx'] },
-};
diff --git a/media-store/app-src/webpack/webpack.dev.js b/media-store/app-src/webpack/webpack.dev.js
deleted file mode 100644
index ef02a698..00000000
--- a/media-store/app-src/webpack/webpack.dev.js
+++ /dev/null
@@ -1,25 +0,0 @@
-const webpack = require('webpack');
-const { merge } = require('webpack-merge');
-const common = require('./webpack.common.js');
-const { rules } = require('./common-rules');
-const { plugins } = require('./common-plugins');
-
-module.exports = merge(common, {
- mode: 'development',
- devtool: 'inline-source-map',
- plugins: [
- ...plugins,
- new webpack.DefinePlugin({
- 'process.env.SERVICE_URL': JSON.stringify('http://localhost:4004/'),
- }),
- ],
- module: {
- rules: [
- ...rules,
- {
- test: /\.css$/,
- use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
- },
- ],
- },
-});
diff --git a/media-store/app-src/webpack/webpack.prod.js b/media-store/app-src/webpack/webpack.prod.js
deleted file mode 100644
index bb047d76..00000000
--- a/media-store/app-src/webpack/webpack.prod.js
+++ /dev/null
@@ -1,40 +0,0 @@
-const webpack = require('webpack');
-const { merge } = require('webpack-merge');
-const MiniCssExtractPlugin = require('mini-css-extract-plugin');
-const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
-const TerserPlugin = require('terser-webpack-plugin');
-const common = require('./webpack.common.js');
-const { rules } = require('./common-rules');
-const { plugins } = require('./common-plugins');
-
-module.exports = merge(common, {
- mode: 'production',
- devtool: 'source-map',
- plugins: [
- ...plugins,
- new webpack.DefinePlugin({
- 'process.env.SERVICE_URL': JSON.stringify('api/'),
- }),
- new MiniCssExtractPlugin({
- filename: '[name].css',
- chunkFilename: '[id].css',
- }),
- ],
- optimization: {
- splitChunks: {
- // To split up js code to different bundles.
- chunks: 'all', // Now bundle with our code will be cleaned up
- }, // from vendors imports (2mb ~> 100kb)
- minimize: true,
- minimizer: [new TerserPlugin(), new CssMinimizerPlugin()], // to minimize file size
- },
- module: {
- rules: [
- ...rules,
- {
- test: /\.css$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader'],
- },
- ],
- },
-});
diff --git a/media-store/deployers/approuter/package.json b/media-store/deployers/approuter/package.json
deleted file mode 100644
index d9a4cd89..00000000
--- a/media-store/deployers/approuter/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "name": "media-store-approuter",
- "description": "Approuter",
- "version": "1.0.0",
- "dependencies": {
- "@sap/approuter": "^6.8.2"
- },
- "scripts": {
- "start": "node node_modules/@sap/approuter/approuter.js"
- }
-}
diff --git a/media-store/deployers/approuter/xs-app.json b/media-store/deployers/approuter/xs-app.json
deleted file mode 100644
index 4270e0cb..00000000
--- a/media-store/deployers/approuter/xs-app.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "welcomeFile": "/index.html",
- "authenticationMethod": "none",
- "routes": [
- {
- "source": "/api/(.*)",
- "target": "$1",
- "destination": "srv-binding",
- "authenticationType": "none"
- },
- {
- "source": "^(.*)",
- "target": "mediastore/$1",
- "service": "html5-apps-repo-rt"
- }
- ]
-}
diff --git a/media-store/deployers/html5Deployer/package.json b/media-store/deployers/html5Deployer/package.json
deleted file mode 100644
index 09f597b2..00000000
--- a/media-store/deployers/html5Deployer/package.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "media-store-html5deployer",
- "engines": {
- "node": ">=6.0.0"
- },
- "dependencies": {
- "@sap/html5-app-deployer": "^2.0.0"
- },
- "scripts": {
- "start": "node node_modules/@sap/html5-app-deployer/index.js"
- }
-}
diff --git a/media-store/deployers/xs-security.json b/media-store/deployers/xs-security.json
deleted file mode 100644
index fd42b7a2..00000000
--- a/media-store/deployers/xs-security.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "xsappname": "media-store-xsuaa",
- "tenant-mode": "dedicated",
- "scopes": [],
- "attributes": [],
- "role-templates": []
-}
diff --git a/media-store/mta.yaml b/media-store/mta.yaml
index 60f2ca04..fff60868 100644
--- a/media-store/mta.yaml
+++ b/media-store/mta.yaml
@@ -48,7 +48,7 @@ modules:
- name: media-store-hmtl5-deployer
# ------------------------------------------------------------
type: com.sap.html5.application-content
- path: deployers/html5Deployer
+ path: app/deployers/html5Deployer
requires:
- name: media-store-html5-host
build-parameters:
@@ -71,7 +71,7 @@ modules:
- name: media-store-approuter
# ------------------------------------------------------------
type: approuter.nodejs
- path: deployers/approuter
+ path: app/deployers/approuter
requires:
- name: media-store-html5-runtime
- name: media-store-xsuaa
@@ -119,7 +119,7 @@ resources:
- name: media-store-xsuaa
# ------------------------------------------------------------
parameters:
- path: deployers/xs-security.json
+ path: app/deployers/xs-security.json
service-plan: application
service: xsuaa
type: org.cloudfoundry.managed-service