+
+
+
+
+
+
+ );
+}
+
+export default DashboardComponent;
diff --git a/frontend/src/components/mydashboard/MydashboardItemComponent.js b/frontend/src/components/mydashboard/MydashboardItemComponent.js
new file mode 100644
index 00000000..cf7e46b7
--- /dev/null
+++ b/frontend/src/components/mydashboard/MydashboardItemComponent.js
@@ -0,0 +1,199 @@
+import React from 'react';
+import { Column } from 'simple-flexbox';
+import { createUseStyles, useTheme } from 'react-jss';
+import PieChartComponent from 'components/details/PieChartComponent';
+import { Col, Container, Row } from 'react-grid-system';
+import Collapsible from 'react-collapsible';
+import Slideshow from './Slideshow';
+
+const data = [];
+
+for (let x = 1; x <= 24; x++) {
+ data.push({ x: x, y: Math.floor(Math.random() * 100) });
+}
+
+const useStyles = createUseStyles((theme) => ({
+ container: {
+ backgroundColor: '#FFFFFF',
+ border: `1px solid ${theme.color.lightGrayishBlue2}`,
+ borderRadius: 4,
+ cursor: 'pointer'
+ },
+ graphContainer: {
+ marginTop: 24,
+ marginLeft: 0,
+ marginRight: 0,
+ width: '100%'
+ },
+ graphSection: {
+ padding: 24
+ },
+ graphSubtitle: {
+ ...theme.typography.smallSubtitle,
+ color: theme.color.grayishBlue2,
+ marginTop: 4,
+ marginRight: 8
+ },
+ graphTitle: {
+ ...theme.typography.cardTitle,
+ color: theme.color.veryDarkGrayishBlue
+ },
+ legendTitle: {
+ ...theme.typography.smallSubtitle,
+ fontWeight: '600',
+ color: theme.color.grayishBlue2,
+ marginLeft: 8
+ },
+ separator: {
+ backgroundColor: theme.color.lightGrayishBlue2,
+ width: 1,
+ minWidth: 1
+ },
+ statContainer: {
+ borderBottom: `1px solid ${theme.color.lightGrayishBlue2}`,
+ padding: '24px 32px 24px 32px',
+ height: 'calc(114px - 48px)',
+ '&:last-child': {
+ border: 'none'
+ }
+ },
+ stats: {
+ borderTop: `1px solid ${theme.color.lightGrayishBlue2}`,
+ width: '100%'
+ },
+ statTitle: {
+ fontWeight: '600',
+ fontSize: 16,
+ lineHeight: '22px',
+ letterSpacing: '0.3px',
+ textAlign: 'center',
+ color: theme.color.grayishBlue2,
+ whiteSpace: 'nowrap',
+ marginBottom: 6
+ },
+ statValue: {
+ ...theme.typography.title,
+ textAlign: 'center',
+ color: theme.color.veryDarkGrayishBlue
+ }
+}));
+
+function MydashboardItemComponent() {
+ const theme = useTheme();
+ const classes = useStyles({ theme });
+
+ function renderStat(title, value) {
+ return (
+
+
+
+ {title}
+ {value}
+
+
+ );
+ }
+
+ return (
+
+
+
+
+ Catagories
+
+
+
+
+
+
+
+
+
+ Favorites
+
+
+ {renderStat('Fav Project 1', 'Transmission')}
+ {renderStat('Fav Project 2', 'Generation')}
+ {renderStat('Fav Project 3', 'Industrial App')}
+ {renderStat('Fav Project 1', 'Transmission')}
+ {renderStat('Fav Project 2', 'Generation')}
+ {renderStat('Fav Project 3', 'Industrial App')}
+ {renderStat('Fav Project 1', 'Transmission')}
+ {renderStat('Fav Project 2', 'Generation')}
+ {renderStat('Fav Project 3', 'Industrial App')}
+
+
+
+
+
+ My chart
+
+
+
+
+
+
+
+ My Recent Projects
+
+
+
+
+
This is the collapsible content.
+
+
+
+
+
This is the collapsible content.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default MydashboardItemComponent;
diff --git a/frontend/src/components/mydashboard/Slideshow.js b/frontend/src/components/mydashboard/Slideshow.js
new file mode 100644
index 00000000..ab040636
--- /dev/null
+++ b/frontend/src/components/mydashboard/Slideshow.js
@@ -0,0 +1,48 @@
+import React, { Component } from 'react';
+import AliceCarousel from 'react-alice-carousel';
+import 'react-alice-carousel/lib/alice-carousel.css';
+import IndustrialImage from 'assets/dummyImages/Industrialapplications.jpg';
+import PowerGeneration from 'assets/dummyImages/powerGeneration.jpg';
+import PowerTransmission from 'assets/dummyImages/powerTransmission.jpg';
+//import './mydashboard.css';
+
+export default class Slideshow extends Component {
+ constructor(props, context) {
+ super();
+ this.state = {
+ images: [IndustrialImage, PowerGeneration, PowerTransmission]
+ };
+ }
+ getData() {
+ const img = this.state.images.map((m) =>
);
+ }
+ responsive = {
+ 0: { items: 1 },
+ 1024: { items: 1 }
+ };
+ componentDidMount() {
+ this.getData();
+ }
+
+ render() {
+ const items = [
+
,
+
,
+
+ ];
+ return (
+
+ );
+ }
+}
diff --git a/frontend/src/components/mydashboard/index.js b/frontend/src/components/mydashboard/index.js
new file mode 100644
index 00000000..d8a1fa5a
--- /dev/null
+++ b/frontend/src/components/mydashboard/index.js
@@ -0,0 +1,3 @@
+import mydashboardComponent from './mydashboardComponent';
+
+export default mydashboardComponent;
diff --git a/frontend/src/components/mydashboard/mydashboard.css b/frontend/src/components/mydashboard/mydashboard.css
new file mode 100644
index 00000000..8533e5bb
--- /dev/null
+++ b/frontend/src/components/mydashboard/mydashboard.css
@@ -0,0 +1,149 @@
+.MydashboardContainer {
+ background-color: #ffffff;
+ /* border:0.5px solid #00b300; */
+ border-color: #00b300;
+ border-radius: 4px;
+ cursor: 'pointer';
+ min-width: 360;
+ max-width: 450;
+ min-height: 500px;
+ max-height: 500px;
+ margin-top: 10px;
+ position: fixed;
+
+}
+
+.FavCardsContainer {
+ background-color: #ffffff;
+ /* border:0.5px solid #00b300; */
+ border-radius: 4px;
+ cursor: 'pointer';
+ min-width: 360;
+ max-width: 450;
+ min-height: 500px;
+ max-height: 500px;
+ margin-top: 10px;
+ position: fixed;
+ overflow-y: visible;
+ overflow-y: scroll;
+} /* Make images easier to work with */
+.img {
+ max-width: 100%;
+ display: block;
+}
+.ProjectsCardsContainer {
+ background-color: #ffffff;
+ /* border:0.5px solid #00b300; */
+ border-radius: 4px;
+ cursor: 'pointer';
+ min-width: 360;
+ max-width: 450;
+ min-height: 500px;
+ max-height: 450px;
+ margin-top: 10px;
+ margin-bottom:10px;
+ position: fixed;
+ overflow-y: visible;
+ overflow-y: scroll;
+}
+
+.star {
+ float: right;
+ color: var(--global--button--text--color);
+ text-decoration: none;
+ font-size: 24px;
+ border-style: none;
+ cursor: pointer;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+.dashboardCardSubTitle i{
+ font-size: 10px;
+}
+
+.dashboardCardSubTitle{
+
+ font-family: inherit;
+ font-style: normal;
+ font-weight: bold;
+ font-size: var(--global--text-title--FontSize)-2;
+ letter-spacing: 0.5px;
+ color: #643082;
+ margin-bottom: 10px;
+ padding-left: 0px;
+ margin-top: 0px;
+ margin-bottom: 5px;
+ margin-left: 0px;
+
+
+
+}
+.dashboardTitle {
+ font-family: inherit;
+ font-style: normal;
+ font-weight: bold;
+ font-size: var(--global--text-title--FontSize);
+ letter-spacing: 0.5px;
+ color: #643082;
+ margin-bottom: 10px;
+ padding-left: 0px;
+ margin-top: 0px;
+ margin-bottom: 5px;
+ margin-left: 0px;
+}
+.dashboardCardSubTitle p{
+ font-family: inherit;
+ font-style: normal;
+ font-weight: normal;
+ font-size: var(--global--text-subtitle--FontSize);
+ letter-spacing: 0.5px;
+ color: var(--global--text--color);
+
+}
+
+.dashboardTitle i {
+ margin-right: 5px;
+ margin-left: 0px;
+}
+
+.favIcon {
+ float: left;
+ display: flex;
+ flex-direction: row;
+ font-weight: bold;
+ /* color: var(--global--panel--color); */
+ background-color: var(--global--background--color);
+ color: var(--global--button--text--color);
+ text-decoration: none;
+ font-size: 22px;
+ text-align: right; /* If you want the text to be centered */
+ border-style: none;
+ padding: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+
+.Collapsible :hover{
+
+ cursor: pointer;
+ color:#643082;
+
+}
+.active,
+.collapsible:hover {
+ background-color: #ccc;
+}
+
+/* Style the collapsible content*/
+.content {
+ padding: 0 18px;
+ display: none;
+ overflow: hidden;
+ background-color: #f1f1f1;
+}
+.alice-carousel ul li img {
+ height: 400px;
+ width: 100%;
+ object-fit: cover;
+}
diff --git a/frontend/src/components/productGrid/LabelComponent.js b/frontend/src/components/productGrid/LabelComponent.js
index 9835f794..01c1fa5c 100644
--- a/frontend/src/components/productGrid/LabelComponent.js
+++ b/frontend/src/components/productGrid/LabelComponent.js
@@ -4,7 +4,6 @@ import React from 'react';
/**
* Displaying a label.
*
- * @author Mani Anand, Martin Wagner
*/
function LabelComponent({ productName }) {
diff --git a/frontend/src/components/productGrid/ProductGridComponent.js b/frontend/src/components/productGrid/ProductGridComponent.js
index 5b51712f..9adbc2d0 100644
--- a/frontend/src/components/productGrid/ProductGridComponent.js
+++ b/frontend/src/components/productGrid/ProductGridComponent.js
@@ -2,13 +2,14 @@ import PropTypes from 'prop-types';
import React, { useContext, useState, useEffect } from 'react';
import { Col, Row, Container } from 'react-grid-system';
import MiniCardComponent from 'components/cards/MiniCardComponent';
-import { getCategorizedProducts } from 'interface/simaProInterface';
import ProductDropdown from './ModelDropdownComponent';
import SLUGS from 'resources/slugs';
import { Link } from 'react-router-dom';
import { PrivateSectionContext } from 'hooks/PrivateSectionContext';
import LabelComponent from './LabelComponent';
import LoadingComponent from 'components/loading';
+import { useDispatch, useSelector } from 'react-redux';
+import { loadProjects } from 'store/actions/productAction';
/**
* The Component creates new cards for the product items using the minicard components form 'components/cards/MiniCardComponent'
@@ -17,25 +18,21 @@ import LoadingComponent from 'components/loading';
* /**
*
* @returns the product and model properties
- * @author Irem Toroslu, Martin Wagner, Mani Anand
*/
function ProductGridComponent({ selectedCategory }) {
const [selectedProducts, setSelectedProducts] = useContext(PrivateSectionContext);
- const [productList, setProductList] = useState([]);
+ const [productList] = useState([]);
+ const products = useSelector((state) => state.products.data);
+ const dispatch = useDispatch();
/*
* useEffect declars the async function getProducts to be executed after the initial render and
* hooks it so the Component reloads on change. At the moment the specified change is the selectedCategory.
*/
useEffect(() => {
- async function getProducts(theSelectedCategory) {
- const products = await getCategorizedProducts(theSelectedCategory);
- setProductList(products);
- console.log(products);
- }
- getProducts(selectedCategory);
- }, [selectedCategory]);
+ dispatch(loadProjects(selectedCategory));
+ }, [selectedCategory, dispatch]);
// TODO: We cannot keep the selection like this, if models are implemented. See #58
const newSelectedProducts = [
@@ -48,18 +45,21 @@ function ProductGridComponent({ selectedCategory }) {
];
if (productList === [] || productList === undefined || productList === null) {
- return
;
+ console.error(
+ 'Products data not recieved.Please verify the API calls and Backend Connection.'
+ );
+ return
;
}
// else:
return (
- {productList.map((product, index) => (
+ {products?.map((product, index) => (
{
+ onClick={() => {
// Save selection to ContextProvider
newSelectedProducts[0].productID = product.productID;
newSelectedProducts[0].productName = product.productName;
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 05f35ccc..9b6a0c07 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -8,6 +8,7 @@
@import url('components/productGrid/ProductGridIndex.css');
@import url('routes/privateSection.css');
@import url('components/details/details.css');
+@import url('components/mydashboard/mydashboard.css');
/* css resets */
/* Box sizing rules */
diff --git a/frontend/src/index.js b/frontend/src/index.js
index e8cf67f0..465d5de2 100644
--- a/frontend/src/index.js
+++ b/frontend/src/index.js
@@ -7,14 +7,17 @@ import Routes from 'routes';
import './index.css';
import * as serviceWorker from './serviceWorker';
import { GlobalStateProvider } from 'hooks/GlobalContext';
-
+import store from './store'
+import { Provider } from 'react-redux'
ReactDOM.render(
+
+
,
document.getElementById('root')
);
diff --git a/frontend/src/interface/BackendConnect.js b/frontend/src/interface/BackendConnect.js
index 5c70c291..a220239b 100644
--- a/frontend/src/interface/BackendConnect.js
+++ b/frontend/src/interface/BackendConnect.js
@@ -1,14 +1,5 @@
import axios from 'axios';
-
-const headers = {
- Authorization: 'Bearer',
- 'My-Custom-Header': 'foobar'
-};
-
-//function timeout(delay) {
-// return new Promise((res) => setTimeout(res, delay));
-//}
-
+import { processBackendData } from 'interface/processBackendData';
/**
* Get request to det the details of all the projects from the API via backend.
* @returns the list of all the projects.
@@ -16,6 +7,11 @@ const headers = {
*/
export async function getSimaProProjects() {
// GET request using axios with set headers
+ const headers = {
+ Authorization: 'Bearer',
+ 'Access-Control-Allow-Origin': 'GET',
+ 'My-Custom-Header': 'foobar'
+ };
let result;
await axios
.get('https://localhost:44323/SimaPro/api/projects', { headers })
@@ -23,27 +19,83 @@ export async function getSimaProProjects() {
const items = data;
result = items.data.Result.Data;
});
+ //console.log('API call to get the list of Products');
+ //console.log(result);
return result;
}
/**
- * Post request to initiate the calculation for a project based on the project id.
- * This request returns the calculationId(calcd). which is then used to retrieve the impact
- * results of a project.
+ * Post request to initiate the calculation for a project based on the project id and preset values.
+ * This request is caught by the backend.
+ * Which then checks if the calculation is stored based on the calculationId generated.
+ * If the calculation is stored returns the results of calculation here.
*/
-export async function postCalculationRequest(projectId) {
+export async function postCalculationRequest(projectId, callback) {
// POST request using axios with set headers
- let result = await axios.post(`https://localhost:44323/SimaPro/api/calculation/${projectId}`, {
- headers
- });
+ const headers = {
+ Authorization: 'Bearer',
+ 'Access-Control-Allow-Origin': 'POST',
+ 'My-Custom-Header': 'foobar'
+ };
+ await axios
+ .post(`https://localhost:44323/SimaPro/api/calculation/${projectId}`, {
+ headers
+ })
+
+ .then(function (data) {
+ processBackendData(data, callback);
+ });
+}
+
+/**
+ * Post request to initiate the calculation for a project based on the project id and custom values.
+ * This request is caught by the backend.
+ * Which then checks if the calculation is stored based on the calculationId generated.
+ * If the calculation is stored returns the results of calculation here.
+ */
+export async function postCalculationRequestCustomSetup(projectId, processId, processName) {
+ // POST request using axios with set headers
+ const headers = {
+ Authorization: 'Bearer',
+ 'Access-Control-Allow-Origin': 'POST',
+ 'My-Custom-Header': 'foobar'
+ };
+ const body = {
+ Id: '00000000-0000-0000-0000-000000000000',
+ MethodId: '210215cc-99e5-4621-a7e0-f5a09ab530fa',
+ MethodName: 'ReCiPe 2016 Midpoint (H)',
+ NormalisationSetId: '86b7bb89-8904-4faf-8e56-2d8bccf13b2b',
+ NormalisationSetName: 'Default',
+ WeightingSetId: 'c5399d7e-67e1-4c18-a0f2-a745f2fdde32',
+ WeightingSetName: 'Default',
+ calculateParameterSets: true,
+ useAnalysisGroups: true,
+ combineOverrideInstanceValues: true,
+ CalculationItems: [
+ {
+ ProcessId: processId,
+ ProcessName: processName,
+ ProductId: projectId,
+ Amount: 1.0,
+ UnitId: 'aab0228e-f2c0-4954-88c8-c9805b594a37',
+ UnitName: 'kg'
+ }
+ ]
+ };
+ let result = await axios.post(
+ `https://localhost:44323/SimaPro/api/calculation/${projectId}`,
+ {
+ headers
+ },
+ { body }
+ );
// .then(function (data) {
// const items = data;
// calcId = items.data.Result.CalculationId;
// });
- console.log('RESULT!!!!!!1');
+ console.log('RESULT of the SimaPro/api/calculation/projectId call ');
console.log(result);
return result;
- //return await postCalculationResultRequest(calcId);
}
/**
@@ -51,8 +103,11 @@ export async function postCalculationRequest(projectId) {
*
*/
export async function getProjectProcesses(projectId) {
- //console.log("------");
- //console.log(productID);
+ const headers = {
+ Authorization: 'Bearer',
+ 'Access-Control-Allow-Origin': 'GET',
+ 'My-Custom-Header': 'foobar'
+ };
let resultProcess;
await axios
.get(`https://localhost:44323/SimaPro/api/processes/referencedata/${projectId}`, {
@@ -65,19 +120,3 @@ export async function getProjectProcesses(projectId) {
});
return resultProcess;
}
-
-/**
- * Get request to get all the methods required for drop down.
- * @returns the list of methods
- */
-export async function getMethods() {
- let methods;
- await axios
- .get('https://localhost:44323/SimaPro/api/methods', { headers })
- //Please verify this step
- .then(function (data) {
- const items = data;
- methods = items.data.Result.Data;
- });
- return methods;
-}
diff --git a/frontend/src/interface/processBackendData.js b/frontend/src/interface/processBackendData.js
new file mode 100644
index 00000000..9e322ca9
--- /dev/null
+++ b/frontend/src/interface/processBackendData.js
@@ -0,0 +1,74 @@
+import {
+ setMaterialCompositionLabels,
+ setMaterialCompositionData,
+ setImpactAssessmentData,
+ setColumnChartData
+} from 'interface/projectInterface';
+
+/*
+ * Function to process the data recieved from the backend
+ * Filters the carbon impact data recieved from API.
+ * Filter the Carbon Values of GlobalWarming
+ * Maps the Carbon Values and its corresponding life cycle stage.
+ * Filters out the material composition labels and data
+ * Filters out all materials less than 1%
+ * Calculate the impact assesment in percent for the column charts
+ *
+ * @param data: data recieved from PostCalculationRequest
+ * @param callback: the handleFinishedDataRequest function from the DetailsComponent.js, this function is called at the end of the data process
+ * the function changes the state of the DetailsComponent thus triggering a rerender and causing the DetailsComponent to display the charts
+ * instead of the loading circle
+ */
+export function processBackendData(data, callback) {
+ const items = data;
+ /*
+ * Filter out the "correct" materials
+ * ignore everything that is not unit = 'kg", because there is also Energy and Power in the List with unit MJ
+ * ignore all the material that are small than 0kg, because scrap and waste materials are represended by a
+ * negativ value and we want to exclude srap and waste
+ */
+ let materialData = items.data.Result.Results[0].Tables[0].Rows;
+ let finalMaterials = [];
+ let materialMap = new Map();
+ var sumOfMaterials = 0;
+ for (let z = 0; z < materialData.length; z++) {
+ //check if unit is kg
+ if (materialData[z][5] === 'kg') {
+ //check if weight is positiv --> input material
+ if (materialData[z][6] > 0) {
+ sumOfMaterials = sumOfMaterials + Number(materialData[z][6]);
+ finalMaterials.push(materialData[z]);
+ }
+ }
+ }
+ console.log('Sum of Material:');
+ console.log(sumOfMaterials);
+ for (let i = 0; i < finalMaterials.length; i++) {
+ if (Number(finalMaterials[i][6]) / sumOfMaterials > 0.01) {
+ materialMap.set(finalMaterials[i][0], finalMaterials[i][6]);
+ }
+ }
+
+ let carbonData = items.data.Result.Results[0].Tables[1].Rows;
+ let impactMap = new Map();
+ for (let i = 0; i < carbonData.length; i++) {
+ impactMap.set(carbonData[i][0], Number(carbonData[i][2]).toFixed(0));
+ }
+
+ let assessmentDataInPercent = [];
+ let assessmentValues = Array.from(impactMap.values());
+ let total = assessmentValues[4];
+
+ for (let i = 0; i < assessmentValues.length - 2; i++) {
+ if (!isNaN(assessmentValues[i])) {
+ assessmentDataInPercent[i] = (Number(assessmentValues[i] / total) * 100).toFixed(1);
+ }
+ }
+
+ setMaterialCompositionLabels(materialMap.keys());
+ setMaterialCompositionData(materialMap.values());
+ setImpactAssessmentData(impactMap);
+ setColumnChartData(assessmentDataInPercent);
+
+ callback();
+}
diff --git a/frontend/src/interface/projectInterface.js b/frontend/src/interface/projectInterface.js
index 1f4e7599..704eb2d0 100644
--- a/frontend/src/interface/projectInterface.js
+++ b/frontend/src/interface/projectInterface.js
@@ -1,12 +1,22 @@
/**
* The projectInterface is the interface between frontend and backend.
*
- * @author Martin Wagner, Julian Oelhaf
*/
import logo_1 from 'assets/dummyImages/Image_1.PNG';
import logo_3 from 'assets/dummyImages/Logo2.png';
+var materialCompositionLabels;
+var materialCompositionData;
+let materialDataInPercent;
+var assessmentValues;
+let chartDataInPercent = [];
+
+export function handOverBackendData(data) {
+ console.log('data');
+ console.log(data);
+}
+
/**
* should get all the Products from the backend (soon) //TODO: declare and write.
* @returns
@@ -29,51 +39,91 @@ export function getModels() {
}
/**
- * should get the material compositon of a specific model
- * inputs contribibuting less than 1% each, should have been filtered out by Siemens Energy
- * @param modelId id of the model, which we want to get the Data
+ * Gets the filtered Material Composititon Data from API
+ * inputs contribibuting less than 1% each, should have been filtered out processBackendData
+ * Calculates the percentage values and returns them.
+ * @param compositionData filtered data from backendconnnect
*/
-export function getMaterialCompositionData(modelId) {
- return [17, 13, 3, 2, 1, 42, 21];
+export function setMaterialCompositionData(compositionData) {
+ console.log('compositionData');
+ materialDataInPercent = [];
+ materialCompositionData = Array.from(compositionData);
+ console.log(materialCompositionData);
+ for (let i = 0; i < materialCompositionData.length; i++) {
+ materialDataInPercent[i] = Number(materialCompositionData[i]);
+ }
+ console.log(materialDataInPercent);
}
+
/**
- * @param modelId id of the model, which we want to get the Data
+ * Getter method to recieve the filtered Material Composititon Data from API
*/
-export function getMaterialCompositionLabels(modelId) {
- return [
- 'Transformer oil',
- 'Steel',
- 'Pressboard',
- 'Stainless steel',
- 'Aluminium',
- 'Silicon steel',
- 'Copper'
- ];
+export function getMaterialCompositionData() {
+ return materialDataInPercent;
}
/**
- * QUESTON: Do these categories stay the same?
+ * Gets the filtered Material Composititon Labels from API
+ * Calculates the percentage values and returns them.
+ * @param compositionData filtered data from backendconnnect
+ */
+export function setMaterialCompositionLabels(compositionLabels) {
+ materialCompositionLabels = Array.from(compositionLabels);
+ console.log(materialCompositionLabels);
+}
+
+/**
+ * Getter method to recieve the filtered Material Composititon Labels from API
+ */
+export function getMaterialCompositionLabels() {
+ return materialCompositionLabels;
+}
+
+/**
+ * Gets the Life Cycle Stages filtered from API
* Impact Assessment is done for each of the life cycle stage
- * @param modelId id of the model, which we want to get the Data
+ * @param modelID id of the model, which we want to get the Data
*/
-export function getLifeCycleStages(modelId) {
+export function getLifeCycleStages(modelID) {
return ['Materials', 'Manufacturing and Transport', 'Operation 30a (75% load)', 'End of Life'];
}
/**
- * Impact Assessment is done for each life cycle stage
- * QUESTION: amount of stages fixed?
- * @param modelId id of the model, which we want to get the Data
+ * Gets the Impact Assessment Data filtered from API
+ * Impact Assessment is done for each of the life cycle stage
+ * @param assessmentData recieved from Backendconnect
*/
-export function getImpactAssessmentData(modelId) {
- return [37, 3, 90, -50];
+export function setImpactAssessmentData(assessmentData) {
+ assessmentValues = assessmentData;
}
+/**
+ * Getter method to recieve the filtered Impact Assessment Data from API
+ */
+export function getImpactAssessmentData() {
+ return assessmentValues;
+}
+
+/**
+ * Gets the Impact Assessment Data filtered from API
+ * Impact Assessment is done for each of the life cycle stage
+ * Percentage is calulated
+ * @param assessmentData recieved from Backendconnect
+ */
+export function setColumnChartData(assessmentDataInPercent) {
+ chartDataInPercent = assessmentDataInPercent;
+}
+/**
+ * Getter method to recieve the filtered Impact Assessment Data from API
+ */
+export function getColumnChartData() {
+ return chartDataInPercent;
+}
/**
* * QUESTION: life cycle stages fixed?
- * @param modelId id of the model, for which we want to get the Data
+ * @param modelID id of the model, for which we want to get the Data
*/
-export function getImpactCategoriesTableHeaders(modelId) {
+export function getImpactCategoriesTableHeaders(modelID) {
return [
{ key: 'header-1', value: 'Impact Category' },
{ key: 'header-2', value: 'Unit' },
@@ -85,71 +135,10 @@ export function getImpactCategoriesTableHeaders(modelId) {
];
}
/**
- * QUESTION: how is the data structured?
- * Do we need to extract the data from a data structure?
- * @param modelId id of the model, for which we want to get the Data
+ * Gets the Impact Categories Table Data filtered from API
+ * Impact Assessment is done for each of the life cycle stage
+ * @param assessmentData recieved from Backendconnect and filtered here
*/
-export function getImpactCategoriesTableData(modelId) {
- return [
- {
- key: 'row-1',
- impactCategory: 'Global Warming',
- unit: 'kg CO2 eq',
- total: '2,350,811',
- materialsLPT: '874,356',
- manufacturing: '71,532',
- operations: '2,114,344',
- endOfLife: '-790,420'
- },
- {
- key: 'row-2',
- impactCategory: 'Ozon layer depletion',
- unit: 'kg CFC-11 eq',
- total: '12',
- materialsLPT: '0',
- manufacturing: '0',
- operations: '12',
- endOfLife: '0'
- },
- {
- key: 'row-3',
- impactCategory: 'Photochemical oxidant formation (POCP)',
- unit: 'kg C2H4 eq',
- total: '2,350,811',
- materialsLPT: '874,356',
- manufacturing: '71,532',
- operations: '2,114,344',
- endOfLife: '-332'
- },
- {
- key: 'row-4',
- impactCategory: 'Acidification',
- unit: 'kg SO2 eq',
- total: '12',
- materialsLPT: '0',
- manufacturing: '0',
- operations: '12',
- endOfLife: '12,159'
- },
- {
- key: 'row-5',
- impactCategory: 'Eutrophication',
- unit: 'kg PO4 eq',
- total: '12',
- materialsLPT: '0',
- manufacturing: '0',
- operations: '12',
- endOfLife: '–5,016'
- },
- {
- key: 'row-6',
- impactCategory: 'Nonrenewable energy',
- unit: 'MJ eq',
- total: '2,781,500,619',
- materialsLPT: '14,672,424',
- manufacturing: '1,454,845',
- operations: '2,774,610,300',
- endOfLife: '–9,236,950'
- }
- ];
+export function getImpactCategoriesTableData() {
+ return assessmentValues;
}
diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js
index 2c6e5c59..488e3a07 100644
--- a/frontend/src/interface/simaProInterface.js
+++ b/frontend/src/interface/simaProInterface.js
@@ -19,9 +19,11 @@ export async function getCategorizedProducts(scope = 'All') {
// We need to be able to get either all products from the backend, or only the Products of a selected Category
// e.g. '/generation/products'; '/transmission/services'; 'industrialApplications/solutions'
// The expected Product has a unique productID, a productName and an imagePath (if any)
+ // TODO: IMPROVE!
if (scope === 'All') {
return await getSimaProducts();
} else if (scope === 'solutions') {
+ console.log("solutions");
return getDummyProducts();
} else {
return await getSimaProducts();
@@ -110,7 +112,6 @@ function getDummyProducts() {
export async function getSimaProducts() {
const products = await getSimaProProjects();
let formattedProducts = [];
- console.log(products);
await products.forEach((product) => {
const productObject = {
productID: product.Id,
diff --git a/frontend/src/routes/PrivateRoutes.js b/frontend/src/routes/PrivateRoutes.js
index e1f4448b..afb83287 100644
--- a/frontend/src/routes/PrivateRoutes.js
+++ b/frontend/src/routes/PrivateRoutes.js
@@ -20,7 +20,8 @@ const ProductSolutionsServices = lazy(() =>
import('./dynamicPaths/ProductSolutionsServicesComponent')
);
// importing required components
-const DashboardComponent = lazy(() => import('../components/dashboard'));
+//const DashboardComponent = lazy(() => import('../components/dashboard'));
+const mydashboardComponent = lazy(() => import('../components/mydashboard/MydashboardComponent'));
/**
* Defining new Routes using private routes function
@@ -34,7 +35,7 @@ function PrivateRoutes() {
}>
-
+
diff --git a/frontend/src/setupTests.js b/frontend/src/setupTests.js
new file mode 100644
index 00000000..960ad642
--- /dev/null
+++ b/frontend/src/setupTests.js
@@ -0,0 +1,2 @@
+import '@testing-library/react/cleanup-after-each';
+import '@testing-library/jest-dom/extend-expect';
diff --git a/frontend/src/store/README.md b/frontend/src/store/README.md
new file mode 100644
index 00000000..4b0057ac
--- /dev/null
+++ b/frontend/src/store/README.md
@@ -0,0 +1,36 @@
+# How to state management with redux toolkit:
+
+optional: install redux devtools browser extension (chrome) to check state in browser devtools
+
+## To save data in state:
+`store/index.js`:
+```js
+ export default configureStore({
+ reducer: {
+ products: productReducer,
+
+ //ADD REDUCERS HERE
+ },
+ })
+```
+`store/slices/anythingSlice.js`
+ Add Slice similar to productSlice.js
+
+`store/actions/anythingAction.js`
+ Add Action like productAction.js, replace function that gets the data
+
+## To read data from state
+```js
+ import { useDispatch, useSelector } from 'react-redux';
+ const products = useSelector(state => state.products.data)
+ const dispatch = useDispatch();
+ dispatch(loadProjects()) //<-- call function that is defined in anythingAction.js
+```
+or if in component:
+```js
+ const products = useSelector(state => state.products.data)
+ const dispatch = useDispatch();
+ useEffect(() => {
+ dispatch(loadProjects())
+ }, []);
+```
\ No newline at end of file
diff --git a/frontend/src/store/actions/productAction.js b/frontend/src/store/actions/productAction.js
new file mode 100644
index 00000000..a2d56569
--- /dev/null
+++ b/frontend/src/store/actions/productAction.js
@@ -0,0 +1,14 @@
+import { getCategorizedProducts } from "interface/simaProInterface";
+import { processingProducts } from "store/slices/productSlice";
+
+export const loadProjects = (selectedCategory) => async (dispatch) => {
+ try {
+ await getCategorizedProducts(selectedCategory).then((products) => {
+ dispatch(
+ processingProducts(JSON.parse(JSON.stringify(products)))
+ );
+ })
+ } catch (error) {
+ console.warn("loading projects didnt work", error)
+ }
+};
diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js
new file mode 100644
index 00000000..cdac55bb
--- /dev/null
+++ b/frontend/src/store/index.js
@@ -0,0 +1,8 @@
+import { configureStore } from '@reduxjs/toolkit'
+import productReducer from "./slices/productSlice";
+
+export default configureStore({
+ reducer: {
+ products: productReducer,
+ },
+})
\ No newline at end of file
diff --git a/frontend/src/store/slices/productSlice.js b/frontend/src/store/slices/productSlice.js
new file mode 100644
index 00000000..604d062d
--- /dev/null
+++ b/frontend/src/store/slices/productSlice.js
@@ -0,0 +1,17 @@
+import { createSlice } from '@reduxjs/toolkit'
+
+export const productSlice = createSlice({
+ name: 'products',
+ initialState: {
+ data: [],
+ },
+ reducers: {
+ processingProducts: (state, action) => {
+ state.data = [...action.payload]
+ },
+ },
+})
+
+export const { processingProducts } = productSlice.actions
+
+export default productSlice.reducer
diff --git a/package-lock.json b/package-lock.json
index 803df3ed..ddca135d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,19 +1,6 @@
{
+ "name": "amos-ss2021-carbon-footprint",
+ "lockfileVersion": 2,
"requires": true,
- "lockfileVersion": 1,
- "dependencies": {
- "axios": {
- "version": "0.21.1",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
- "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
- "requires": {
- "follow-redirects": "^1.10.0"
- }
- },
- "follow-redirects": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
- "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
- }
- }
+ "packages": {}
}
diff --git a/wiki-images/RequiredPackages-VSInstaller1.png b/wiki-images/RequiredPackages-VSInstaller1.png
new file mode 100644
index 00000000..8a4c9b84
Binary files /dev/null and b/wiki-images/RequiredPackages-VSInstaller1.png differ
diff --git a/wiki-images/RequiredPackages-VSInstaller2.png b/wiki-images/RequiredPackages-VSInstaller2.png
new file mode 100644
index 00000000..39d1cb87
Binary files /dev/null and b/wiki-images/RequiredPackages-VSInstaller2.png differ
diff --git a/wiki-images/RequiredPackages-VSInstaller3.png b/wiki-images/RequiredPackages-VSInstaller3.png
new file mode 100644
index 00000000..38bb7f6b
Binary files /dev/null and b/wiki-images/RequiredPackages-VSInstaller3.png differ