diff --git a/Backend/.env b/Backend/.env
new file mode 100644
index 00000000..b1fe361e
--- /dev/null
+++ b/Backend/.env
@@ -0,0 +1,7 @@
+#API Keys
+APIKEY1 = ZSQ57OXG4YKUA0B8 #API Key Hakan;
+APIKEY2 = MB6DE4CNFFYGP4M7 #API Key Steffen;
+APIKEY3 = NOGQ7D1A1RHDGMU4 #API Key Cedrik
+APIKEY4 = ZSQ57OXG4YKUA0B8 #API Key Hakan; #RESERVIERT FÜR MONATLICH
+APIKEY5 = MB6DE4CNFFYGP4M7 #API Key Steffen;
+APIKEY6 = NOGQ7D1A1RHDGMU4 #API Key Cedrik;
\ No newline at end of file
diff --git a/Backend/.gitignore b/Backend/.gitignore
index 6a7d6d8e..fa6a20f5 100644
--- a/Backend/.gitignore
+++ b/Backend/.gitignore
@@ -73,7 +73,6 @@ web_modules/
.yarn-integrity
# dotenv environment variable files
-.env
.env.development.local
.env.test.local
.env.production.local
diff --git a/Backend/package-lock.json b/Backend/package-lock.json
index 304db1a9..f1b1cc96 100644
--- a/Backend/package-lock.json
+++ b/Backend/package-lock.json
@@ -1,17 +1,17 @@
{
- "name": "package.json",
+ "name": "benchmarket-backend",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
- "name": "package.json",
+ "name": "benchmarket-backend",
"version": "1.0.0",
- "license": "ISC",
"dependencies": {
"axios": "^0.26.1",
"body-parser": "^1.19.2",
"convert-csv-to-json": "^1.3.3",
+ "dotenv": "^16.0.1",
"express": "^4.17.3",
"linebyline": "^1.3.0",
"match-sorter": "^6.3.1",
@@ -643,6 +643,14 @@
"node": ">=8"
}
},
+ "node_modules/dotenv": {
+ "version": "16.0.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
+ "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
@@ -2839,6 +2847,11 @@
"is-obj": "^2.0.0"
}
},
+ "dotenv": {
+ "version": "16.0.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
+ "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ=="
+ },
"duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
diff --git a/Backend/package.json b/Backend/package.json
index 3aa56854..26762213 100644
--- a/Backend/package.json
+++ b/Backend/package.json
@@ -1,5 +1,5 @@
{
- "name": "package.json",
+ "name": "benchmarket-backend",
"version": "1.0.0",
"description": "BenchmarketBackendServer",
"main": "server.js",
@@ -8,11 +8,11 @@
"start": "node server.js"
},
"author": "Steffen Kruschina @fefifef",
- "license": "ISC",
"dependencies": {
"axios": "^0.26.1",
"body-parser": "^1.19.2",
"convert-csv-to-json": "^1.3.3",
+ "dotenv": "^16.0.1",
"express": "^4.17.3",
"linebyline": "^1.3.0",
"match-sorter": "^6.3.1",
diff --git a/Backend/server.js b/Backend/server.js
index f6b467f6..4af2afc4 100644
--- a/Backend/server.js
+++ b/Backend/server.js
@@ -1,3 +1,4 @@
+require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const fs = require('fs');
@@ -17,12 +18,12 @@ let accessURL = '*';
const apiKeys =[
- 'ZSQ57OXG4YKUA0B8', //API Key Hakan;
- 'MB6DE4CNFFYGP4M7', //API Key Steffen;
- 'NOGQ7D1A1RHDGMU4', //API Key Cedrik
- 'ZSQ57OXG4YKUA0B8', //API Key Hakan; //RESERVIERT FÜR MONATLICH
- 'MB6DE4CNFFYGP4M7', //API Key Steffen;
- 'NOGQ7D1A1RHDGMU4' //API Key Cedrik
+ process.env.APIKEY1,
+ process.env.APIKEY2,
+ process.env.APIKEY3,
+ process.env.APIKEY4,
+ process.env.APIKEY5,
+ process.env.APIKEY6
]
let apiKeyIndex = 0;
// let apiKey;
diff --git a/Frontend/.env b/Frontend/.env
index 665e1871..d2fe3ef3 100644
--- a/Frontend/.env
+++ b/Frontend/.env
@@ -1 +1,2 @@
-REACT_APP_BASEURL = http://localhost:3001
\ No newline at end of file
+REACT_APP_BASEURL = http://localhost:3001
+REACT_APP_BOTBACKENDURL = http://benchmarket.germanywestcentral.cloudapp.azure.com:1880
\ No newline at end of file
diff --git a/Frontend/.env.production b/Frontend/.env.production
index b0ce0d55..78643652 100644
--- a/Frontend/.env.production
+++ b/Frontend/.env.production
@@ -1 +1,2 @@
-REACT_APP_BASEURL = http://benchmarket.germanywestcentral.cloudapp.azure.com:3001
\ No newline at end of file
+REACT_APP_BASEURL = http://benchmarket.germanywestcentral.cloudapp.azure.com:3001
+REACT_APP_BOTBACKENDURL = http://benchmarket.germanywestcentral.cloudapp.azure.com:1880
\ No newline at end of file
diff --git a/Frontend/README.md b/Frontend/README.md
index d3b3ef60..f38f96b5 100644
--- a/Frontend/README.md
+++ b/Frontend/README.md
@@ -10,7 +10,7 @@ To avoid incompatibility's issues it is recommended to [install](https://nodejs.
- Node (version 16.14.2)
- npm (version 8.5.0)
-Once the installation is finished, for load the used dependencies it is required to run:
+Once the installation is finished, for loading the used dependencies it is required to run:
####`npm install`
## Available Scripts
diff --git a/Frontend/package-lock.json b/Frontend/package-lock.json
index 82ae76b0..b7e14b36 100644
--- a/Frontend/package-lock.json
+++ b/Frontend/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "finanzen-projekt",
+ "name": "bench-market",
"version": "0.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
- "name": "finanzen-projekt",
+ "name": "bench-market",
"version": "0.1.0",
"dependencies": {
"@date-io/date-fns": "^2.13.1",
@@ -14473,14 +14473,6 @@
"url": "https://opencollective.com/webpack"
}
},
- "node_modules/react-chatbot-kit/node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
"node_modules/react-chatbot-kit/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -27723,11 +27715,6 @@
"ajv-keywords": "^3.5.2"
}
},
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
- },
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
diff --git a/Frontend/public/favicon.ico b/Frontend/public/favicon.ico
index a11777cc..ee93e25f 100644
Binary files a/Frontend/public/favicon.ico and b/Frontend/public/favicon.ico differ
diff --git a/Frontend/public/index.html b/Frontend/public/index.html
index aa069f27..81bf65eb 100644
--- a/Frontend/public/index.html
+++ b/Frontend/public/index.html
@@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
-
React App
+ Bench:market
diff --git a/Frontend/public/logo192.png b/Frontend/public/logo192.png
index fc44b0a3..2ecb5d4a 100644
Binary files a/Frontend/public/logo192.png and b/Frontend/public/logo192.png differ
diff --git a/Frontend/public/logo512.png b/Frontend/public/logo512.png
index a4e47a65..e7f9526f 100644
Binary files a/Frontend/public/logo512.png and b/Frontend/public/logo512.png differ
diff --git a/Frontend/public/manifest.json b/Frontend/public/manifest.json
index 080d6c77..fb7615ec 100644
--- a/Frontend/public/manifest.json
+++ b/Frontend/public/manifest.json
@@ -1,6 +1,6 @@
{
- "short_name": "React App",
- "name": "Create React App Sample",
+ "short_name": "Bench:market",
+ "name": "Bench:market | SWE Finanzen",
"icons": [
{
"src": "favicon.ico",
diff --git a/Frontend/src/App.css b/Frontend/src/App.css
index 31aceeee..1eb69a87 100644
--- a/Frontend/src/App.css
+++ b/Frontend/src/App.css
@@ -1,5 +1,6 @@
.App {
text-align: center;
+ color: #30302f
}
.App-logo {
@@ -48,3 +49,12 @@
.hovered {
color: green;
}
+
+@keyframes spin {
+ from {
+ transform:rotate(0deg);
+ }
+ to {
+ transform:rotate(360deg);
+ }
+}
diff --git a/Frontend/src/App.jsx b/Frontend/src/App.jsx
index 6383d045..34da9136 100644
--- a/Frontend/src/App.jsx
+++ b/Frontend/src/App.jsx
@@ -3,6 +3,7 @@ import {CircularProgress} from '@mui/material';
import {BrowserRouter as Router} from 'react-router-dom';
import AppRoutes from './routes';
import './App.css';
+import { Loading } from './components/common';
/**
* App root component with link navigations and routes
@@ -17,7 +18,7 @@ const App = () => (
transform: 'translate(-50%, -50%)'
}}
>
-
+
}>
diff --git a/Frontend/src/benchi-chatbot/MessageParser.js b/Frontend/src/benchi-chatbot/MessageParser.js
index 13f9747a..0417357b 100644
--- a/Frontend/src/benchi-chatbot/MessageParser.js
+++ b/Frontend/src/benchi-chatbot/MessageParser.js
@@ -32,7 +32,7 @@ class MessageParser {
async fetchAnswer(message) {
try {
- const response = await fetch(`http://benchmarket.germanywestcentral.cloudapp.azure.com:1880/interpretMessage?message=${message}`, {mode:'cors'})
+ const response = await fetch(`${process.env.REACT_APP_BOTBACKENDURL}/interpretMessage?message=${message}`, {mode:'cors'})
const json = await response.json();
return json.answers;
} catch (e) {
diff --git a/Frontend/src/benchi-chatbot/TextToSpeech.js b/Frontend/src/benchi-chatbot/TextToSpeech.js
index a148ddb7..22952a56 100644
--- a/Frontend/src/benchi-chatbot/TextToSpeech.js
+++ b/Frontend/src/benchi-chatbot/TextToSpeech.js
@@ -6,7 +6,7 @@ class TextToSpeech {
let audio;
try {
- const response = await fetch(`http://benchmarket.germanywestcentral.cloudapp.azure.com:1880/textToSpeech?text=${answer}`, {mode:'cors'})
+ const response = await fetch(`${process.env.REACT_APP_BOTBACKENDURL}/textToSpeech?text=${answer}`, {mode:'cors'})
const arrayBuffer = await response.arrayBuffer();
TextToSpeech.ctx.close();
TextToSpeech.ctx = new AudioContext();
diff --git a/Frontend/src/benchi-chatbot/config.js b/Frontend/src/benchi-chatbot/config.js
index 63d3dd93..1dd6e70a 100644
--- a/Frontend/src/benchi-chatbot/config.js
+++ b/Frontend/src/benchi-chatbot/config.js
@@ -12,7 +12,6 @@ const config = {
state: {
questionNr: 0,
userPreferences: {experience: '', risk: '', active: false, effort: '', duration: ''},
- textToSpeech: new TextToSpeech()
},
customComponents: {
// Replaces the default header
diff --git a/Frontend/src/components/common/AssetDetailItem.jsx b/Frontend/src/components/common/AssetDetailItem.jsx
index 15388c3b..88b0362f 100644
--- a/Frontend/src/components/common/AssetDetailItem.jsx
+++ b/Frontend/src/components/common/AssetDetailItem.jsx
@@ -4,6 +4,8 @@ import {Avatar, Box, Container, ListItem, Typography} from '@mui/material';
import DropdownMenu from '../screens/WatchLists/DropdownMenu';
import PropTypes from 'prop-types';
+import Colors from './Colors';
+
/**
* Formats the date (day and month)
* @param activityDate
@@ -51,7 +53,7 @@ const AssetDetailItem = props => (
borderBottomLeftRadius: props.itemsArray && props.index === props.itemsArray.length - 1 && '0.5rem',
borderBottomRightRadius: props.itemsArray && props.index === props.itemsArray.length - 1 && '0.5rem',
backgroundColor: 'white',
- borderLeftColor: props.activities ? props.colorsArray[4][props.row.type][1] : props.colorsArray[props.row.symbol.hashCode() % 4],
+ borderLeftColor: props.activities ? props.colorsArray[0][props.row.type][1] : Colors.COLORPALETTE[props.row.symbol.hashCode() % 10],
boxShadow: props.index === 0 ?
'rgb(0 0 0 / 15%) 0px -6px 6px -6px' :
props.itemsArray && props.index === props.itemsArray.length - 1 ?
@@ -76,8 +78,8 @@ const AssetDetailItem = props => (
xs: 12
}}
sx={{
- color: props.colorsArray[4][props.row.type][0],
- backgroundColor: props.colorsArray[4][props.row.type][1],
+ color: props.colorsArray[0][props.row.type][0],
+ backgroundColor: props.colorsArray[0][props.row.type][1],
}}
>
{`${props.row.type}`}
@@ -101,7 +103,7 @@ const AssetDetailItem = props => (
alt={`${props.activities ? props.row.assetName : props.row.name}-logo`}
//src={`${process.env.PUBLIC_URL}/assets/images/allianz-logo.jpeg`} //TODO: put icon if exists
sx={{
- backgroundColor: props.activities ? props.colorsArray[props.row.asset.hashCode() % 4] : props.colorsArray[props.row.symbol.hashCode() % 4],
+ backgroundColor: props.activities ? Colors.COLORPALETTE[props.row.asset.hashCode() % 10] : Colors.COLORPALETTE[props.row.symbol.hashCode() % 10],
width: {
xs: '2.5rem',
md: '2.8rem'
diff --git a/Frontend/src/components/common/Benchi.jsx b/Frontend/src/components/common/Benchi.jsx
index de65ab01..4042d448 100644
--- a/Frontend/src/components/common/Benchi.jsx
+++ b/Frontend/src/components/common/Benchi.jsx
@@ -15,7 +15,7 @@ import ActionProvider from '../../benchi-chatbot/ActionProvider.js';
import TextToSpeech from '../../benchi-chatbot/TextToSpeech.js';
/**
- * Template to show modals throughout the app
+ * Renders the Benchi Icon and Chat
* @param props
* @returns {JSX.Element}
* @constructor
diff --git a/Frontend/src/components/common/Colors.jsx b/Frontend/src/components/common/Colors.jsx
index ad382cb8..fa31fd50 100644
--- a/Frontend/src/components/common/Colors.jsx
+++ b/Frontend/src/components/common/Colors.jsx
@@ -1,11 +1,25 @@
const Colors = {
BROWN: '#493f35',
LIGHTBROWN: '#eacfb4',
+ TEXTBROWN: '#30302f',
GREY: '#f3f4f6',
+ DARKGREY: '#bdbab7',
GREEN: '#4eb96f',
DARKGREEN: '#068930',
-
-
+ DARKORANGE: '#e47e25',
+ DARKERDARKORANGE: '#c96208',
+ COLORPALETTE: [
+ '#e57e24ff', //cadmium-orange
+ '#eb8e1fff', //carrot-orange
+ '#f19b1fff', //orange-peel
+ '#b69994ff', //tuscany
+ '#3a97d2ff', //carolina-blue
+ '#3d9bcaff', //carolina-blue-2
+ '#4eb96fff', //medium-sea-green
+ '#c1be49ff', // olive-green
+ '#efc317ff', //jonquil
+ '#ecb81aff', //orange-yellow
+ ]
}
export default Colors;
\ No newline at end of file
diff --git a/Frontend/src/components/common/DoughnutChart.jsx b/Frontend/src/components/common/DoughnutChart.jsx
index 88df38c6..20e3a106 100644
--- a/Frontend/src/components/common/DoughnutChart.jsx
+++ b/Frontend/src/components/common/DoughnutChart.jsx
@@ -4,6 +4,24 @@ import {Chart as ChartJS, ArcElement, Tooltip, Legend} from 'chart.js';
import {Doughnut} from 'react-chartjs-2';
import {Typography, Grid, Paper} from '@mui/material';
+import Colors from './Colors';
+
+/**
+ * Creates a hashCode from a String
+ * @param String
+ * @returns {interger}
+ */
+ String.prototype.hashCode = function() {
+ let hash = 0, i, chr;
+ if (this.length === 0) return hash;
+ for (i = 0; i < this.length; i++) {
+ chr = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + chr;
+ hash |= 0; // Convert to 32bit integer
+ }
+ return hash;
+};
+
/**
* Shows a Custom DoughnutChart
* @param props
@@ -29,16 +47,19 @@ const DoughnutChart = props => {
setMiddleDisplayValue(defaultMiddleDisplayValue);
}
+ const getColors = (symbols) => {
+ let colors = [];
+ symbols.forEach((symbol, index) => {
+ const symbolColor = Colors.COLORPALETTE[symbol ? symbol.hashCode() % 10 : index*8 % 10];
+ colors.push(symbolColor);
+ });
+ return colors;
+ }
+
const labels = props.labels;
const valueData = props.data;
- const colors = [
- 'rgba(59, 151, 210, 1)',
- 'rgba(241, 155, 31, 1)',
- 'rgba(229, 126, 37, 1)',
- 'rgba(239, 195, 25, 1)',
- 'rgba(78, 185, 111, 1)',
- ]
+ const colors = getColors(props.symbols);
const data = {
labels: labels,
@@ -133,7 +154,8 @@ DoughnutChart.propTypes = {
defaultMiddleDisplayLabel: PropTypes.string,
defaultMiddleDisplayValue: PropTypes.string,
data: PropTypes.array,
- labels: PropTypes.array
+ labels: PropTypes.array,
+ symbols: PropTypes.array
};
export default DoughnutChart;
diff --git a/Frontend/src/components/common/Loading.jsx b/Frontend/src/components/common/Loading.jsx
new file mode 100644
index 00000000..f054091a
--- /dev/null
+++ b/Frontend/src/components/common/Loading.jsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+/**
+ * Spinning Benchmarket Logo for displaying while loading
+ * @returns {JSX.Element}
+ * @constructor
+ */
+ const Loading = props => {
+
+ return (
+
+ );
+ }
+
+
+Loading.propTypes = {
+ size: PropTypes.number
+};
+
+export default Loading;
diff --git a/Frontend/src/components/common/SearchResultsTable.jsx b/Frontend/src/components/common/SearchResultsTable.jsx
index 1829ac42..3bf0988c 100644
--- a/Frontend/src/components/common/SearchResultsTable.jsx
+++ b/Frontend/src/components/common/SearchResultsTable.jsx
@@ -6,6 +6,8 @@ import BookmarkBorderIcon from '@mui/icons-material/BookmarkBorder';
import AddIcon from '@mui/icons-material/Add';
import PropTypes from 'prop-types';
+import Colors from './Colors';
+
/**
* Component related to the list of search results
* @param props
@@ -13,7 +15,6 @@ import PropTypes from 'prop-types';
* @constructor
*/
const SearchResultsTable = props => {
- const colorsArray = ['rgb(59 151 210)', 'rgb(78 185 111)', 'rgb(228 126 37)', 'rgb(239 195 21)'];
/**
* Checks whether asset is already in watchlist
@@ -71,7 +72,7 @@ const SearchResultsTable = props => {
{
sx={{
color: 'white',
width: '5rem',
- borderColor: 'rgb(228 126 37)',
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#e47e25',
+ backgroundColor: '#e47e25',
'&:hover': {
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#c96208',
+ backgroundColor: '#e47e25',
}
}}
>
diff --git a/Frontend/src/components/common/StyledTextField.jsx b/Frontend/src/components/common/StyledTextField.jsx
new file mode 100644
index 00000000..f6d4bc28
--- /dev/null
+++ b/Frontend/src/components/common/StyledTextField.jsx
@@ -0,0 +1,27 @@
+import {TextField, styled} from '@mui/material';
+
+const StyledTextField = styled(TextField)({
+//Label color when focused
+'& label.Mui-focused': {
+ color: '#493f35',
+},
+'& .MuiInput-underline:after': {
+ borderBottomColor: '#493f35',
+},
+'& .MuiOutlinedInput-root': {
+ //Standard border color
+ '& fieldset': {
+ borderColor: '#c4b8ac',
+ },
+ //Border color on hover
+ '&:hover fieldset': {
+ borderColor: '#493f35',
+ },
+ //Border color when focused
+ '&.Mui-focused fieldset': {
+ borderColor: '#493f35',
+ },
+},
+});
+
+export default StyledTextField;
\ No newline at end of file
diff --git a/Frontend/src/components/common/index.jsx b/Frontend/src/components/common/index.jsx
index 6b34f1a6..fb5004cc 100644
--- a/Frontend/src/components/common/index.jsx
+++ b/Frontend/src/components/common/index.jsx
@@ -5,7 +5,9 @@ import AssetDetailItem from './AssetDetailItem';
import DoughnutChart from './DoughnutChart';
import Benchi from './Benchi';
import Footer from './Footer';
+import Loading from './Loading';
import Colors from './Colors';
+import StyledTextField from './StyledTextField';
export {
SideNavLeft,
@@ -15,5 +17,7 @@ export {
DoughnutChart,
Footer,
Benchi,
+ Loading,
+ StyledTextField,
Colors
}
\ No newline at end of file
diff --git a/Frontend/src/components/screens/Activities/ActivitiesList.jsx b/Frontend/src/components/screens/Activities/ActivitiesList.jsx
index 58bdcb27..5ec2127a 100644
--- a/Frontend/src/components/screens/Activities/ActivitiesList.jsx
+++ b/Frontend/src/components/screens/Activities/ActivitiesList.jsx
@@ -17,7 +17,7 @@ import {AssetDetailItem} from '../../common';
*/
const ActivitiesList = (props) => {
const [, setListDropdownIndex] = useState(0);
- const colorsArray = ['rgb(59 151 210)', 'rgb(78 185 111)', 'rgb(228 126 37)', 'rgb(239 195 21)',{
+ const colorsArray = [{
'buy': ['blue', 'rgb(59, 151, 210, .2)'],
'deposit': ['green', 'rgb(78, 185, 111, .2)'],
'sell': ['brown', 'rgb(228, 126, 37, .2)'],
@@ -77,7 +77,7 @@ const ActivitiesList = (props) => {
- {activitiesForEachYearArray[index].length} total ·
+ {activitiesForEachYearArray[index].length} total ·
{activitiesForEachYearArray[index].filter(activity => activity.type === 'buy').length} buys ·
{activitiesForEachYearArray[index].filter(activity => activity.type === 'sell').length} sells ·
{activitiesForEachYearArray[index].filter(activity => activity.type === 'dividend').length} dividends ·
diff --git a/Frontend/src/components/screens/Activities/ActivitiesScreen.jsx b/Frontend/src/components/screens/Activities/ActivitiesScreen.jsx
index ad290cd3..576c619f 100644
--- a/Frontend/src/components/screens/Activities/ActivitiesScreen.jsx
+++ b/Frontend/src/components/screens/Activities/ActivitiesScreen.jsx
@@ -156,13 +156,51 @@ const ActivitiesScreen = props => {
Add Activity
-
+ {props.portfolioData[props.activePortfolio]['activities'].length === 0 ?
+
+
+ Start off by adding an Activity
+
+
+ Activities are the base for all data in Bench:market! They track changes in your portfolio and allow us to create detailed Charts about your Portfolio.
+
+
+ As soon as you add an activity our algorithms will automatically calculated all important numbers related to your portfolio. If your need any help you can always ask our Chatbot Benchi!
+
+
+
+ :
+
+ }
);
diff --git a/Frontend/src/components/screens/Activities/AddActivity/AddActivityForm.jsx b/Frontend/src/components/screens/Activities/AddActivity/AddActivityForm.jsx
index c75d310b..8f4987a6 100644
--- a/Frontend/src/components/screens/Activities/AddActivity/AddActivityForm.jsx
+++ b/Frontend/src/components/screens/Activities/AddActivity/AddActivityForm.jsx
@@ -1,6 +1,6 @@
import React, {useState, useEffect} from 'react';
import {useNavigate} from 'react-router-dom';
-import {Grid, Button, Box, TextField, MenuItem, styled, InputAdornment} from '@mui/material';
+import {Grid, Button, Box, TextField, MenuItem, InputAdornment} from '@mui/material';
import {LocalizationProvider} from '@mui/x-date-pickers/LocalizationProvider';
import {AdapterDateFns} from '@mui/x-date-pickers/AdapterDateFns';
import {DatePicker} from '@mui/x-date-pickers/DatePicker';
@@ -9,30 +9,7 @@ import ClearIcon from '@mui/icons-material/Clear';
import DragHandleIcon from '@mui/icons-material/DragHandle';
import PropTypes from 'prop-types';
import SearchAssetInput from './SearchAssetsInput';
-
-const StyledTextField = styled(TextField)({
- //Label color when focused
- '& label.Mui-focused': {
- color: '#493f35',
- },
- '& .MuiInput-underline:after': {
- borderBottomColor: '#493f35',
- },
- '& .MuiOutlinedInput-root': {
- //Standard border color
- '& fieldset': {
- borderColor: '#c4b8ac',
- },
- //Border color on hover
- '&:hover fieldset': {
- borderColor: '#493f35',
- },
- //Border color when focused
- '&.Mui-focused fieldset': {
- borderColor: '#493f35',
- },
- },
-});
+import { StyledTextField } from '../../../common';
/**
* Form for adding an activity
@@ -43,7 +20,7 @@ const StyledTextField = styled(TextField)({
const AddActivityForm = props => {
const initialValues = {
- assetType: 'share',
+ assetType: props.initialAssetObj ? (props.initialAssetObj.assetType === 'Crypto' ? 'crypto' : props.initialAssetObj.assetType === 'Cash' ? 'cash' : 'share') : 'share',
asset: props.initialAssetObj,
assetInput: '',
typeShare: 'buy',
diff --git a/Frontend/src/components/screens/Activities/AddActivity/SearchAssetsInput.jsx b/Frontend/src/components/screens/Activities/AddActivity/SearchAssetsInput.jsx
index 9360ed40..968d854a 100644
--- a/Frontend/src/components/screens/Activities/AddActivity/SearchAssetsInput.jsx
+++ b/Frontend/src/components/screens/Activities/AddActivity/SearchAssetsInput.jsx
@@ -3,6 +3,7 @@ import {Box} from '@mui/material';
import Autocomplete from '@mui/material/Autocomplete';
import CircularProgress from '@mui/material/CircularProgress';
import PropTypes from 'prop-types';
+import { Loading } from '../../../common';
/**
* Form for adding an activity
@@ -56,7 +57,7 @@ const SearchAssetInput = props => {
const [open, setOpen] = useState(false);
const [options, setOptions] = useState([]);
const [loading, setLoading] = useState(false);
- const [cash, setCash] = useState(false);
+ const [cash, setCash] = useState(props.initialAssetObj ? (props.initialAssetObj.assetType === 'Cash' ? true : false) : false);
const sharesInPortfolioOptions = getSharesInPortfolioOptions();
const cryptoInPortfolioOptions = getCryptoInPortfolioOptions();
@@ -258,7 +259,7 @@ const fetchCryptoOptions = async (query) => {
autoComplete: 'new-password', // disable autocomplete and autofill
endAdornment: (
- {loading ? : null}
+ {loading ? : null}
{params.InputProps.endAdornment}
),
diff --git a/Frontend/src/components/screens/Activities/Modals/activityModals.jsx b/Frontend/src/components/screens/Activities/Modals/activityModals.jsx
index 723a739d..509b6b35 100644
--- a/Frontend/src/components/screens/Activities/Modals/activityModals.jsx
+++ b/Frontend/src/components/screens/Activities/Modals/activityModals.jsx
@@ -19,10 +19,11 @@ export const renderRemoveActivityModal = (open, onClick, handleClose) => (
sx={{
color: 'white',
width: '5rem',
- borderColor: 'rgb(228 126 37)',
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#e47e25',
+ backgroundColor: '#e47e25',
'&:hover': {
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#c96208',
+ backgroundColor: '#e47e25',
}
}}
>
diff --git a/Frontend/src/components/screens/Analysis/AnalysisDetailitem.jsx b/Frontend/src/components/screens/Analysis/AnalysisDetailItem.jsx
similarity index 98%
rename from Frontend/src/components/screens/Analysis/AnalysisDetailitem.jsx
rename to Frontend/src/components/screens/Analysis/AnalysisDetailItem.jsx
index 3a008c8a..8752b5de 100644
--- a/Frontend/src/components/screens/Analysis/AnalysisDetailitem.jsx
+++ b/Frontend/src/components/screens/Analysis/AnalysisDetailItem.jsx
@@ -68,4 +68,4 @@ AnalysisDetailItem.propTypes = {
percentage: PropTypes.string,
};
-export default AnalysisDetailItem;
\ No newline at end of file
+export default AnalysisDetailItem;
diff --git a/Frontend/src/components/screens/Analysis/AnalysisList.jsx b/Frontend/src/components/screens/Analysis/AnalysisList.jsx
index c9f2ea7d..bc96b625 100644
--- a/Frontend/src/components/screens/Analysis/AnalysisList.jsx
+++ b/Frontend/src/components/screens/Analysis/AnalysisList.jsx
@@ -4,29 +4,7 @@ import {List, MenuItem, styled, TextField} from '@mui/material';
import AnalysisDetailItem from './AnalysisDetailItem';
import PropTypes from 'prop-types';
-const StyledTextField = styled(TextField)({
- //Label color when focused
- '& label.Mui-focused': {
- color: '#493f35',
- },
- '& .MuiInput-underline:after': {
- borderBottomColor: '#493f35',
- },
- '& .MuiOutlinedInput-root': {
- //Standard border color
- '& fieldset': {
- borderColor: '#c4b8ac',
- },
- //Border color on hover
- '&:hover fieldset': {
- borderColor: '#493f35',
- },
- //Border color when focused
- '&.Mui-focused fieldset': {
- borderColor: '#493f35',
- },
- },
-});
+import { StyledTextField } from '../../common';
/**
* Component to render the selected portfolio allocation list
diff --git a/Frontend/src/components/screens/Analysis/AnalysisScreen.jsx b/Frontend/src/components/screens/Analysis/AnalysisScreen.jsx
index 2daaed8e..bcf810e2 100644
--- a/Frontend/src/components/screens/Analysis/AnalysisScreen.jsx
+++ b/Frontend/src/components/screens/Analysis/AnalysisScreen.jsx
@@ -52,7 +52,8 @@ const AnalysisScreen = props => {
stockArray.push({
asset: element.name,
- percentage: parseFloat(percentage.toFixed(2))
+ percentage: parseFloat(percentage.toFixed(2)),
+ symbol: element.symbol
})
});
@@ -116,8 +117,6 @@ const AnalysisScreen = props => {
}
})
-
-
if(stockValue){
percentage = stockValue / value * 100;
@@ -145,7 +144,7 @@ const AnalysisScreen = props => {
})
}
- if(portfolioData.cashValue ){
+ if(portfolioData.cashValue){
percentage = portfolioData.cashValue / value * 100;
stockArray.push({
@@ -161,15 +160,18 @@ const AnalysisScreen = props => {
const getDoughnutChartData = (splitArray) => { //Perpare data for the doughnut chart
let labelArray = [];
let dataArray = [];
+ let symbolsArray = [];
splitArray.forEach(arrayElement => {
labelArray.push(arrayElement.asset)
dataArray.push(arrayElement.percentage)
+ symbolsArray.push(arrayElement.symbol)
});
return {
'labels': labelArray,
- 'data': dataArray
+ 'data': dataArray,
+ 'symbols': symbolsArray
}
}
@@ -206,6 +208,7 @@ const AnalysisScreen = props => {
analysis
data={doughnutChartData['data']}
labels={doughnutChartData['labels']}
+ symbols={doughnutChartData['symbols']}
defaultMiddleDisplayLabel={analysisTypes[analysisType]}
defaultMiddleDisplayValue={''}
/>
@@ -274,7 +277,7 @@ const AnalysisScreen = props => {
xs: 18
}}
>
- Start off by adding a Activity
+ Start off by adding an Activity
{
xs: 16
}}
>
- With activities you can fill your portfolio with your diffrent types of assets.
+ With activities you can fill your portfolio with your different types of assets.
{
xs: 16
}}
>
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+ Come back after adding one and see how your Portfolio is allocated!
diff --git a/Frontend/src/components/screens/Analysis/__test__/AnalysisScreen.test.jsx b/Frontend/src/components/screens/Analysis/__test__/AnalysisScreen.test.jsx
index 05d1c717..f327c036 100644
--- a/Frontend/src/components/screens/Analysis/__test__/AnalysisScreen.test.jsx
+++ b/Frontend/src/components/screens/Analysis/__test__/AnalysisScreen.test.jsx
@@ -8,6 +8,10 @@ import toJson from 'enzyme-to-json';
configure({adapter: new Adapter()});
+jest.mock('../../../../benchi-chatbot/TextToSpeech', () => ({
+ ctx: {}
+}));
+
it('AnalysisScreen renders without crashing', () => {
const setSearchResult = jest.fn();
const setPortfolioData = jest.fn();
diff --git a/Frontend/src/components/screens/AssetDetails/AssetCard.jsx b/Frontend/src/components/screens/AssetDetails/AssetCard.jsx
index 76e27e67..b135e1c3 100644
--- a/Frontend/src/components/screens/AssetDetails/AssetCard.jsx
+++ b/Frontend/src/components/screens/AssetDetails/AssetCard.jsx
@@ -1,8 +1,9 @@
import React, {useEffect, useState} from 'react';
+import {useNavigate} from 'react-router-dom';
import AssetChart from './AssetChart';
import ChartButtons from './ChartButtons';
import Masterdata from './Masterdata';
-import {Container, Card, Box} from '@mui/material';
+import {Container, Card, Box, Button} from '@mui/material';
import PropTypes from 'prop-types';
import SwitchButtons from './SwitchButtons';
import AssetPerformance from './AssetPerformance';
@@ -49,13 +50,36 @@ const AssetCard = props => {
}
}
+ const navigate = useNavigate();
+ const routeChange = path => {
+ navigate(path);
+ }
+
return (
-
+
+
{renderContent()}
diff --git a/Frontend/src/components/screens/AssetDetails/AssetPerformance.jsx b/Frontend/src/components/screens/AssetDetails/AssetPerformance.jsx
index 3bcc44af..e7398169 100644
--- a/Frontend/src/components/screens/AssetDetails/AssetPerformance.jsx
+++ b/Frontend/src/components/screens/AssetDetails/AssetPerformance.jsx
@@ -130,7 +130,7 @@ export const AssetPerformance = props => {
{
setRealised(!realised)
- }}/>} label='Realised Performance'/>
+ }}/>} label='Include realised Gains'/>
}/>
diff --git a/Frontend/src/components/screens/AssetDetails/__test__/AssetDetails.test.jsx b/Frontend/src/components/screens/AssetDetails/__test__/AssetDetails.test.jsx
index b0ba5b11..ecedff77 100644
--- a/Frontend/src/components/screens/AssetDetails/__test__/AssetDetails.test.jsx
+++ b/Frontend/src/components/screens/AssetDetails/__test__/AssetDetails.test.jsx
@@ -6,6 +6,10 @@ import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
Enzyme.configure({adapter: new Adapter()})
+jest.mock('../../../../benchi-chatbot/TextToSpeech', () => ({
+ ctx: {}
+}));
+
it('AssetDetailsScreen renders without crashing', () => {
const portfolioData = {
'Portfolio': {
diff --git a/Frontend/src/components/screens/Dashboard/AllocationGraph.jsx b/Frontend/src/components/screens/Dashboard/AllocationGraph.jsx
index e0ecc3c6..534b168c 100644
--- a/Frontend/src/components/screens/Dashboard/AllocationGraph.jsx
+++ b/Frontend/src/components/screens/Dashboard/AllocationGraph.jsx
@@ -28,6 +28,15 @@ const AllocationGraph = props => {
return labels;
})();
+ const symbols = (() => {
+ let symbols = [];
+ assets.forEach(element => {
+ let symbol = element['symbol'];
+ symbols.push(symbol);
+ });
+ return symbols;
+ })();
+
const valueData = (() => {
let valueData = [];
assets.forEach(element => {
@@ -40,6 +49,7 @@ const AllocationGraph = props => {
diff --git a/Frontend/src/components/screens/Dashboard/DashboardScreen.jsx b/Frontend/src/components/screens/Dashboard/DashboardScreen.jsx
index c954f7ae..7bb4649c 100644
--- a/Frontend/src/components/screens/Dashboard/DashboardScreen.jsx
+++ b/Frontend/src/components/screens/Dashboard/DashboardScreen.jsx
@@ -7,6 +7,7 @@ import AllocationGraph from './AllocationGraph';
import PortfolioOverview from './PortfolioOverview';
import PortfolioCharts from './PortfolioCharts';
import ChartButtons from '../AssetDetails/ChartButtons';
+import {RenderAddPortfolioModal} from './Modals/dashboardModals'
/**
* Component related to the dashboard screen
@@ -15,8 +16,10 @@ import ChartButtons from '../AssetDetails/ChartButtons';
* @constructor
*/
const DashboardScreen = props => {
- const [view, setView] = useState('month');
+ const [view, setView] = useState('all');
+ const [addPortfolioModal, setAddPortfolioModal] = useState(false);
+ //adds a dummyCash account to the data
const dummyCash = () => {
const cash = [{
firstActivity: '2900-01-01',
@@ -46,6 +49,42 @@ const DashboardScreen = props => {
return portfolioData;
});
}
+
+ //adds a new Portfolio to the data
+ const addPortfolio = (name) => {
+ props.setPortfolioData(prevData => {
+ const portfolioData = {...prevData,
+ [name]: {
+ 'name': name,
+ 'value': 0,
+ 'gains': 0,
+ 'realisedGains': 0,
+ 'totalGains': 0,
+ 'dividends': 0,
+ 'performanceWithRealisedGains': 0,
+ 'performanceWithoutRealisedGains': 0,
+ 'shares': [],
+ 'crypto': [],
+ 'cash': [],
+ 'activities': [],
+ 'activitiesLastId': -1,
+ 'dailyDataForValueDevelopment': {},
+ 'dailyDataForPerformanceGraph': {},
+ 'updated': '1970-01-01',
+ 'shareValue': 0,
+ 'cryptoValue': 0,
+ 'cashValue': 0
+ }
+ };
+ return portfolioData;
+ });
+ props.setActivePortfolio(name);
+ }
+
+ // Function to close the modals
+ const handleClose = () => {
+ setAddPortfolioModal(false);
+ }
const navigate = useNavigate();
const routeChange = path => {
@@ -56,7 +95,7 @@ const DashboardScreen = props => {
{
portfolioData={props.portfolioData}
activePortfolio={props.activePortfolio}
setActivePortfolio={props.setActivePortfolio}
+ setAddPortfolioModal={setAddPortfolioModal}
/>
@@ -79,81 +119,81 @@ const DashboardScreen = props => {
{props.portfolioData[props.activePortfolio]['dailyDataForValueDevelopment'] && Object.keys(props.portfolioData[props.activePortfolio]['dailyDataForValueDevelopment']).length === 0 ?
-
-
-
-
-
-
-
- Start off by adding a Activity
-
-
- Activities are the base for all data in Bench:market! They track changes in your portfolio and
-
-
- As soon as you add an activity our algorithms will automatically calculated all important numbers related to your portfolio. If your need any help you can always ask our Chatbot Benchi!
-
-
-
-
+ marginTop: '30px'
+ }}
+ >
+
+
+
+
+
+ Start off by adding an Activity
+
+
+ Activities are the base for all data in Bench:market! They track changes in your portfolio and allow us to create detailed Charts about your Portfolio.
+
+
+ As soon as you add an activity our algorithms will automatically calculated all important numbers related to your portfolio. If your need any help you can always ask our Chatbot Benchi!
+
+
+
:
}
@@ -163,6 +203,7 @@ const DashboardScreen = props => {
onClick={() => dummyCash()}
sx={{
margin: '1rem',
+ marginTop: '3rem',
color: '#4eb96f',
borderColor: '#4eb96f',
backgroundColor: 'white',
@@ -191,6 +232,12 @@ const DashboardScreen = props => {
messageType={props.messageType}
setMessageType={props.setMessageType}
/>
+ handleClose()}
+ onClick={(newPortfolioName) => addPortfolio(newPortfolioName)}
+ />
);
diff --git a/Frontend/src/components/screens/Dashboard/Modals/dashboardModals.jsx b/Frontend/src/components/screens/Dashboard/Modals/dashboardModals.jsx
new file mode 100644
index 00000000..fb8e5b9f
--- /dev/null
+++ b/Frontend/src/components/screens/Dashboard/Modals/dashboardModals.jsx
@@ -0,0 +1,90 @@
+import React, {useEffect, useState} from 'react';
+import {Button, FormControl, FormHelperText, InputLabel} from '@mui/material';
+import {CustomModal, StyledTextField} from '../../../common';
+
+export const RenderAddPortfolioModal = ({
+ open,
+ portfolioData,
+ handleClose,
+ onClick
+ }) => {
+ const [error, setError] = useState(false);
+ const [errorDescripton, setErrorDescripton] = useState('');
+ const [newPortfolioName, setNewPortfolioName] = useState('');
+
+ useEffect(() => {
+ if (open) {
+ if (newPortfolioName === '') {
+ setError(true);
+ setErrorDescripton('Can not be empty');
+ return;
+ }
+ const existingPortfolios = Object.keys(portfolioData);
+ for (let index = 0; index < existingPortfolios.length; index++) {
+ const element = existingPortfolios[index];
+ if (element === newPortfolioName) {
+ setError(true);
+ setErrorDescripton('Name is already used');
+ return;
+ }
+ }
+ setError(false);
+ }
+ }, [open, newPortfolioName]);
+
+ return (
+ {
+ handleClose();
+ setError(false);
+ }}
+ labelledby='add_portfolio-modal-title'
+ describedby='add_portfolio-modal-description'
+ modalTitle='Add a new portfolio:'
+ modalBody={() => (
+
+ {
+ setNewPortfolioName(event.target.value);
+ }}
+ />
+ {error && *{errorDescripton}}
+
+ )}
+ modalButton={() => (
+
+ )}
+ />
+ );
+ }
\ No newline at end of file
diff --git a/Frontend/src/components/screens/Dashboard/PortfolioCharts.jsx b/Frontend/src/components/screens/Dashboard/PortfolioCharts.jsx
index 7f9382a9..11debdcd 100644
--- a/Frontend/src/components/screens/Dashboard/PortfolioCharts.jsx
+++ b/Frontend/src/components/screens/Dashboard/PortfolioCharts.jsx
@@ -1,18 +1,21 @@
import React from 'react';
-import {Container, Box} from '@mui/material';
+import {Grid, Box} from '@mui/material';
import PortfolioPerformance from './PortfolioPerformance';
import PortfolioValueChart from './PortfolioValuechart';
export const PortfolioCharts = props => {
return (
-
-
+
+
-
+
-
-
+
+
)
}
diff --git a/Frontend/src/components/screens/Dashboard/PortfolioOverview.jsx b/Frontend/src/components/screens/Dashboard/PortfolioOverview.jsx
index 1be6538e..94781793 100644
--- a/Frontend/src/components/screens/Dashboard/PortfolioOverview.jsx
+++ b/Frontend/src/components/screens/Dashboard/PortfolioOverview.jsx
@@ -61,7 +61,7 @@ const PortfolioOverview = props => {
{}}
+ onClick={() => props.setAddPortfolioModal(true)}
>
@@ -96,6 +96,7 @@ PortfolioOverview.propTypes = {
activePortfolio: PropTypes.any,
setActivePortfolio: PropTypes.func,
portfolioData: PropTypes.object,
+ setAddPortfolioModal: PropTypes.func
};
export default PortfolioOverview;
\ No newline at end of file
diff --git a/Frontend/src/components/screens/Dashboard/PortfolioPerformance.jsx b/Frontend/src/components/screens/Dashboard/PortfolioPerformance.jsx
index 7983b225..1c80ff1f 100644
--- a/Frontend/src/components/screens/Dashboard/PortfolioPerformance.jsx
+++ b/Frontend/src/components/screens/Dashboard/PortfolioPerformance.jsx
@@ -134,7 +134,7 @@ export const PortfolioPerformance = props => {
control={ {
setRealised(!realised)
}}/>}
- label='Realised Performance'
+ label='Include realised Gains'
/>
}/>
diff --git a/Frontend/src/components/screens/Dashboard/__test__/DashboardScreen.test.jsx b/Frontend/src/components/screens/Dashboard/__test__/DashboardScreen.test.jsx
index b1c93b92..659e8948 100644
--- a/Frontend/src/components/screens/Dashboard/__test__/DashboardScreen.test.jsx
+++ b/Frontend/src/components/screens/Dashboard/__test__/DashboardScreen.test.jsx
@@ -3,9 +3,13 @@ import DashboardScreen from '../DashboardScreen';
import toJson from 'enzyme-to-json';
import Enzyme, {shallow} from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
+import {BrowserRouter} from 'react-router-dom';
Enzyme.configure({adapter: new Adapter()})
+jest.mock('../../../../benchi-chatbot/TextToSpeech', () => ({
+ ctx: {}
+}));
it('DashboardScreen renders without crashing', () => {
const portfolioData = {
@@ -29,8 +33,9 @@ it('DashboardScreen renders without crashing', () => {
const getAllAssets = jest.fn();
const setStatusMessage = jest.fn();
const setMessageType = jest.fn();
+ const addPortfolio = jest.fn();
- const wrapper = shallow(
+ const wrapper = shallow(
{
setPortfolioData={setPortfolioData}
setStatusMessage={setStatusMessage}
setMessageType={setMessageType}
- />);
+ />
+ );
expect(toJson(wrapper)).toMatchSnapshot();
})
\ No newline at end of file
diff --git a/Frontend/src/components/screens/Dashboard/__test__/__snapshots__/DashboardScreen.test.jsx.snap b/Frontend/src/components/screens/Dashboard/__test__/__snapshots__/DashboardScreen.test.jsx.snap
index a5d5ceea..6b5c5ec1 100644
--- a/Frontend/src/components/screens/Dashboard/__test__/__snapshots__/DashboardScreen.test.jsx.snap
+++ b/Frontend/src/components/screens/Dashboard/__test__/__snapshots__/DashboardScreen.test.jsx.snap
@@ -1,19 +1,69 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DashboardScreen renders without crashing 1`] = `
-
-
+
-
+
`;
diff --git a/Frontend/src/components/screens/ErrorPage.jsx b/Frontend/src/components/screens/ErrorPage.jsx
index ddce41aa..1c51718d 100644
--- a/Frontend/src/components/screens/ErrorPage.jsx
+++ b/Frontend/src/components/screens/ErrorPage.jsx
@@ -1,5 +1,5 @@
import React from 'react';
-import {Typography, Container, List, ListItem} from '@mui/material';
+import {Typography, Container } from '@mui/material';
import {Link} from 'react-router-dom';
const ErrorPage = () => (
diff --git a/Frontend/src/components/screens/Settings/Modals/settingsModals.jsx b/Frontend/src/components/screens/Settings/Modals/settingsModals.jsx
index 8349f6fc..7ad91d43 100644
--- a/Frontend/src/components/screens/Settings/Modals/settingsModals.jsx
+++ b/Frontend/src/components/screens/Settings/Modals/settingsModals.jsx
@@ -16,10 +16,11 @@ export const renderDeleteDataModal = (open, handleClose, onClick) => (
sx={{
color: 'white',
width: '5rem',
- borderColor: 'rgb(228 126 37)',
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#e47e25',
+ backgroundColor: '#e47e25',
'&:hover': {
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#c96208',
+ backgroundColor: '#e47e25',
}
}}
>
diff --git a/Frontend/src/components/screens/Settings/SettingsScreen.jsx b/Frontend/src/components/screens/Settings/SettingsScreen.jsx
index 203ecaf5..0931dcb8 100644
--- a/Frontend/src/components/screens/Settings/SettingsScreen.jsx
+++ b/Frontend/src/components/screens/Settings/SettingsScreen.jsx
@@ -4,7 +4,6 @@ import ScreensTemplate from '../../ScreensTemplate';
import {Container, Box, Button} from '@mui/material';
import {renderDeleteDataModal} from './Modals/settingsModals'
import PropTypes from 'prop-types';
-import {margin} from '@mui/system';
import {Grid} from '@mui/material';
import Typography from '@mui/material/Typography';
import SettingsIcon from '@mui/icons-material/Settings';
@@ -41,7 +40,7 @@ const SettingsScreen = props => {
{
{
xs: 12
}}
sx={{
+ color: 'white',
'@media screen and (max-width: 768px)': {
marginBottom: '40px'
}
@@ -188,7 +188,7 @@ const SettingsScreen = props => {
{
xs: 12
}}
sx={{
+ color: 'white',
'@media screen and (max-width: 768px)': {
marginBottom: '40px'
}
}}
>
- Delete your data to get an empty portfolio. Your watchlist will be reset as well. Be careful that we can't restore your data, so download it first if you still need it!
+ Delete your data to get an empty portfolio. Your watchlist will be reset as well. Be careful because we can't restore your data, so download it first if you still need it!
{
onClick={() => setDeleteDataModal(true)}
sx={{
color: 'white',
- borderColor: 'rgb(228 126 37)',
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#e47e25',
+ backgroundColor: '#e47e25',
'&:hover': {
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#c96208',
+ backgroundColor: '#e47e25',
},
margin: 'auto !important',
display: 'block'
diff --git a/Frontend/src/components/screens/Settings/__test__/SettingsScreen.test.jsx b/Frontend/src/components/screens/Settings/__test__/SettingsScreen.test.jsx
index 92964aa9..e795f837 100644
--- a/Frontend/src/components/screens/Settings/__test__/SettingsScreen.test.jsx
+++ b/Frontend/src/components/screens/Settings/__test__/SettingsScreen.test.jsx
@@ -7,6 +7,10 @@ import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
Enzyme.configure({adapter: new Adapter()})
+jest.mock('../../../../benchi-chatbot/TextToSpeech', () => ({
+ ctx: {}
+}));
+
it('SettingsScreen renders without crashing', () => {
const emptyPortfolioData = {
'Portfolio': {
diff --git a/Frontend/src/components/screens/WatchLists/AssetListItem.jsx b/Frontend/src/components/screens/WatchLists/AssetListItem.jsx
index d782bbf6..24dbe1fb 100644
--- a/Frontend/src/components/screens/WatchLists/AssetListItem.jsx
+++ b/Frontend/src/components/screens/WatchLists/AssetListItem.jsx
@@ -13,7 +13,6 @@ import {AssetDetailItem} from '../../common';
*/
const AssetListItem = props => {
const [, setListDropdownIndex] = useState(0);
- const colorsArray = ['rgb(59 151 210)', 'rgb(78 185 111)', 'rgb(228 126 37)', 'rgb(239 195 21)'];
return (
@@ -32,7 +31,6 @@ const AssetListItem = props => {
key={`asset_${index}`}
row={row}
index={index}
- colorsArray={colorsArray}
itemsArray={props.assetsListArray[props.selectedListIndex]}
listName={props.watchListsArray[index]}
selectedListIndex={props.selectedListIndex}
diff --git a/Frontend/src/components/screens/WatchLists/Modals/assetModals.jsx b/Frontend/src/components/screens/WatchLists/Modals/assetModals.jsx
index e17dd092..827e5f57 100644
--- a/Frontend/src/components/screens/WatchLists/Modals/assetModals.jsx
+++ b/Frontend/src/components/screens/WatchLists/Modals/assetModals.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import {Button, TextField} from '@mui/material';
-import {CustomModal} from '../../../common';
+import {CustomModal, StyledTextField} from '../../../common';
export const renderRemoveAssetModal = (open, handleClose, onClick) => (
(
sx={{
color: 'white',
width: '5rem',
- borderColor: 'rgb(228 126 37)',
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#e47e25',
+ backgroundColor: '#e47e25',
'&:hover': {
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#c96208',
+ backgroundColor: '#e47e25',
}
}}
>
@@ -37,7 +38,7 @@ export const renderAddAssetModal = (open, handleClose, errorModal, onChange, onC
describedby='add_asset-modal-description'
modalTitle='New asset'
modalBody={() => (
- (
(
- (
- (
sx={{
color: 'white',
width: '5rem',
- borderColor: 'rgb(228 126 37)',
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#e47e25',
+ backgroundColor: '#e47e25',
'&:hover': {
- backgroundColor: 'rgb(228 126 37)',
+ borderColor: '#c96208',
+ backgroundColor: '#e47e25',
}
}}
>
diff --git a/Frontend/src/components/screens/WatchLists/WatchLists.jsx b/Frontend/src/components/screens/WatchLists/WatchLists.jsx
index 1f588435..c192b6b9 100644
--- a/Frontend/src/components/screens/WatchLists/WatchLists.jsx
+++ b/Frontend/src/components/screens/WatchLists/WatchLists.jsx
@@ -25,29 +25,23 @@ import DropdownMenu from './DropdownMenu';
import CustomSelectField from './CustomSelectField';
import {renderAddWatchlistModal, renderEditListModal, renderRemoveListModal} from './Modals/watchlistModals';
-const StyledTextField = styled(TextField)({
- //Label color when focused
- '& label.Mui-focused': {
- color: '#493f35',
- },
- '& .MuiInput-underline:after': {
- borderBottomColor: '#493f35',
- },
- '& .MuiOutlinedInput-root': {
- //Standard border color
- '& fieldset': {
- borderColor: '#c4b8ac',
- },
- //Border color on hover
- '&:hover fieldset': {
- borderColor: '#493f35',
- },
- //Border color when focused
- '&.Mui-focused fieldset': {
- borderColor: '#493f35',
- },
- },
-});
+import { StyledTextField, Colors } from '../../common';
+
+/**
+ * Creates a hashCode from a String
+ * @param String
+ * @returns {interger}
+ */
+ String.prototype.hashCode = function() {
+ let hash = 0, i, chr;
+ if (this.length === 0) return hash;
+ for (i = 0; i < this.length; i++) {
+ chr = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + chr;
+ hash |= 0; // Convert to 32bit integer
+ }
+ return hash;
+};
/**
* Show all the watchLists
@@ -62,7 +56,7 @@ const WatchLists = props => {
const [watchlist, setWatchlist] = useState(undefined);
const [errorModal, setErrorModal] = useState(false);
const [listDropdownIndex, setListDropdownIndex] = useState(0);
- const avatarGroupColors = ['rgb(59 151 210)', 'rgb(78 185 111)', 'rgb(228 126 37)'];
+ const avatarGroupColors = Colors.COLORPALETTE;
const handleWatchListItemClick = (event, index) => {
props.setSelectedListIndex(index);
@@ -298,7 +292,7 @@ const WatchLists = props => {
'&.MuiAvatar-circular': {
borderColor: props.selectedListIndex === index ? 'white' : 'black'
},
- backgroundColor: avatarGroupColors[assetIndex],
+ backgroundColor: avatarGroupColors[asset.symbol.hashCode() % 10],
width: {
md: '1.2rem',
xl: '1.5rem'
diff --git a/Frontend/src/components/screens/WatchLists/__test__/WatchListsScreen.test.jsx b/Frontend/src/components/screens/WatchLists/__test__/WatchListsScreen.test.jsx
index 8df3abf4..002598ce 100644
--- a/Frontend/src/components/screens/WatchLists/__test__/WatchListsScreen.test.jsx
+++ b/Frontend/src/components/screens/WatchLists/__test__/WatchListsScreen.test.jsx
@@ -25,6 +25,10 @@ jest.mock('react-router-dom', () => ({
useNavigate: () => mockedNavigator
}));
+jest.mock('../../../../benchi-chatbot/TextToSpeech', () => ({
+ ctx: {}
+}));
+
describe('Tests regarding WatchList screen', () => {
const addToWatchList = jest.fn();
const setWatchListsArray = jest.fn();