diff --git a/frontend/src/assets/dummyData/dummyData.js b/frontend/src/assets/dummyData/dummyData.js new file mode 100644 index 00000000..5543fbaf --- /dev/null +++ b/frontend/src/assets/dummyData/dummyData.js @@ -0,0 +1,153 @@ +import logo from 'assets/logo/LogoCarbonteam.png'; +import logo_1 from 'assets/dummyImages/Image_1.PNG'; +import logo_2 from 'assets/dummyImages/Logo2.png'; + +export function getDummyProductData() { + // WTH are we looking for here? do we need to iterate over projects (api_demo_project, ...) or over final processes? + const products = [ + { + Id: '09f64eeb-13b0-4e09-9fb4-50398483ecfd', //(project_id?) final_process_id? (final_product_id?) + Name: 'Electric Motors#ID:09f64eeb-13b0-4e09-9fb4-50398483ecfd#Scenario:scenario_baseline', + Description: + 'Categorie:Generation/Product#Model:09f64eeb-13b0-4e09-9fb4-50398483ecfd#Location:Germany', + productImage: logo + }, + { + Id: 'aufwlc93-kldp-4fer-15s7-51245631fega', + Name: 'Electric Motors#ID:aufwlc93-kldp-4fer-15s7-51245631fega#Scenario:scenario_scenario1', + Description: + 'Categorie:Generation/Product#Model:09f64eeb-13b0-4e09-9fb4-503984f3ecfd#Location:Germany', + productImage: logo_1 + }, + { + Id: 'aufwlc93-kldp-4fer-15s7-5124563regen', + Name: 'Electric Motors#ID:aufwlc93-kldp-4fer-15s7-5124563regen#Scenario:scenario_scenario3', + Description: + 'Categorie:Generation/Product#Model:09f64eeb-13b0-4e09-9fb4-503984f3ecfd#Location:Germany', + productImage: logo_1 + }, + { + Id: 'aufwlc93-kldp-4fer-15s7-51245631mega', + Name: 'Electric Motors#ID:aufwlc93-kldp-4fer-15s7-51245631mega#Scenario:scenario_scenario2', + Description: + 'Categorie:Generation/Product#Model:09f64eeb-13b0-4e09-9fb4-503984f3ecfd#Location:Germany', + productImage: logo_1 + }, + { + Id: '7ghnaoeb-kfue-qp04-slfg-12059492gggg', + Name: 'Wireless Power Transmittor#ID:7ghnaoeb-kfue-qp04-slfg-12059492begp#Scenario:scenario_secondOption', + Description: + 'Categorie:Transmission/Product#Model:09f64eeb-12f0-4e09-9fb4-50398483ecfd#Location:Germany', + productImage: logo_2 + }, + { + Id: '7ghnaoeb-kfue-qp04-slfg-12059492begp', //(project_id?) final_process_id? (final_product_id?) + Name: 'Wireless Power Transmittor#ID:7ghnaoeb-kfue-qp04-slfg-12059492begp#Scenario:scenario_baseline', + Description: + 'Categorie:Transmission/Product#Model:09f64eeb-12f0-4e09-9fb4-50398483ecfd#Location:Germany', + productImage: logo_2 + }, + { + Id: 'whatis00-this-id00-just-d01n9352rnow', //(project_id?) final_process_id? (final_product_id?) + Name: 'Gas Turbine#ID:whatis00-this-id00-just-d01n9352rnow#Scenario:scenario_baseline', + Description: + 'Categorie:Generation/Product#Model:09f64eeb-12f0-4e09-9fb4-50395583ecfd#Location:Germany', + productImage: logo + }, + { + Id: 'aufglc25-kldd-4ger-16s2-51002631fell', //(project_id?) final_process_id? (final_product_id?) + Name: 'Alround Product#ID:aufglc25-kldd-4ger-16s2-51002631fell#Scenario:scenario_baseline', + Description: + 'Categorie:Generation/Product#Model:09f64eeb-1234-4e09-9fb4-50398483ecfd#Location:France', + productImage: logo_1 + }, + { + Id: 'aufglc25-kldd-4ger-16s2-5100Julian00', //(project_id?) final_process_id? (final_product_id?) + Name: 'Super Product#ID:aufglc25-kldd-4ger-16s2-5100Julian00#Scenario:scenario_baseline', + Description: + 'Categorie:Generation/Product#Model:09f64eeb-1234-4321-9fb4-50398483ecfd#Location:Germany', + productImage: logo_1 + }, + { + Id: 'aufglc25-kldd-4ger-16s2-5100100sai00', //(project_id?) final_process_id? (final_product_id?) + Name: 'Super Product#ID:aufglc25-kldd-4ger-16s2-5100100sai00#Scenario:scenario_1', + Description: + 'Categorie:Generation/Product#Model:09f64eeb-1234-4321-9fb4-50398483ecfd#Location:India', + productImage: logo_1 + }, + { + Id: 'aufglc25-kldd-4ger-16s2-5100MartinWl', //(project_id?) final_process_id? (final_product_id?) + Name: 'Super Service#ID:aufglc25-kldd-4ger-16s2-5100MartinWl#Scenario:scenario_baseline', + Description: + 'Categorie:Generation/Service#Model:09f64eeb-1234-4e09-9fb4-50398483ecfd#Location:Germany', + productImage: logo + }, + { + Id: 'aufglc25-kldd-4ger-16s2-510MartinD1l', //(project_id?) final_process_id? (final_product_id?) + Name: 'Super Service#ID:aufglc25-kldd-4ger-16s2-510MartinD1l#Scenario:scenario_1', + Description: + 'Categorie:Generation/Service#Model:09f64eeb-1234-4e09-9fb4-50398483ecfd#Location:Germany', + productImage: logo + }, + { + Id: 'aufglc25-kldd-4ger-16s2-510026Irem01', //(project_id?) final_process_id? (final_product_id?) + Name: 'Super Solution#ID:aufglc25-kldd-4ger-16s2-510026Irem01#Scenario:scenario_baseline', + Description: + 'Categorie:Generation/Solution#Model:09f64eeb-1234-4e09-9fb4-50398483ecfd#Location:Germany', + productImage: logo_1 + }, + { + Id: 'hello0th-ere0-4ger-16s2-51002631Mani', //(project_id?) final_process_id? (final_product_id?) + Name: 'Super Solution#ID:hello0th-ere0-4ger-16s2-51002631Mani#Scenario:scenario_1', + Description: + 'Categorie:Transmission/Solution#Model:09f64eeb-1234-4e09-9fb4-50398483ecfd#Location:India', + productImage: logo_1 + }, + { + Id: 'hello0th-ere0-4ger-16s2-51002Parham1', + Name: 'THE Solution#ID:hello0th-ere0-4ger-16s2-51002Parham1#Scenario:scenario_baseline', + Description: + 'Categorie:Transmission/Solution#Model:09f64eeb-1234-4e09-9fb4-50355483ecfd#Location:Iran', + productImage: logo_1 + } + ]; + return products; +} + +/** + * should get all the Models for one Product + * @param productID the id of the Project to get the models for + * @returns + */ +//export async function getModels(productID) { +export function getModels(productName, productID) { + switch (productID) { + case '09f64eeb-13b0-4e09-9fb4-50398483ecfd': + return [{ modelID: 1, productID: productID, modelName: 'Electric Motor Type 25b' }]; + case 'aufwlc93-kldp-4fer-15s7-51245631fega': + return []; + case '7ghnaoeb-kfue-qp04-slfg-12059492begp': + return [ + { modelID: 6, productID: productID, modelName: 'Transmitter DIN42a' }, + { modelID: 7, productID: productID, modelName: 'Transmitter DIN42b' }, + { modelID: 8, productID: productID, modelName: 'Transmitter DIN42c' }, + { modelID: 9, productID: productID, modelName: 'Transmitter DIN42d' } + ]; + case 'whatis00-this-id00-just-d01n9352rnow': + return [ + { modelID: 10, productID: productID, modelName: 'Gas Turbine Type 1' }, + { modelID: 11, productID: productID, modelName: 'Gas Turbine Type 2' }, + { modelID: 12, productID: productID, modelName: 'Gas Turbine Type 3' }, + { modelID: 13, productID: productID, modelName: 'Gas Turbine Type 4' } + ]; + case 'aufglc25-kldd-4ger-16s2-51002631fell': + return [ + { modelID: 14, productID: productID, modelName: 'Allround Product 1' }, + { modelID: 15, productID: productID, modelName: 'Allround Product 2' }, + { modelID: 16, productID: productID, modelName: 'Allround Product 3' }, + { modelID: 17, productID: productID, modelName: 'Allround Product 4' } + ]; + default: + return [{ modelID: 42, productID: productID, modelName: productName }]; + } +} diff --git a/frontend/src/components/login/LoginComponent.js b/frontend/src/components/login/LoginComponent.js index 7e4a77b9..d29bb377 100644 --- a/frontend/src/components/login/LoginComponent.js +++ b/frontend/src/components/login/LoginComponent.js @@ -4,6 +4,8 @@ import CarbonFootprintLogo from 'assets/logo/LogoCarbonteam.png'; import slugs from 'resources/slugs'; import { GlobalContext } from 'hooks/GlobalContext'; import React from 'react'; +import { useDispatch } from 'react-redux'; +import { loadProjects } from 'store/actions/productAction'; /** * The LoginComponent realizes the Login Page. @@ -13,13 +15,19 @@ import React from 'react'; function LoginComponent() { const [, setState] = useContext(GlobalContext); + const dispatch = useDispatch(); + return (
setState({ userIsLoggedIn: true })} + onSubmit={() => { + setState({ userIsLoggedIn: true }); + // Loads all Projects from SimaPro and stores them in the state. + dispatch(loadProjects()); + }} >
Carbon Footprint diff --git a/frontend/src/components/productGrid/ModelDropdownComponent.js b/frontend/src/components/productGrid/ModelDropdownComponent.js index 07681905..f0c55f63 100644 --- a/frontend/src/components/productGrid/ModelDropdownComponent.js +++ b/frontend/src/components/productGrid/ModelDropdownComponent.js @@ -1,8 +1,8 @@ import PropTypes from 'prop-types'; import React, { useContext, useState } from 'react'; -import { getModels } from 'interface/simaProInterface'; import { PrivateSectionContext } from 'hooks/PrivateSectionContext'; import LoadingComponent from 'components/loading'; +import { getModels } from 'assets/dummyData/dummyData'; /** * This component creates the dropdownboxes for the related products @@ -26,7 +26,7 @@ const ModelDropdownComponent = (props) => { //checking if the variable list is empty if (variables === [] || variables === undefined || variables === null) { - return ; + return ; } if (variables.length === 1) { diff --git a/frontend/src/components/productGrid/ProductGridComponent.js b/frontend/src/components/productGrid/ProductGridComponent.js index 9adbc2d0..d1b67800 100644 --- a/frontend/src/components/productGrid/ProductGridComponent.js +++ b/frontend/src/components/productGrid/ProductGridComponent.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, { useContext, useState, useEffect } from 'react'; +import React, { useContext, useState } from 'react'; import { Col, Row, Container } from 'react-grid-system'; import MiniCardComponent from 'components/cards/MiniCardComponent'; import ProductDropdown from './ModelDropdownComponent'; @@ -8,9 +8,9 @@ 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'; +import { useSelector } from 'react-redux'; +import { categories, types } from 'resources/globalConstants/categories'; /** * The Component creates new cards for the product items using the minicard components form 'components/cards/MiniCardComponent' * it displays all the related products images attached to each card in a certain category. @@ -20,19 +20,63 @@ import { loadProjects } from 'store/actions/productAction'; * @returns the product and model properties */ -function ProductGridComponent({ selectedCategory }) { +function ProductGridComponent({ selectedCategory, selectedType }) { const [selectedProducts, setSelectedProducts] = useContext(PrivateSectionContext); 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(() => { - dispatch(loadProjects(selectedCategory)); - }, [selectedCategory, dispatch]); + let preProducts = useSelector((state) => state); + let products; + + switch (selectedCategory) { + case categories.generation: + switch (selectedType) { + case types.product: + products = preProducts?.generation?.products; + break; + case types.solution: + products = preProducts?.generation?.solutions; + break; + case types.service: + products = preProducts?.generation?.services; + break; + default: + break; + } + break; + case categories.transmission: + switch (selectedType) { + case types.product: + products = preProducts?.transmission?.products; + break; + case types.solution: + products = preProducts?.transmission?.solutions; + break; + case types.service: + products = preProducts?.transmission?.services; + break; + default: + break; + } + break; + case categories.industrialApplications: + switch (selectedType) { + case types.product: + products = preProducts?.industrialApplication?.products; + break; + case types.solution: + products = preProducts?.industrialApplication?.solutions; + break; + case types.service: + products = preProducts?.industrialApplication?.services; + break; + default: + break; + } + break; + default: + products = []; + break; + } // TODO: We cannot keep the selection like this, if models are implemented. See #58 const newSelectedProducts = [ @@ -112,7 +156,8 @@ function ProductGridComponent({ selectedCategory }) { } ProductGridComponent.propTypes = { - selectedCategory: PropTypes.string.isRequired + selectedCategory: PropTypes.string.isRequired, + selectedType: PropTypes.string.isRequired }; export default ProductGridComponent; diff --git a/frontend/src/hooks/PrivateSectionContext.js b/frontend/src/hooks/PrivateSectionContext.js index 0b2c1915..86e82aa2 100644 --- a/frontend/src/hooks/PrivateSectionContext.js +++ b/frontend/src/hooks/PrivateSectionContext.js @@ -5,7 +5,7 @@ */ import React, { useState, createContext } from 'react'; -import { categories } from 'interface/categories'; +import { categories } from 'resources/globalConstants/categories'; export const PrivateSectionContext = createContext(); diff --git a/frontend/src/interface/BackendConnect.js b/frontend/src/interface/BackendConnect.js index a220239b..382a5ed1 100644 --- a/frontend/src/interface/BackendConnect.js +++ b/frontend/src/interface/BackendConnect.js @@ -19,8 +19,8 @@ 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); + console.log('API call to get the list of Products'); + console.log(result); return result; } diff --git a/frontend/src/interface/categories.js b/frontend/src/interface/categories.js deleted file mode 100644 index 32bcadb9..00000000 --- a/frontend/src/interface/categories.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * defines the category names that are also used in the Sidebar. - * - * @author Martin Wagner - */ - -export const categories = { - generation: 'Generation', - transmission: 'Transmission', - industrialApplications: 'Industrial Applications' -}; diff --git a/frontend/src/interface/processBackendData.js b/frontend/src/interface/processBackendData.js index 9e322ca9..db439235 100644 --- a/frontend/src/interface/processBackendData.js +++ b/frontend/src/interface/processBackendData.js @@ -4,6 +4,8 @@ import { setImpactAssessmentData, setColumnChartData } from 'interface/projectInterface'; +import { categories } from 'resources/globalConstants/categories'; +import { simaProCategories } from 'resources/globalConstants/SimaProProductCategories'; /* * Function to process the data recieved from the backend @@ -72,3 +74,40 @@ export function processBackendData(data, callback) { callback(); } +/** + * + * @param {*} projectDescription The comments mentioned in SimaPro Appliction. + * It if of the form "Categorie:[Generation/Transmission/IndustrialApplication]/[Solutions/Product/Services]#Model:ModelId#Location:loaction"" + * This function segrigates the projects based on Generation, Transmission and Industrial APplications as mentioned in peojectDescription. + * @returns projects based on Generation, Transmission and Industrial APplications + */ +export function projectCategoryProcessing(projectDescription) { + if ( + projectDescription === [] || + projectDescription === undefined || + projectDescription === null + ) { + return []; + } else if (projectDescription.split(/[#,:,/]/).includes(simaProCategories.generation)) { + return [categories.generation]; + } else if (projectDescription.split(/[#,:,/]/).includes(simaProCategories.transmission)) { + return [categories.transmission]; + } else { + return [categories.industrialApplications]; + } +} +/** + * + * @param {*} simaProjectName ProjectName as recieved from the Sima Pro application. + * It is of the form "ProjectName#ID:ProjectID#Scenario:scenario" + * This function seperated the Project name and Scenario name for further processing and stores them in scenarios + * @returns projectName and scenarioName for displaying in the ProductGrid Page + */ +export function projectNameProcessing(simaProjectName) { + let prjs = simaProjectName.split(/[#,:,/]/); + let ProjectNameAndScenarioName = { + projectName: prjs[0], + scenarioName: prjs[4] + }; + return ProjectNameAndScenarioName; +} diff --git a/frontend/src/interface/processProjects.js b/frontend/src/interface/processProjects.js new file mode 100644 index 00000000..760f2c31 --- /dev/null +++ b/frontend/src/interface/processProjects.js @@ -0,0 +1,48 @@ +/** + * + * Filters out any duplicate Products and stores them as a child of the basline Scneario + * + * @param {{ industrialApplications: { products: [], solutions: [], services: [] }, transmission: { products: [], solutions: [], services: [] },generation: { products: [], solutions: [], services: [] }}} typifiedAndCategorizedProducts the Products as previously arranged + * @returns + */ +export function processScenarios(typifiedAndCategorizedProducts) { + let baselineScneariosOnly = []; + let firstElement = { productName: '-1', scenarioType: '-1' }; + + for (let index = 0; index < typifiedAndCategorizedProducts.length; index++) { + const secondElement = typifiedAndCategorizedProducts[index]; + // First check whether we are looking at a duplicate pair + if (firstElement.productName.localeCompare(secondElement.productName) === 0) { + // Then make sure we have the baseline + if (firstElement.scenarioType.includes('baseline')) { + // Add the second one to the baseline and remove it from the array by not inserting it into the new array + firstElement.scenarioList.push(secondElement); + // Do not advance the firstElement Pointer, there might be more than one other scenario to come. + if (index === typifiedAndCategorizedProducts.length - 1) { + // We reached the end and the last element was a duplicate. Don't push that duplicate element but push + // the baseline element. + baselineScneariosOnly.push(firstElement); + } + } else { + // We have a scenario selected, and there somehow still is a duplicate + console.error('Invalid Duplicate found in processScenarios'); + } + } else { + // No duplicate: Advance firstElement Pointer + if (index > 0) { + // Skip the dummy first Element, then + // Add the finished first Element to the stack + baselineScneariosOnly.push(firstElement); + } + if (index === typifiedAndCategorizedProducts.length - 1) { + // We reached the end of the Array and don't have a duplicate, append second element as well. + baselineScneariosOnly.push(secondElement); + } else { + // Not at the end yet, advance pointer + firstElement = secondElement; + } + } + } + // When done with one iteration, return new Array + return baselineScneariosOnly; +} diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js index 488e3a07..ee8b26f0 100644 --- a/frontend/src/interface/simaProInterface.js +++ b/frontend/src/interface/simaProInterface.js @@ -2,124 +2,188 @@ * The simaProInterface is the interface between frontend, backend (and Sima Pro API). * It provides the needed utility functions. * - * @author Martin Wagner */ import logo from 'assets/logo/LogoCarbonteam.png'; -import logo_1 from 'assets/dummyImages/Image_1.PNG'; -import logo_2 from 'assets/dummyImages/Logo2.png'; -import { categories } from './categories'; import { getSimaProProjects } from 'interface/BackendConnect'; +import { projectCategoryProcessing, projectNameProcessing } from './processBackendData'; +import { getDummyProductData } from 'assets/dummyData/dummyData'; +import { types, categories } from 'resources/globalConstants/categories'; +import { simaProTypes } from 'resources/globalConstants/SimaProProductCategories'; +import { processScenarios } from './processProjects'; + +// Toggle to NOT use SimaPro Data +let useDummyData = true; /** - * should get all the Products from the backend (soon) - * @returns + * + * Sorts all projects in as per category and type. + * + * @returns the sorted projects object */ -export async function getCategorizedProducts(scope = 'All') { +export async function getCategorizedProducts() { // 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(); - } + let formattedProducts = await getSimaProducts(); + let productCategoriesAndTypes = { + industrialApplications: { products: [], solutions: [], services: [] }, + transmission: { products: [], solutions: [], services: [] }, + generation: { products: [], solutions: [], services: [] } + }; + formattedProducts.forEach((formattedProduct) => { + console.log('formattedProduct'); + console.log(formattedProduct); + switch (formattedProduct.categories[0]) { + case categories.transmission: + switch (formattedProduct.type) { + case types.product: + productCategoriesAndTypes.transmission.products.push(formattedProduct); + break; + case types.solution: + productCategoriesAndTypes.transmission.solutions.push(formattedProduct); + break; + case types.service: + productCategoriesAndTypes.transmission.services.push(formattedProduct); + break; + default: + break; + } + break; + case categories.generation: + switch (formattedProduct.type) { + case types.product: + productCategoriesAndTypes.generation.products.push(formattedProduct); + break; + case types.solution: + productCategoriesAndTypes.generation.solutions.push(formattedProduct); + break; + case types.service: + productCategoriesAndTypes.generation.services.push(formattedProduct); + break; + default: + break; + } + break; + case categories.industrialApplications: + switch (formattedProduct.type) { + case types.product: + productCategoriesAndTypes.industrialApplications.products.push( + formattedProduct + ); + break; + case types.solution: + productCategoriesAndTypes.industrialApplications.solutions.push( + formattedProduct + ); + break; + case types.service: + productCategoriesAndTypes.industrialApplications.services.push( + formattedProduct + ); + break; + default: + break; + } + break; + default: + break; + } + }); + console.log('Typified and Categorized Products'); + console.log(productCategoriesAndTypes); + + return productCategoriesAndTypes; } /** - * should get all the Models for one Product - * @param productID the id of the Project to get the models for - * @returns + * Reducing the SimaPro projects to products. + * The segrigation is based on the comment mentioned in the SimaPro application + * Further split the products based on the category + * sample comment: "Categorie:[Generation/Transmission/IndustrialApplication]/[Solutions/Product/Services]#Model:ModelId#Location:loaction" + *This function filters out all the products obtained from API */ -//export async function getModels(productID) { -export function getModels(productName, productID) { - switch (productID) { - case '09f64eeb-13b0-4e09-9fb4-50398483ecfd': - return [{ modelID: 1, productID: productID, modelName: 'Electric Motor Type 25b' }]; - case 'aufwlc93-kldp-4fer-15s7-51245631fega': - return []; - case '7ghnaoeb-kfue-qp04-slfg-12059492begp': - return [ - { modelID: 6, productID: productID, modelName: 'Transformer DIN42a' }, - { modelID: 7, productID: productID, modelName: 'Transformer DIN42b' }, - { modelID: 8, productID: productID, modelName: 'Transformer DIN42b' }, - { modelID: 9, productID: productID, modelName: 'Transformer DIN42b' } - ]; - case 'whatis00-this-id00-just-d01n9352rnow': - return [ - { modelID: 10, productID: productID, modelName: 'Gas Turbine Type 1' }, - { modelID: 11, productID: productID, modelName: 'Gas Turbine Type 2' }, - { modelID: 12, productID: productID, modelName: 'Gas Turbine Type 3' }, - { modelID: 13, productID: productID, modelName: 'Gas Turbine Type 4' } - ]; - case 'aufglc25-kldd-4ger-16s2-51002631fell': - return [ - { modelID: 14, productID: productID, modelName: 'Allround Product 1' }, - { modelID: 15, productID: productID, modelName: 'Allround Product 2' }, - { modelID: 16, productID: productID, modelName: 'Allround Product 3' }, - { modelID: 17, productID: productID, modelName: 'Allround Product 4' } - ]; - default: - return [{ modelID: 42, productID: productID, modelName: productName }]; +export async function getSimaProducts() { + let products; + if (!useDummyData) { + products = await getSimaProProjects(); + } else { + products = getDummyProductData(); } -} + let formattedProducts = []; + + // Format all the SimaPro Products in a way where we can work with them + products.forEach((product) => { + let description = product.Description; + let splittedString = description.split(/[#,:,/]/); + + console.log(splittedString); + + if (description === null) { + } else { + let productSolutionService; + + if (splittedString.includes(simaProTypes.product)) { + productSolutionService = types.product; + } else if (splittedString.includes(simaProTypes.solution)) { + productSolutionService = types.solution; + } else if (splittedString.includes(simaProTypes.service)) { + productSolutionService = types.service; + } -function getDummyProducts() { - // WTH are we looking for here? do we need to iterate over projects (api_demo_project, ...) or over final processes? - const products = [ - { - productID: '09f64eeb-13b0-4e09-9fb4-50398483ecfd', //(project_id?) final_process_id? (final_product_id?) - productName: 'Electric Motors', //final_process_name? -> probably rather the project name later. But unclear! - categories: [categories.generation, categories.transmission], - productImage: logo - }, - { - productID: 'aufwlc93-kldp-4fer-15s7-51245631fega', //(project_id?) final_process_id? (final_product_id?) - productName: 'Motors Type XYZb', //final_process_name? - categories: [categories.transmission], - productImage: logo_1 - }, - { - productID: '7ghnaoeb-kfue-qp04-slfg-12059492begp', //(project_id?) final_process_id? (final_product_id?) - productName: 'Transformers', //final_process_name? - categories: [categories.transmission], - productImage: logo_2 - }, - { - productID: 'whatis00-this-id00-just-d01n9352rnow', //(project_id?) final_process_id? (final_product_id?) - productName: 'Gas Turbines', //final_process_name? - categories: [categories.generation], - productImage: logo - }, - { - productID: 'aufglc25-kldd-4ger-16s2-51002631fell', //(project_id?) final_process_id? (final_product_id?) - productName: 'Allround Product', //final_process_name? - categories: [categories.transmission, categories.generation], - productImage: logo_1 + let projectAndScenarioName = projectNameProcessing(product.Name); + + // Definition of the object that is used to hold the data + + let productObject = { + productID: product.Id, + productName: projectAndScenarioName.projectName, + categories: projectCategoryProcessing(product.Description), + productImage: useDummyData ? product.productImage : logo, + type: productSolutionService, + scenarioType: projectAndScenarioName.scenarioName, + scenarioList: [] // A list of products starting with itself as the baseline Scenario + }; + + formattedProducts.push(productObject); } - ]; - return products; + }); + console.log('The formatted Products (getSimaProducts)'); + console.log(formattedProducts); + + // Now sort the Products Alphabetically and put the baseline Scenario in first place if the Names are identical + formattedProducts.sort(compareProducts); + + // and then process them to not show scenario duplicates + let processedAndSortedTastyProducts = processScenarios(formattedProducts); + + return processedAndSortedTastyProducts; } /** - * Reducing the SimaPro projects to products. - * + * Function used to determine the order of the elements. + * It is expected to return + * - a negative value if first argument is less than second argument, + * - zero if they're equal and + * - a positive value otherwise. + * If omitted, the elements are sorted in ascending, ASCII character order. + * @param {{productName: String, scenarioType: String}} productA + * @param {{productName: String, scenarioType: String}} productB */ -export async function getSimaProducts() { - const products = await getSimaProProjects(); - let formattedProducts = []; - await products.forEach((product) => { - const productObject = { - productID: product.Id, - productName: product.Name, - categories: [categories.generation, categories.transmission], - productImage: logo - }; - formattedProducts.push(productObject); - }); - return formattedProducts; +function compareProducts(productA, productB) { + let evaluation = productA.productName.localeCompare(productB.productName); + + // Put the baseline first + if (evaluation === 0) { + if (productA.scenarioType.includes('baseline')) { + return -1; + } else if (productB.scenarioType.includes('baseline')) { + return 1; + } else { + return productA.scenarioType.localeCompare(productB.scenarioType); + } + } else { + return evaluation; + } } diff --git a/frontend/src/resources/globalConstants/SimaProProductCategories.js b/frontend/src/resources/globalConstants/SimaProProductCategories.js new file mode 100644 index 00000000..119e3b3c --- /dev/null +++ b/frontend/src/resources/globalConstants/SimaProProductCategories.js @@ -0,0 +1,14 @@ +/** + * Defines the CategorieNames the way that they can be found inside of SimaPro Projects + */ +export const simaProCategories = { + generation: 'Generation', + transmission: 'Transmission', + industrialApplications: 'IndustrialApplication' +}; + +export const simaProTypes = { + product: 'Product', + solution: 'Solution', + service: 'Service' +}; diff --git a/frontend/src/resources/globalConstants/categories.js b/frontend/src/resources/globalConstants/categories.js new file mode 100644 index 00000000..ad6f7c7a --- /dev/null +++ b/frontend/src/resources/globalConstants/categories.js @@ -0,0 +1,17 @@ +/** + * Defines the category names of the projects that are also used in the Sidebar. + */ +export const categories = { + generation: 'Generation', + transmission: 'Transmission', + industrialApplications: 'Industrial Application' +}; + +/** + * Defines the type names of the projects. + */ +export const types = { + product: 'product', + solution: 'solution', + service: 'service' +}; diff --git a/frontend/src/resources/globalConstants/productObjectClass.js b/frontend/src/resources/globalConstants/productObjectClass.js new file mode 100644 index 00000000..2c5532f1 --- /dev/null +++ b/frontend/src/resources/globalConstants/productObjectClass.js @@ -0,0 +1,41 @@ +/** + * a productObject, that holds all data of one product + */ +export default class productObject { + productID = ''; + productName = ''; + categories = []; + productImage = ''; + type = ''; + scenarioType = ''; + scenarioList = []; // A list of products starting with itself as the baseline Scenario + + /** + * Creates a new productObject + * + * @param {String} productID + * @param {String} productName + * @param {[String]} categories + * @param {String} productImage + * @param {String} type + * @param {String} scenarioType + * @param {[productObject]} scenarioList + */ + constructor( + productID, + productName, + categories, + productImage, + type, + scenarioType, + scenarioList + ) { + this.productID = productID; + this.productName = productName; + this.categories = categories; + this.productImage = productImage; + this.type = type; + this.scenarioType = scenarioType; + this.scenarioList = scenarioList; + } +} diff --git a/frontend/src/resources/slugs.js b/frontend/src/resources/slugs.js index 061c0a6a..107e881c 100644 --- a/frontend/src/resources/slugs.js +++ b/frontend/src/resources/slugs.js @@ -2,6 +2,8 @@ * slugs.js defines all known path extensions */ +import { types } from './globalConstants/categories'; + const slugs = { // private comparison: '/comparison', @@ -10,9 +12,9 @@ const slugs = { generation: '/generation', transmission: '/transmission', industrialApplications: '/industrialApplications', - products: '/products', - solutions: '/solutions', - services: '/services', + products: '/' + types.product, + solutions: '/' + types.solution, + services: '/' + types.service, overview: '/overview', quickguide: '/quickguide', overviewTwo: '/overview/two', diff --git a/frontend/src/routes/PrivateRoutes.js b/frontend/src/routes/PrivateRoutes.js index afb83287..3cbaffde 100644 --- a/frontend/src/routes/PrivateRoutes.js +++ b/frontend/src/routes/PrivateRoutes.js @@ -16,9 +16,9 @@ import GenerationInfo from 'components/productGrid/GenerationInfo'; import TransmissionInfo from 'components/productGrid/TransmissionInfo'; import IndustrialApplicationInfo from 'components/productGrid/IndustrialApplicationInfo'; import CategoryIndex from 'components/productGrid/CategoryIndex'; -const ProductSolutionsServices = lazy(() => - import('./dynamicPaths/ProductSolutionsServicesComponent') -); +import ProductSolutionsServicesComponent from 'routes/dynamicPaths/ProductSolutionsServicesComponent'; +import { categories } from 'resources/globalConstants/categories'; + // importing required components //const DashboardComponent = lazy(() => import('../components/dashboard')); const mydashboardComponent = lazy(() => import('../components/mydashboard/MydashboardComponent')); @@ -48,15 +48,23 @@ function PrivateRoutes() { ( + + )} /> ( + + )} /> ( + + )} /> ; + return ; } + +ProductSolutionsServicesComponent.propTypes = { + category: PropTypes.string.isRequired +}; diff --git a/frontend/src/store/actions/productAction.js b/frontend/src/store/actions/productAction.js index a2d56569..03112d05 100644 --- a/frontend/src/store/actions/productAction.js +++ b/frontend/src/store/actions/productAction.js @@ -1,14 +1,20 @@ -import { getCategorizedProducts } from "interface/simaProInterface"; -import { processingProducts } from "store/slices/productSlice"; +import { getCategorizedProducts } from 'interface/simaProInterface'; +import { processingIndustrialApplications } from 'store/slices/industrialApplicationsSlice'; +import { processingGeneration } from 'store/slices/generationSlice'; +import { processingTransmission } from 'store/slices/transmissionSlice'; -export const loadProjects = (selectedCategory) => async (dispatch) => { +export const loadProjects = () => async (dispatch) => { try { - await getCategorizedProducts(selectedCategory).then((products) => { - dispatch( - processingProducts(JSON.parse(JSON.stringify(products))) - ); - }) + await getCategorizedProducts().then((products) => { + dispatch(processingGeneration(JSON.parse(JSON.stringify(products.generation)))); + dispatch(processingTransmission(JSON.parse(JSON.stringify(products.transmission)))); + dispatch( + processingIndustrialApplications( + JSON.parse(JSON.stringify(products.industrialApplications)) + ) + ); + }); } catch (error) { - console.warn("loading projects didnt work", error) + console.warn('loading projects didnt work', error); } }; diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index cdac55bb..ddd1b1b6 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -1,8 +1,12 @@ -import { configureStore } from '@reduxjs/toolkit' -import productReducer from "./slices/productSlice"; +import { configureStore } from '@reduxjs/toolkit'; +import industrialApplicationsReducer from './slices/industrialApplicationsSlice'; +import generationReducer from './slices/generationSlice'; +import transmissionReducer from './slices/transmissionSlice'; export default configureStore({ - reducer: { - products: productReducer, - }, -}) \ No newline at end of file + reducer: { + industrialApplications: industrialApplicationsReducer, + generation: generationReducer, + transmission: transmissionReducer + } +}); diff --git a/frontend/src/store/slices/generationSlice.js b/frontend/src/store/slices/generationSlice.js new file mode 100644 index 00000000..27f81c08 --- /dev/null +++ b/frontend/src/store/slices/generationSlice.js @@ -0,0 +1,21 @@ +import { createSlice } from '@reduxjs/toolkit'; + +export const generationSlice = createSlice({ + name: 'generation', + initialState: { + products: [], + solutions: [], + services: [] + }, + reducers: { + processingGeneration: (state, action) => { + state.products = [...action.payload.products]; + state.solutions = [...action.payload.solutions]; + state.services = [...action.payload.services]; + } + } +}); + +export const { processingGeneration } = generationSlice.actions; + +export default generationSlice.reducer; diff --git a/frontend/src/store/slices/industrialApplicationsSlice.js b/frontend/src/store/slices/industrialApplicationsSlice.js new file mode 100644 index 00000000..70f14226 --- /dev/null +++ b/frontend/src/store/slices/industrialApplicationsSlice.js @@ -0,0 +1,21 @@ +import { createSlice } from '@reduxjs/toolkit'; + +export const industrialApplicationsSlice = createSlice({ + name: 'industralApplications', + initialState: { + products: [], + solutions: [], + services: [] + }, + reducers: { + processingIndustrialApplications: (state, action) => { + state.products = [...action.payload.products]; + state.solutions = [...action.payload.solutions]; + state.services = [...action.payload.services]; + } + } +}); + +export const { processingIndustrialApplications } = industrialApplicationsSlice.actions; + +export default industrialApplicationsSlice.reducer; diff --git a/frontend/src/store/slices/productSlice.js b/frontend/src/store/slices/productSlice.js deleted file mode 100644 index 604d062d..00000000 --- a/frontend/src/store/slices/productSlice.js +++ /dev/null @@ -1,17 +0,0 @@ -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/frontend/src/store/slices/transmissionSlice.js b/frontend/src/store/slices/transmissionSlice.js new file mode 100644 index 00000000..da54e5bc --- /dev/null +++ b/frontend/src/store/slices/transmissionSlice.js @@ -0,0 +1,21 @@ +import { createSlice } from '@reduxjs/toolkit'; + +export const transmissionSlice = createSlice({ + name: 'transmission', + initialState: { + products: [], + solutions: [], + services: [] + }, + reducers: { + processingTransmission: (state, action) => { + state.products = [...action.payload.products]; + state.solutions = [...action.payload.solutions]; + state.services = [...action.payload.services]; + } + } +}); + +export const { processingTransmission } = transmissionSlice.actions; + +export default transmissionSlice.reducer;