diff --git a/.github/workflows/Reactjs.yml b/.github/workflows/Reactjs.yml index ec9d7cbd..91ea4991 100644 --- a/.github/workflows/Reactjs.yml +++ b/.github/workflows/Reactjs.yml @@ -7,7 +7,7 @@ on: push: branches: [ main, release ] pull_request: - branches: [ main, frontend-dev, release ] + branches: [ main, frontend-dev, release, dev ] jobs: buildAndTest: diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 4758e580..d5b2979f 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -4,7 +4,7 @@ on: push: branches: [ main, release ] pull_request: - branches: [ main, backend-dev, release ] + branches: [ main, backend-dev, release, dev ] jobs: build: diff --git a/.gitignore b/.gitignore index e5e57a24..2494ccb8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ node_modules .idea /.vs/slnx.sqlite-journal .vs/slnx.sqlite + +frontend/yarn.lock diff --git a/backend/Backend/Middleware/RequestInterceptorDelegatingHandler.cs b/backend/Backend/Middleware/RequestInterceptorDelegatingHandler.cs new file mode 100644 index 00000000..4bcff7d8 --- /dev/null +++ b/backend/Backend/Middleware/RequestInterceptorDelegatingHandler.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.IO.Compression; +using System.IO; +using System.Text; + +namespace Backend.Middleware +{ + // Catch the http post request(postCalculationRequest) from front-end. + // Further process the request and send back the Results to fornt-end. + public class RequestInterceptorDelegatingHandler : DelegatingHandler + { + private readonly string baseUrl; + + public RequestInterceptorDelegatingHandler(IConfiguration configuration) + { + baseUrl = Environment.GetEnvironmentVariable("BaseUrl") ?? configuration["BaseUrl"]; + } + + protected override async Task SendAsync(HttpRequestMessage request, + CancellationToken cancellationToken) + { + if (request.RequestUri.ToString().Contains("api/calculation")) + { + var requestResponse = await base.SendAsync(request, cancellationToken); + var contentString = await requestResponse.Content.ReadAsStringAsync(); + //Retrieve the CalculationId from the post request + var responseContent = JObject.Parse(contentString); + var calculationId = responseContent["Result"]["CalculationId"].ToString(); + + // Get the status of the calculation based on the CalculationId earlier created. + var calculationStateRequest = new HttpRequestMessage(new HttpMethod("GET"), baseUrl + "calculation/state/" + calculationId) { }; + HttpResponseMessage calculationStateResponse; + + Thread.Sleep(500); + //Checks of the calculation is completed. + //Results: Calulating,Storing,Stored,Not Stored, Not Found + while (true) + { + calculationStateResponse = await base.SendAsync(calculationStateRequest, cancellationToken); + + var calculationResponseContent = JObject.Parse(await calculationStateResponse.Content.ReadAsStringAsync()); + var calculationResultStatus = calculationResponseContent["Result"].ToString(); + + if (calculationResultStatus == "Stored") + { + break; + } + Thread.Sleep(500); + } + //If the calculation is stored.Send a post post request to retrieve the results and send back to the front-end. + var calculationResultRequest = new HttpRequestMessage(new HttpMethod("POST"), baseUrl + "calculation/result/" + calculationId) { + Content = new StringContent(JsonConvert.SerializeObject(""), Encoding.UTF8, "application/json") + }; + HttpResponseMessage calculationResultResponse = await base.SendAsync(calculationResultRequest, cancellationToken); + return calculationResultResponse; + } + + return await base.SendAsync(request, cancellationToken); + + } + } +} diff --git a/backend/Backend/Startup.cs b/backend/Backend/Startup.cs index 8f5588ac..4631be96 100644 --- a/backend/Backend/Startup.cs +++ b/backend/Backend/Startup.cs @@ -1,5 +1,6 @@ using AspNetCore.Proxy; using Backend.Security; +using Backend.Middleware; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; @@ -14,6 +15,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using System.Net.Http; +using System.Net; namespace Backend { @@ -39,13 +42,24 @@ public void ConfigureServices(IServiceCollection services) services.AddProxies(); //Used to get the authenticate/process the Http requests. services.AddTransient(); + + //Used to intercept and process frontend requests. + services.AddTransient(); + //Decompress the gZip results recieved from the api + HttpClientHandler handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }; + services.AddHttpClient("SimaProClient", client => { var baseUrl = Environment.GetEnvironmentVariable("BaseUrl") ?? Configuration["BaseUrl"]; client.BaseAddress = new Uri(baseUrl); //client.Timeout = TimeSpan.FromSeconds(30); }) + .ConfigurePrimaryHttpMessageHandler(() => { + return handler; + }) + .AddHttpMessageHandler() .AddHttpMessageHandler(); + } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/deliverables/2021-06-09 - AMOS SS2021 - Team 8 - Planning Document.pdf b/deliverables/2021-06-09 - AMOS SS2021 - Team 8 - Planning Document.pdf new file mode 100644 index 00000000..d2f91156 Binary files /dev/null and b/deliverables/2021-06-09 - AMOS SS2021 - Team 8 - Planning Document.pdf differ diff --git a/deliverables/2021-06-09 Kanban Board.png b/deliverables/2021-06-09 Kanban Board.png new file mode 100644 index 00000000..7470e794 Binary files /dev/null and b/deliverables/2021-06-09 Kanban Board.png differ diff --git a/deliverables/2021-06-16 - AMOS SS2021 - Team 8 - Planning Document.pdf b/deliverables/2021-06-16 - AMOS SS2021 - Team 8 - Planning Document.pdf new file mode 100644 index 00000000..986c569f Binary files /dev/null and b/deliverables/2021-06-16 - AMOS SS2021 - Team 8 - Planning Document.pdf differ diff --git a/deliverables/2021-06-16 Kanban Board.png b/deliverables/2021-06-16 Kanban Board.png new file mode 100644 index 00000000..01af35c4 Binary files /dev/null and b/deliverables/2021-06-16 Kanban Board.png differ diff --git a/frontend/.gitignore b/frontend/.gitignore index e9e922df..87f8a738 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -21,5 +21,6 @@ npm-debug.log* yarn-debug.log* yarn-error.log* +yarn.lock package-lock.json diff --git a/frontend/package.json b/frontend/package.json index e673983f..4b468468 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,9 +4,11 @@ "version": "0.1.0", "private": true, "dependencies": { + "@material-ui/core": "^4.11.4", "@react-pdf/renderer": "^2.0.12", "apexcharts": "^3.26.1", "axios": "^0.21.1", + "cors": "^2.8.5", "html2canvas": "^1.0.0-rc.7", "jspdf": "^2.3.1", "jspdf-autotable": "^3.5.14", diff --git a/frontend/src/assets/dummyImages/Industrialapplications.jpg b/frontend/src/assets/dummyImages/Industrialapplications.jpg new file mode 100644 index 00000000..f266adc7 Binary files /dev/null and b/frontend/src/assets/dummyImages/Industrialapplications.jpg differ diff --git a/frontend/src/assets/dummyImages/powerGeneration.jpg b/frontend/src/assets/dummyImages/powerGeneration.jpg new file mode 100644 index 00000000..7b37f935 Binary files /dev/null and b/frontend/src/assets/dummyImages/powerGeneration.jpg differ diff --git a/frontend/src/assets/dummyImages/powerTransmission.jpg b/frontend/src/assets/dummyImages/powerTransmission.jpg new file mode 100644 index 00000000..422afdd8 Binary files /dev/null and b/frontend/src/assets/dummyImages/powerTransmission.jpg differ diff --git a/frontend/src/assets/icons/checkbox-off.js b/frontend/src/assets/icons/checkbox-off.js deleted file mode 100644 index 396af4ea..00000000 --- a/frontend/src/assets/icons/checkbox-off.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/checkbox-on.js b/frontend/src/assets/icons/checkbox-on.js deleted file mode 100644 index c5028419..00000000 --- a/frontend/src/assets/icons/checkbox-on.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -); diff --git a/frontend/src/assets/icons/icon-agents.js b/frontend/src/assets/icons/icon-agents.js deleted file mode 100644 index 98a63233..00000000 --- a/frontend/src/assets/icons/icon-agents.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-arrow-down.js b/frontend/src/assets/icons/icon-arrow-down.js deleted file mode 100644 index a942d9b8..00000000 --- a/frontend/src/assets/icons/icon-arrow-down.js +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -); - - diff --git a/frontend/src/assets/icons/icon-arrow-up.js b/frontend/src/assets/icons/icon-arrow-up.js deleted file mode 100644 index d6ad4fbd..00000000 --- a/frontend/src/assets/icons/icon-arrow-up.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -); diff --git a/frontend/src/assets/icons/icon-arrow.js b/frontend/src/assets/icons/icon-arrow.js deleted file mode 100644 index c3b8cb6f..00000000 --- a/frontend/src/assets/icons/icon-arrow.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -) \ No newline at end of file diff --git a/frontend/src/assets/icons/icon-articles.js b/frontend/src/assets/icons/icon-articles.js deleted file mode 100644 index 37a46612..00000000 --- a/frontend/src/assets/icons/icon-articles.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-bell-new.js b/frontend/src/assets/icons/icon-bell-new.js deleted file mode 100644 index faf6258d..00000000 --- a/frontend/src/assets/icons/icon-bell-new.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -); diff --git a/frontend/src/assets/icons/icon-browse.js b/frontend/src/assets/icons/icon-browse.js deleted file mode 100644 index 88f0e4f9..00000000 --- a/frontend/src/assets/icons/icon-browse.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-building.js b/frontend/src/assets/icons/icon-building.js deleted file mode 100644 index 4d1e7c6e..00000000 --- a/frontend/src/assets/icons/icon-building.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -) \ No newline at end of file diff --git a/frontend/src/assets/icons/icon-burger.js b/frontend/src/assets/icons/icon-burger.js deleted file mode 100644 index 4636caf8..00000000 --- a/frontend/src/assets/icons/icon-burger.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-circle.js b/frontend/src/assets/icons/icon-circle.js deleted file mode 100644 index ffcb6b20..00000000 --- a/frontend/src/assets/icons/icon-circle.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -) \ No newline at end of file diff --git a/frontend/src/assets/icons/icon-contacts.js b/frontend/src/assets/icons/icon-contacts.js deleted file mode 100644 index a124e987..00000000 --- a/frontend/src/assets/icons/icon-contacts.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-heart.js b/frontend/src/assets/icons/icon-heart.js deleted file mode 100644 index f564d586..00000000 --- a/frontend/src/assets/icons/icon-heart.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default () => ( - - - -) \ No newline at end of file diff --git a/frontend/src/assets/icons/icon-home.js b/frontend/src/assets/icons/icon-home.js deleted file mode 100644 index d75b40ac..00000000 --- a/frontend/src/assets/icons/icon-home.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); - diff --git a/frontend/src/assets/icons/icon-ideas.js b/frontend/src/assets/icons/icon-ideas.js deleted file mode 100644 index 72beb334..00000000 --- a/frontend/src/assets/icons/icon-ideas.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - {/* /> */} - - - - - - - -); diff --git a/frontend/src/assets/icons/icon-inbox.js b/frontend/src/assets/icons/icon-inbox.js deleted file mode 100644 index 39d70532..00000000 --- a/frontend/src/assets/icons/icon-inbox.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-login.js b/frontend/src/assets/icons/icon-login.js deleted file mode 100644 index 823c2c44..00000000 --- a/frontend/src/assets/icons/icon-login.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -) \ No newline at end of file diff --git a/frontend/src/assets/icons/icon-logo.js b/frontend/src/assets/icons/icon-logo.js deleted file mode 100644 index 46c87a47..00000000 --- a/frontend/src/assets/icons/icon-logo.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default () => ( - - - - - - - - - - -); diff --git a/frontend/src/assets/icons/icon-logout.js b/frontend/src/assets/icons/icon-logout.js deleted file mode 100644 index 394cdb6e..00000000 --- a/frontend/src/assets/icons/icon-logout.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -); diff --git a/frontend/src/assets/icons/icon-overview.js b/frontend/src/assets/icons/icon-overview.js deleted file mode 100644 index f606da1f..00000000 --- a/frontend/src/assets/icons/icon-overview.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - - - - - - - -); \ No newline at end of file diff --git a/frontend/src/assets/icons/icon-plus.js b/frontend/src/assets/icons/icon-plus.js deleted file mode 100644 index 505f07ee..00000000 --- a/frontend/src/assets/icons/icon-plus.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default () => ( - - - - -) \ No newline at end of file diff --git a/frontend/src/assets/icons/icon-power.js b/frontend/src/assets/icons/icon-power.js deleted file mode 100644 index 105d6d94..00000000 --- a/frontend/src/assets/icons/icon-power.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-search.js b/frontend/src/assets/icons/icon-search.js deleted file mode 100644 index 3270dfc8..00000000 --- a/frontend/src/assets/icons/icon-search.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -); diff --git a/frontend/src/assets/icons/icon-settings.js b/frontend/src/assets/icons/icon-settings.js deleted file mode 100644 index 3e41cc3c..00000000 --- a/frontend/src/assets/icons/icon-settings.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-subscription.js b/frontend/src/assets/icons/icon-subscription.js deleted file mode 100644 index 7e8994fe..00000000 --- a/frontend/src/assets/icons/icon-subscription.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - - - - - - - -); diff --git a/frontend/src/assets/icons/icon-tickets.js b/frontend/src/assets/icons/icon-tickets.js deleted file mode 100644 index 0ee32826..00000000 --- a/frontend/src/assets/icons/icon-tickets.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - -); diff --git a/frontend/src/assets/icons/icon-transmission.js b/frontend/src/assets/icons/icon-transmission.js deleted file mode 100644 index 00757f07..00000000 --- a/frontend/src/assets/icons/icon-transmission.js +++ /dev/null @@ -1,15 +0,0 @@ - -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -) \ No newline at end of file diff --git a/frontend/src/assets/icons/icon-user.js b/frontend/src/assets/icons/icon-user.js deleted file mode 100644 index ba2319a6..00000000 --- a/frontend/src/assets/icons/icon-user.js +++ /dev/null @@ -1,11 +0,0 @@ - -import React from 'react'; - -/* eslint import/no-anonymous-default-export: [2, {"allowArrowFunction": true}] */ -export default (props) => ( - - - - -) \ No newline at end of file diff --git a/frontend/src/assets/icons/index.js b/frontend/src/assets/icons/index.js deleted file mode 100644 index 01c30772..00000000 --- a/frontend/src/assets/icons/index.js +++ /dev/null @@ -1,61 +0,0 @@ -import IconCheckboxOff from './checkbox-off'; -import IconCheckboxOn from './checkbox-on'; -import IconAgents from './icon-agents'; -import IconArrowUp from './icon-arrow-up'; -import IconArticles from './icon-articles'; -import IconBell from './icon-bell-new'; -import IconBurger from './icon-burger'; -import IconContacts from './icon-contacts'; -import IconIdeas from './icon-ideas'; -import IconLogo from './icon-logo'; -import IconLogout from './icon-logout'; -import IconOverview from './icon-overview'; -import IconSearch from './icon-search'; -import IconSettings from './icon-settings'; -import IconSubscription from './icon-subscription'; -import IconTickets from './icon-tickets'; -import IconInbox from './icon-inbox'; -import IconHome from './icon-home'; -import IconLogin from './icon-login'; -import IconPower from './icon-power'; -import IconTransmission from './icon-transmission'; -import IconArrow from './icon-arrow'; -import IconBrowse from './icon-browse'; -import IconBuilding from './icon-building'; -import IconArrowDown from './icon-arrow-down'; -import IconCircle from './icon-circle' -import IconUser from './icon-user' -import IconHeart from './icon-heart' -import IconPlus from './icon-plus' - -export { - IconCheckboxOff, - IconCheckboxOn, - IconAgents, - IconArrowUp, - IconArticles, - IconBell, - IconBurger, - IconContacts, - IconIdeas, - IconLogo, - IconLogout, - IconOverview, - IconSearch, - IconSettings, - IconSubscription, - IconTickets, - IconInbox, - IconHome, - IconLogin, - IconPower, - IconTransmission, - IconArrow, - IconBrowse, - IconBuilding, - IconArrowDown, - IconCircle, - IconUser, - IconHeart, - IconPlus -}; diff --git a/frontend/src/components/cards/MiniCardComponent.js b/frontend/src/components/cards/MiniCardComponent.js index b6f73329..a296b8cb 100644 --- a/frontend/src/components/cards/MiniCardComponent.js +++ b/frontend/src/components/cards/MiniCardComponent.js @@ -1,55 +1,25 @@ import React from 'react'; -import { Column } from 'simple-flexbox'; -import { createUseStyles, useTheme } from 'react-jss'; -const useStyles = createUseStyles((theme) => ({ - container: { - backgroundColor: '#FFFFFF', - border: `3px solid ${theme.color.lightGrayishBlue2}`, - borderRadius: 4, - cursor: 'pointer', - maxWidth: 350, - minWidth: 210, // resizing the card min width - maxHeight: 150, - // marginTop:50, - // padding: '8px 16px 8px 16px', - '&:hover': { - borderColor: theme.uniformStyle.color.tableHeaderColor, - '&:nth-child(n) > span': { - color: theme.color.lightBlue - } - } - }, - title: { - ...theme.typography.cardTitle, - color: theme.color.grayishBlue2, - marginBottom: 12, - minWidth: 205, - textAlign: 'center' - }, - value: { - color: theme.color.veryDarkGrayishBlue, - fontWeight: 'inherit', - fontSize: 14, - letterSpacing: '1px', - lineHeight: '50px', - textAlign: 'center' - } -})); +import { Col, Container, Row } from 'react-grid-system'; -// create cards for selection of the products - -function MiniCardComponent({ className = '', title, value, path }) { - const theme = useTheme(); - const classes = useStyles({ theme }); - const composedClassName = [classes.container, className].join(' '); +/** + * creates cards for selection of the products in the Product Grid + * + * @param {*} props: The classname and the path that should be used. + * @returns + */ +function MiniCardComponent({ title, path }) { return ( - - {/* Resize the image on the cards (product images) */} -
- {/* define the image path */} - -
-
+ + + {/* Resize the image on the cards (product images) */} + + {/* define the image path */} + + + + + + ); } diff --git a/frontend/src/components/cards/miniCard.css b/frontend/src/components/cards/miniCard.css new file mode 100644 index 00000000..62a4a593 --- /dev/null +++ b/frontend/src/components/cards/miniCard.css @@ -0,0 +1,19 @@ +.MiniCardImageContainer { + background-color: #ffffff; + border: 3px solid lightslategray; + border-radius: 8px; + cursor: pointer; + max-width: 350px; + min-width: 210px; + max-height: 150px; +} + +.MiniCardImageContainer:hover { + border-color: var(--global--active--highlighting-color); +} + +.MiniCardImageContainer img { + margin: auto; + padding: 4px; + max-height: 130px; +} diff --git a/frontend/src/components/collapsible/CollapsibleContent.js b/frontend/src/components/collapsible/CollapsibleContent.js index 6faae6b7..8f465cee 100644 --- a/frontend/src/components/collapsible/CollapsibleContent.js +++ b/frontend/src/components/collapsible/CollapsibleContent.js @@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { useScrollHeight } from 'react-collapsible-content'; + const STATUS = { COLLAPSED: 'COLLAPSED', PRE_EXPANDED: 'PRE_EXPANDED', @@ -9,6 +10,9 @@ const STATUS = { PRE_COLLAPSED: 'PRE_COLLAPSED' }; +/** + * This component returns the collapsible items on the sidebar component. + */ function CollapsibleContent({ children, expanded, @@ -25,6 +29,9 @@ function CollapsibleContent({ onTransitionStart, onTransitionEnd }); + + /* This styling needs to be done in JS code.*/ + let transitionStyles; switch (status) { case STATUS.EXPANDED: @@ -42,7 +49,6 @@ function CollapsibleContent({ default: transitionStyles = { maxHeight: scrollHeight, transitionDuration: '.001s' }; } - useEffect(() => { if (expanded) { if (status === STATUS.COLLAPSED) { diff --git a/frontend/src/components/dashboard/DashboardComponent.js b/frontend/src/components/dashboard/DashboardComponent.js index b50d8d11..02085751 100644 --- a/frontend/src/components/dashboard/DashboardComponent.js +++ b/frontend/src/components/dashboard/DashboardComponent.js @@ -4,7 +4,6 @@ import { createUseStyles } from 'react-jss'; import MiniCardComponent from 'components/cards/MiniCardComponent'; import TodayTrendsComponent from './TodayTrendsComponent'; import UnresolvedTicketsComponent from './UnresolvedTicketsComponent'; -import TasksComponent from './TasksComponent'; const useStyles = createUseStyles({ cardsContainer: { @@ -102,7 +101,7 @@ function DashboardComponent() { breakpoints={{ 1024: 'column' }} > - + {/* */} ); diff --git a/frontend/src/components/dashboard/TasksComponent.js b/frontend/src/components/dashboard/TasksComponent.js deleted file mode 100644 index 4dfd06b9..00000000 --- a/frontend/src/components/dashboard/TasksComponent.js +++ /dev/null @@ -1,167 +0,0 @@ -import React, { useState } from 'react'; -import { Row } from 'simple-flexbox'; -import { createUseStyles, useTheme } from 'react-jss'; -import { IconCheckboxOn, IconCheckboxOff } from 'assets/icons'; -import CardComponent from 'components/cards/CardComponent'; - -const useStyles = createUseStyles((theme) => ({ - addButton: { - backgroundColor: theme.color.lightGrayishBlue, - color: theme.color.grayishBlue2, - fontSize: '20px !important', - padding: '7px !important' - }, - itemTitle: { - ...theme.typography.itemTitle, - color: theme.color.veryDarkGrayishBlue - }, - itemValue: { - color: theme.color.grayishBlue2 - }, - greyTitle: { - color: theme.color.grayishBlue3 - }, - tagStyles: { - borderRadius: 5, - cursor: 'pointer', - fontWeight: 'bold', - fontSize: 11, - letterSpacing: '0.5px', - lineHeight: '14px', - padding: '5px 12px 5px 12px' - }, - checkboxWrapper: { - cursor: 'pointer', - marginRight: 16 - } -})); - -const TAGS = { - URGENT: { text: 'URGENT', backgroundColor: '#FEC400', color: '#FFFFFF' }, - NEW: { text: 'NEW', backgroundColor: '#29CC97', color: '#FFFFFF' }, - DEFAULT: { text: 'DEFAULT', backgroundColor: '#F0F1F7', color: '#9FA2B4' } -}; - -function TasksComponent(props) { - const theme = useTheme(); - const classes = useStyles({ theme }); - const [items, setItems] = useState([ - { title: 'Finish ticket update', checked: false, tag: TAGS.URGENT }, - { - title: 'Create new ticket example', - checked: false, - tag: TAGS.NEW - }, - { title: 'Update ticket report', checked: true, tag: TAGS.DEFAULT } - ]); - - function onCheckboxClick(index) { - setItems((prev) => { - const newItems = [...prev]; - newItems[index].checked = newItems[index].checked ? false : true; - return newItems; - }); - } - function getNextTag(current = 'URGENT') { - const tagLabels = ['URGENT', 'NEW', 'DEFAULT']; - const tagIndex = (tagLabels.indexOf(current) + 1) % 3; - return TAGS[tagLabels[tagIndex]]; - } - - function onTagClick(index) { - setItems((prev) => { - const newItems = [...prev]; - newItems[index].tag = getNextTag(newItems[index].tag.text); - return newItems; - }); - } - - function onAddButtonClick() { - setItems((prev) => { - const newItems = [...prev]; - newItems.push({ - title: `Task ${newItems.length + 1}`, - checked: false, - tag: getNextTag() - }); - return newItems; - }); - } - - function renderAddButton() { - return ( - - + - - ); - } - - return ( - - - Create new task - - {renderAddButton()} - , - ...items.map((item, index) => ( - - )) - ]} - /> - ); -} - -function TaskComponent({ classes, index, item = {}, onCheckboxClick, onTagClick }) { - const { tag = {} } = item; - return ( - - -
onCheckboxClick(index)}> - {item.checked ? : } -
- {item.title} -
- -
- ); -} - -function TagComponent({ backgroundColor, classes, color, index, onClick, text }) { - return ( - onClick(index)} - > - {text} - - ); -} - -export default TasksComponent; diff --git a/frontend/src/components/details/CanvasComponent.jsx b/frontend/src/components/details/CanvasComponent.jsx deleted file mode 100644 index 3d04f2c5..00000000 --- a/frontend/src/components/details/CanvasComponent.jsx +++ /dev/null @@ -1,75 +0,0 @@ -/** -in this main component come all the canvas page components -such as diagrams and tables - -@author Parham Gandomkar, Irem Toroslu -*/ - -import React, { Component } from 'react'; -import PieChart from './PieChartComponent'; -import ColumnChart from './ColumnChartComponent'; -import Table from './TableComponent'; -import theme from 'resources/theme'; - -class CanvasComponent extends Component { - render() { - /* - if the loadComparePage state from its parrent (the detail Component) - is set to true, here the canvas page should be divided into two canvases - */ - return ( -
-
-
-

- {' '} - Results of the impact assessment{' '} -

- -
-
-

- {' '} - Material Composition{' '} -

- -
-
-
-
-

- {' '} - Impact categories{' '} -

- - - - - ); - } -} - -export default CanvasComponent; diff --git a/frontend/src/components/details/ColumnChartComponent.jsx b/frontend/src/components/details/ColumnChartComponent.jsx index f97587a6..6cb1c186 100644 --- a/frontend/src/components/details/ColumnChartComponent.jsx +++ b/frontend/src/components/details/ColumnChartComponent.jsx @@ -1,7 +1,6 @@ import React from 'react'; import ReactApexChart from 'react-apexcharts'; -import { getResultsImpactAssessment } from 'interface/projectInterface'; -import theme from 'resources/theme'; +import { getImpactAssessmentData, getLifeCycleStages } from 'interface/projectInterface'; /** * Column Chart @@ -13,7 +12,7 @@ const ColumnChartComponent = () => { { name: 'Global warming in kg CO2 equivalents', // TODO: this data needs to be recieved from backend - data: getResultsImpactAssessment() + data: getImpactAssessmentData() } ]; @@ -25,14 +24,27 @@ const ColumnChartComponent = () => { plotOptions: { bar: { - columnWidth: '60%' + columnWidth: '70%', + BorderRadius: 10, + dataLabels: { + position: 'top' // top, center, bottom + } } }, fill: { - colors: [theme.uniformStyle.color.barChartColor] + colors: ['#21cc82'] //['#2cb5de'] }, + dataLabels: { - enabled: false + enabled: true, + formatter: function (val) { + return val + '%'; + }, + offsetY: -20, + style: { + fontSize: '12px', + colors: ['#21cc82'] + } }, yaxis: { title: { @@ -43,39 +55,36 @@ const ColumnChartComponent = () => { labels: { formatter: function (y) { return y.toFixed(0) + '%'; - }, - style: { - fontSize: theme.typography.chartItemstitle.fontSize, - fontWeight: theme.typography.chartItemstitle.fontWeight } } }, xaxis: { - categories: [ - 'Materials', - 'Manufacturing and Transport', - 'Operation 30a (75% load)', - 'End of Life' - ], + categories: getLifeCycleStages(), labels: { rotate: -90, style: { - fontSize: theme.typography.chartItemstitle.fontSize, - fontWeight: theme.typography.chartItemstitle.fontWeight + fontSize: 10 } - } + }, + responsive: [ + { + breakpoint: 300, + options: { + chart: { + width: 500 + }, + legend: { + position: 'bottom' + } + } + } + ] } }; return ( -
- +
+
); }; diff --git a/frontend/src/components/details/CompareCanvas.jsx b/frontend/src/components/details/CompareCanvas.jsx deleted file mode 100644 index 4b54a15b..00000000 --- a/frontend/src/components/details/CompareCanvas.jsx +++ /dev/null @@ -1,157 +0,0 @@ -import React from 'react'; -import PieChart from './PieChartComponent'; -import ColumnChart from './ColumnChartComponent'; -import TableComponent from './TableComponent'; -import theme from 'resources/theme'; - -/** - * This component displays the difference/comparison between the dashboards of two different type of variables of the same model - * will be compared when clicking on the "comparison" button. - * - * @returns the dasboard comparison - * @author Parham Gandomkar, Irem Toroslu - * - */ - -const CompareCanvas = () => { - return ( -
-
-
-

- Baseline Scenario -

-
-

- {' '} - Material Composition{' '} -

- -
- -
-
-

Baseline Scenario -

-

- {' '} - Material Composition{' '} -

- -
-
-
-
-

- {' '} - Results of the impact assessment{' '} -

- -
-
-

- {' '} - Results of the impact assessment{' '} -

- -
-
- -
-
-

- {' '} - Impact categories{' '} -

- -
-
-
-
-

- {' '} - Impact categories{' '} -

-
- -
-
-
-
- - ); -}; - -export default CompareCanvas; diff --git a/frontend/src/components/details/CompareVariablesComponent.jsx b/frontend/src/components/details/CompareVariablesComponent.jsx deleted file mode 100644 index d8c90d6c..00000000 --- a/frontend/src/components/details/CompareVariablesComponent.jsx +++ /dev/null @@ -1,123 +0,0 @@ -import React from 'react'; -import theme from 'resources/theme'; - -/** -a drop down component for selecting variables -if we need to compare two variables - - @author Parham Gandomkar -*/ -const CompareVariablesComponent = (props) => { - const { state } = props; - return ( -
-
-

Select variables to compare:

-
-
-
- -
- {state.variables.map((item) => ( - - ))} -
-
-
-
-
- -
- {state.variables.map((item) => ( - - ))} -
-
-
-
- -
- -
- ); -}; - -export default CompareVariablesComponent; diff --git a/frontend/src/components/details/DetailsComponent.js b/frontend/src/components/details/DetailsComponent.js index 4c8b8c13..ac8b5af7 100644 --- a/frontend/src/components/details/DetailsComponent.js +++ b/frontend/src/components/details/DetailsComponent.js @@ -1,10 +1,10 @@ import React, { Component } from 'react'; -import Canvas from './CanvasComponent'; -import SelectVariable from './SelectVariableComponent'; -import DividerPanel from './PanelComponent'; -import theme from 'resources/theme'; +import ScenarioComponent from './ScenarioComponent'; +import { jsPDF } from 'jspdf'; +import html2canvas from 'html2canvas'; import { Col, Container, Row } from 'react-grid-system'; import './navbar.css'; +// import { postCalculationRequest } from 'interface/BackendConnect'; /** * the main component for detail page which includes @@ -15,98 +15,101 @@ import './navbar.css'; */ class DetailsComponent extends Component { state = { - compareCanvas: false + loadComparePage: false }; render() { - let styleSubtitle = { - fontSize: theme.typography.subtitle.fontSize, - fontWeight: theme.typography.subtitle.fontWeight, - lineHeight: theme.typography.subtitle.lineHeight, - letterSpacing: theme.typography.subtitle.letterSpacing, - marginLeft: 15 - }; /* the default canvas has to be divided into two canvases an extra drop down button for second variable should be rendered the compare button should be disabled */ let handleCompareButton = () => { - const compareCanvas = true; + const loadComparePage = true; /* now all components such as canvas component should be notified by setting the compareCanvas state to true */ - this.setState({ compareCanvas }); + this.setState({ loadComparePage }); + }; + + let handleExportPdfButton = () => { + // geting the element that should be exported + var div = document.getElementById('capture'); + + // converting html to an image and then exporting it by pdf + html2canvas(div).then((canvas) => { + var imgData = canvas.toDataURL('image/jpeg', 1); + // pdf configuration + var pdf = new jsPDF('p', 'mm', 'a4'); + var pageWidth = pdf.internal.pageSize.getWidth(); + var pageHeight = pdf.internal.pageSize.getHeight(); + var imageWidth = canvas.width; + var imageHeight = canvas.height; + + var ratio = + imageWidth / imageHeight >= pageWidth / pageHeight + ? pageWidth / imageWidth + : pageHeight / imageHeight; + pdf.addImage(imgData, 'JPEG', 0, 0, imageWidth * ratio, imageHeight * ratio); + pdf.save('invoice.pdf'); + }); }; + const scenarioNames = { baseline: 'Baseline Scenario', - modified: 'modified Scenario' + modified: 'Modified Scenario' }; const { selectedProduct } = this.props; - if (!this.state.compareCanvas) { - return ( - - -

The chosen Model is {selectedProduct.modelName}

-
- -
- -
+ // The styling of the Container, Row and Col can not be moved to css, as the css has a lower priority than the react-grid-system default. + const noPaddingStyle = { + padding: 0, + margin: 0 + }; + + // postCalculationRequest(selectedProduct.productID); + + if (!this.state.loadComparePage) { + return ( + + +
+ + + + ); } else { return ( - - - - + + + -

- The chosen Model is {selectedProduct.modelName} -

-
- -
- - -
- + -

- The chosen Model is {selectedProduct.modelName} -

-
- -
- - diff --git a/frontend/src/components/details/MobileTableComponent.jsx b/frontend/src/components/details/MobileTableComponent.jsx new file mode 100644 index 00000000..9d85727b --- /dev/null +++ b/frontend/src/components/details/MobileTableComponent.jsx @@ -0,0 +1,95 @@ +import React, { Component } from 'react'; +import { Container } from 'react-grid-system'; +import { + getImpactCategoriesTableHeaders, + getImpactCategoriesTableData +} from 'interface/projectInterface'; + +/** + * Mobile version of the TableComponent. Restructures the Table to be displayable on a mobile screen. + * Switches Rows and Headers and splits the table in two parts. + */ +class MobileTableComponent extends Component { + state = { + headers: getImpactCategoriesTableHeaders(this.props.modelId), + rows: getImpactCategoriesTableData(this.props.modelId) + }; + render() { + const idKey = this.props.key; + return ( + + {/* dynamic display of product and model */} +
{this.props.productName}
+
+ {/* Don't display model name if model name == product name or undefined */} + {this.props.modelName === this.props.productName || + this.props.modelName === undefined + ? '' + : this.props.modelName} +
+ +
+ {/* style needs to be defined in js */} + + {this.state.headers.map((header, index) => ( + + + + + + + ))} + +
+ {header.value} + + {Object.values(this.state.rows[3])[index + 1]} + + {Object.values(this.state.rows[4])[index + 1]} + + {Object.values(this.state.rows[5])[index + 1]} +
+ +
+ + + {/* style needs to be defined in js */} + + {this.state.headers.map((header, 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]} +
+ + ); + } +} + +export default MobileTableComponent; diff --git a/frontend/src/components/details/NavbarComponent.js b/frontend/src/components/details/NavbarComponent.js new file mode 100644 index 00000000..50f0a6c3 --- /dev/null +++ b/frontend/src/components/details/NavbarComponent.js @@ -0,0 +1,51 @@ +import React from 'react'; +import slugs from 'resources/slugs'; +import { Link } 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 + */ + +const NavbarComponent = (props) => { + if (!props.loadComparePage) { + return ( +
+ + +