diff --git a/.github/workflows/Reactjs.yml b/.github/workflows/Reactjs.yml index 91ea4991..c3562550 100644 --- a/.github/workflows/Reactjs.yml +++ b/.github/workflows/Reactjs.yml @@ -11,8 +11,11 @@ on: jobs: buildAndTest: - name: Build and Test Frontend - runs-on: ubuntu-latest + name: Build and Test Frontend on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] defaults: run: working-directory: ./frontend diff --git a/.gitignore b/.gitignore index 2494ccb8..6d68f400 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,10 @@ node_modules .idea /.vs/slnx.sqlite-journal .vs/slnx.sqlite +obj/Debug/netcoreapp5.0/amos-ss2021-carbon-footprint.csproj.AssemblyReference.cache frontend/yarn.lock +.vs/slnx.sqlite +.vs/amos-ss2021-carbon-footprint/v16/.suo +.vs/slnx.sqlite +.vs/slnx.sqlite diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index 37102765..20d00776 100644 Binary files a/.vs/slnx.sqlite and b/.vs/slnx.sqlite differ diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..5d7cc94b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/backend/Backend/Backend.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/backend/Backend/Backend.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/backend/Backend/Backend.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/backend/Backend/Backend.csproj b/backend/Backend/Backend.csproj index b412042f..34180f81 100644 --- a/backend/Backend/Backend.csproj +++ b/backend/Backend/Backend.csproj @@ -8,7 +8,7 @@ - + diff --git a/backend/Backend/Startup.cs b/backend/Backend/Startup.cs index 4631be96..05ec1281 100644 --- a/backend/Backend/Startup.cs +++ b/backend/Backend/Startup.cs @@ -29,10 +29,19 @@ public Startup(IConfiguration configuration) public IConfiguration Configuration { get; } + readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; + // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + services.AddCors(options => + { + options.AddPolicy(name: MyAllowSpecificOrigins, + builder => { + builder.WithOrigins("http://localhost:3000").AllowAnyHeader(); + }); + }); services.AddControllers(); services.AddSwaggerGen(c => { @@ -76,11 +85,14 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseRouting(); + app.UseCors(); + app.UseAuthorization(); app.UseEndpoints(endpoints => { - endpoints.MapControllers(); + endpoints.MapControllers() + .RequireCors(MyAllowSpecificOrigins); }); } diff --git a/deliverables/2021-06-30 - AMOS SS2021 - Team 8 - Planning Document.pdf b/deliverables/2021-06-30 - AMOS SS2021 - Team 8 - Planning Document.pdf new file mode 100644 index 00000000..efabeb35 Binary files /dev/null and b/deliverables/2021-06-30 - AMOS SS2021 - Team 8 - Planning Document.pdf differ diff --git a/deliverables/2021-06-30 Kanban Board.png b/deliverables/2021-06-30 Kanban Board.png new file mode 100644 index 00000000..562a62ee Binary files /dev/null and b/deliverables/2021-06-30 Kanban Board.png differ diff --git a/docs/drawing.svg b/docs/drawing.svg new file mode 100644 index 00000000..0750d838 --- /dev/null +++ b/docs/drawing.svg @@ -0,0 +1,123 @@ + + + + + + + + image/svg+xml + + + + + + + + + Dear Jimmy, + +First of all, I am sooo happy to know you. During this time being, We went through a lot during this 3 years.We had become more like two sistersI will miss you so much but pls keep in mind that you have a sister here. Wish you all the best ! :) And no worries , we will definetely keep in touch! + +Irem + + diff --git a/frontend/jest.config.js b/frontend/jest.config.js index 350fee7a..f0c4913c 100644 --- a/frontend/jest.config.js +++ b/frontend/jest.config.js @@ -187,3 +187,9 @@ module.exports = { // Whether to use watchman for file crawling // watchman: true, }; +module.exports = { + moduleNameMapper: { + '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|css|png|less|scss)$': + 'identity-obj-proxy' + } +}; diff --git a/frontend/package.json b/frontend/package.json index 4b468468..a996aea6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,8 @@ "dependencies": { "@material-ui/core": "^4.11.4", "@react-pdf/renderer": "^2.0.12", - "apexcharts": "^3.26.1", + "@reduxjs/toolkit": "^1.6.0", + "apexcharts": "^3.27.1", "axios": "^0.21.1", "cors": "^2.8.5", "html2canvas": "^1.0.0-rc.7", @@ -14,13 +15,16 @@ "jspdf-autotable": "^3.5.14", "prop-types": "^15.7.2", "react": "^16.13.1", + "react-alice-carousel": "^2.5.1", "react-apexcharts": "^1.3.9", "react-burger-menu": "^2.6.13", + "react-collapsible": "^2.8.3", "react-collapsible-content": "^1.0.0", "react-dom": "^16.8.6", "react-grid-system": "^7.1.2", "react-hook-form": "^7.4.2", "react-jss": "^10.6.0", + "react-redux": "^7.2.4", "react-router-dom": "^5.2.0", "react-scripts": "^4.0.3", "react-select": "^4.3.0", @@ -54,8 +58,12 @@ "devDependencies": { "@testing-library/jest-dom": "^5.12.0", "@testing-library/react": "^11.2.7", - "gh-pages": "^2.2.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.6", + "gh-pages": "^3.2.3", + "identity-obj-proxy": "^3.0.0", "jest": "26.6.0", + "jest-transform-stub": "^2.0.0", "prettier": "2.3.0" } } diff --git a/frontend/src/components/dashboard/UnresolvedTicketsComponent.js b/frontend/src/components/dashboard/UnresolvedTicketsComponent.js index 603be24e..952cbda6 100644 --- a/frontend/src/components/dashboard/UnresolvedTicketsComponent.js +++ b/frontend/src/components/dashboard/UnresolvedTicketsComponent.js @@ -32,8 +32,13 @@ function UnresolvedTicketsComponent({ containerStyles }) { title='Unresolved tickets' link='View details' subtitle='Group:' + subtitleTwo='Support' items={[ + renderStat('Waiting on Feature Request', 4238), + renderStat('Awaiting Customer Response', 1005), + renderStat('Awaiting Developer Fix', 914), + renderStat('Pending', 281), renderStat('Waiting on Feature Request', 4238), renderStat('Awaiting Customer Response', 1005), renderStat('Awaiting Developer Fix', 914), diff --git a/frontend/src/components/details/ColumnChartComponent.jsx b/frontend/src/components/details/ColumnChartComponent.jsx index 6cb1c186..ae9a93df 100644 --- a/frontend/src/components/details/ColumnChartComponent.jsx +++ b/frontend/src/components/details/ColumnChartComponent.jsx @@ -1,18 +1,18 @@ -import React from 'react'; +import { React } from 'react'; import ReactApexChart from 'react-apexcharts'; -import { getImpactAssessmentData, getLifeCycleStages } from 'interface/projectInterface'; +import { getColumnChartData, getLifeCycleStages } from 'interface/projectInterface'; /** * Column Chart - * - * @author Julian Oelhaf + * Recieves the data from projectInterface.js using "getColumnChartData()" + * populates the data ito the column chart in Details Page. */ const ColumnChartComponent = () => { + const values = getColumnChartData(); const series = [ { name: 'Global warming in kg CO2 equivalents', - // TODO: this data needs to be recieved from backend - data: getImpactAssessmentData() + data: values } ]; @@ -68,7 +68,7 @@ const ColumnChartComponent = () => { }, responsive: [ { - breakpoint: 300, + breakpoint: 6400, options: { chart: { width: 500 diff --git a/frontend/src/components/details/DetailsComponent.js b/frontend/src/components/details/DetailsComponent.js index d03334e3..b2f06451 100644 --- a/frontend/src/components/details/DetailsComponent.js +++ b/frontend/src/components/details/DetailsComponent.js @@ -5,14 +5,15 @@ import { jsPDF } from 'jspdf'; import html2canvas from 'html2canvas'; import { Col, Container, Row } from 'react-grid-system'; import './navbar.css'; -// import { postCalculationRequest } from 'interface/BackendConnect'; - +import { postCalculationRequest } from 'interface/BackendConnect'; +import LoadingComponent from 'components/loading'; /** * the main component for detail page which includes * canvas page and variable drop down list * * @param props the recently selected model of a product. */ + class DetailsComponent extends Component { /* State consists of three variable one for each of the possible state * baselineScenario: only display the baseline scenario @@ -22,7 +23,8 @@ class DetailsComponent extends Component { state = { baselineScenario: true, modifiedScenario: false, - loadComparePage: false + loadComparePage: false, + stillLoading: true }; render() { @@ -82,17 +84,29 @@ class DetailsComponent extends Component { pdf.save('invoice.pdf'); }); }; - + /* + * Important function that is given as the callback parameter to the postCalculationRequest in order to be called + * when the data processing is finished. Then the state stillLoading will be set to false. + * This change of state trigger the DetailsComponent to rerender and now display the charts and tables + * instead of the LoadingComponent. + */ + let handleFinishedDataRequest = () => { + this.setState({ stillLoading: false }); + }; const scenarioNames = { baseline: 'Baseline Scenario', modified: 'Modified Scenario' }; const { selectedProduct } = this.props; - // postCalculationRequest(selectedProduct.productID); + if (this.state.stillLoading) { + postCalculationRequest(selectedProduct.productID, handleFinishedDataRequest); + return ; + } if (this.state.baselineScenario) { // if state equals baseline scenario only + console.log(selectedProduct); return ( diff --git a/frontend/src/components/details/MobileTableComponent.jsx b/frontend/src/components/details/MobileTableComponent.jsx index 2874322c..984f24e9 100644 --- a/frontend/src/components/details/MobileTableComponent.jsx +++ b/frontend/src/components/details/MobileTableComponent.jsx @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import { Container } from 'react-grid-system'; import { getImpactCategoriesTableHeaders, - getImpactCategoriesTableData + getImpactAssessmentData } from 'interface/projectInterface'; import PropTypes from 'prop-types'; @@ -12,8 +12,8 @@ import PropTypes from 'prop-types'; */ class MobileTableComponent extends Component { state = { - headers: getImpactCategoriesTableHeaders(this.props.modelId), - rows: getImpactCategoriesTableData(this.props.modelId) + headers: getImpactCategoriesTableHeaders(), + rows: getImpactAssessmentData() }; render() { const idKey = this.props.tableKey; @@ -44,7 +44,8 @@ class MobileTableComponent extends Component { {header.value} - + {getRowDataHelper(idKey, index, this.state.rows)} + {/* {Object.values(this.state.rows[3])[index + 1]} @@ -52,38 +53,7 @@ class MobileTableComponent extends Component { {Object.values(this.state.rows[5])[index + 1]} - - - ))} - - - -
- - - {/* style needs to be defined in js */} - - {this.state.headers.map((header, index) => ( - - - - - + */} ))} @@ -94,10 +64,47 @@ class MobileTableComponent extends Component { } MobileTableComponent.propTypes = { - modelId: PropTypes.string.isRequired, + modelID: PropTypes.string.isRequired, productName: PropTypes.string.isRequired, modelName: PropTypes.string.isRequired, tableKey: PropTypes.string.isRequired }; export default MobileTableComponent; + +/** + * Makes life a little bit easier, and developers a little bit happier. + * (By translating the row data to column data for the Mobile component) + * + * @param {*} idKey - allows unique id to be generated + * @param {number} rowIndex - the index of the current row + * @param rows - the rowdata that will be accesed + * @returns the ; + case 1: + return ( + + ); + case 2: + return ; + + case 3: + return ; + case 4: + return ; + case 5: + return ; + case 6: + return ; + default: + return Material Composition - + @@ -63,7 +63,7 @@ class ScenarioComponent extends Component { > @@ -75,7 +75,7 @@ class ScenarioComponent extends Component { @@ -94,7 +94,7 @@ ScenarioComponent.propTypes = { onExportClick: PropTypes.func.isRequired, scenarioName: PropTypes.string, selectedProduct: PropTypes.shape({ - modelId: PropTypes.string, + modelID: PropTypes.string, modelName: PropTypes.string, productName: PropTypes.string }) diff --git a/frontend/src/components/details/SelectVariableComponent.jsx b/frontend/src/components/details/SelectVariableComponent.jsx index b2644354..4451af3e 100644 --- a/frontend/src/components/details/SelectVariableComponent.jsx +++ b/frontend/src/components/details/SelectVariableComponent.jsx @@ -3,7 +3,6 @@ import React, { Component } from 'react'; /** * a drop down component for selecting variable * - * @author Parham Gandomkar, Irem Toroslu */ class SelectVariableComponent extends Component { @@ -49,22 +48,18 @@ class SelectVariableComponent extends Component {
-
{this.state.variables.map((item) => ( - - ))}
diff --git a/frontend/src/components/details/TableComponent.jsx b/frontend/src/components/details/TableComponent.jsx index 0012bbf3..34f12b9f 100644 --- a/frontend/src/components/details/TableComponent.jsx +++ b/frontend/src/components/details/TableComponent.jsx @@ -3,16 +3,15 @@ import React, { Component } from 'react'; import { Container } from 'react-grid-system'; import { getImpactCategoriesTableHeaders, - getImpactCategoriesTableData + getImpactAssessmentData } from 'interface/projectInterface'; - /** * displays the impact catagories table of the selected model of the related product. */ class TableComponent extends Component { state = { - headers: getImpactCategoriesTableHeaders(this.props.modelId), - rows: getImpactCategoriesTableData(this.props.modelId) + headers: getImpactCategoriesTableHeaders(), + rows: getImpactAssessmentData() }; render() { const idKey = this.props.tableKey; @@ -35,18 +34,23 @@ class TableComponent extends Component { ))} +
- {this.state.rows.map((item, index) => ( - - - - - - - - - - ))} + + + + + + + + +
- {header.value} - - {Object.values(this.state.rows[0])[index + 1]} - - {Object.values(this.state.rows[1])[index + 1]} - - {Object.values(this.state.rows[2])[index + 1]} -
element of the corresponding row + */ +function getRowDataHelper(idKey, rowIndex, rows) { + switch (rowIndex) { + case 0: + return {'Global Warming'} + {'kg CO'} + 2 + {' eq'}{' '} + {rows.get('Total')}{rows.get('Materials')}{rows.get('Manufacturing and Transportation')}{rows.get('Operation')}{rows.get('End of life')}; + } +} diff --git a/frontend/src/components/details/NavbarComponent.js b/frontend/src/components/details/NavbarComponent.js index a2664f91..b576c52e 100644 --- a/frontend/src/components/details/NavbarComponent.js +++ b/frontend/src/components/details/NavbarComponent.js @@ -8,7 +8,6 @@ import { useHistory } from 'react-router-dom'; * a divider Pannel for seperating search compoents and result components * and also providing the comparison feature by compare button * - * @author Parham Gandomkar, Irem Toroslu, Julian Oelhaf, Mani Anand */ const NavbarComponent = (props) => { const history = useHistory(); @@ -19,7 +18,7 @@ const NavbarComponent = (props) => {
history.goBack()}> -
{item.impactCategory}{item.unit}{item.total}{item.materialsLPT}{item.manufacturing}{item.operations}{item.endOfLife}
{'Global Warming'} + {'kg CO'} + 2 + {' eq'}{' '} + {this.state.rows.get('Total')}{this.state.rows.get('Materials')} + {this.state.rows.get('Manufacturing and Transportation')} + {this.state.rows.get('Operation')}{this.state.rows.get('End of life')}
@@ -57,7 +61,7 @@ class TableComponent extends Component { export default TableComponent; TableComponent.propTypes = { - modelId: PropTypes.string.isRequired, + modelID: PropTypes.string.isRequired, modelName: PropTypes.string.isRequired, productName: PropTypes.string.isRequired, tableKey: PropTypes.string.isRequired diff --git a/frontend/src/components/login/LoginComponent.js b/frontend/src/components/login/LoginComponent.js index 0ece803d..7e4a77b9 100644 --- a/frontend/src/components/login/LoginComponent.js +++ b/frontend/src/components/login/LoginComponent.js @@ -48,6 +48,7 @@ function LoginComponent() { +