Connected two graphs to backend, WIP

This commit is contained in:
2023-10-19 23:02:09 +03:00
parent 6ccf92ecce
commit 6ca8b861e4
8 changed files with 236 additions and 70 deletions

View File

@@ -22,6 +22,11 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>3.1.4</version> <version>3.1.4</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>

View File

@@ -0,0 +1,14 @@
package com.faf223.expensetrackerfaf.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
}

View File

@@ -0,0 +1,40 @@
package com.faf223.expensetrackerfaf.config;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:5173");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, X-Auth-Token");
response.setHeader("Access-Control-Allow-Credentials", "true");
if (!"OPTIONS".equalsIgnoreCase(request.getMethod())) {
chain.doFilter(req, res);
}
}
@Override
public void init(FilterConfig config) {
}
}

View File

@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@CrossOrigin
@RestController @RestController
@RequestMapping("/incomes") @RequestMapping("/incomes")
@RequiredArgsConstructor @RequiredArgsConstructor
@@ -54,6 +55,7 @@ public class IncomeController {
} }
} }
@CrossOrigin
@GetMapping("/{userUuid}") @GetMapping("/{userUuid}")
public ResponseEntity<List<IncomeDTO>> getIncomesByUser(@PathVariable String userUuid) { public ResponseEntity<List<IncomeDTO>> getIncomesByUser(@PathVariable String userUuid) {
List<IncomeDTO> incomes = incomeService.getIncomesByUserId(userUuid).stream().map(incomeMapper::toDto).collect(Collectors.toList()); List<IncomeDTO> incomes = incomeService.getIncomesByUserId(userUuid).stream().map(incomeMapper::toDto).collect(Collectors.toList());

View File

@@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@fortawesome/free-brands-svg-icons": "^6.4.2", "@fortawesome/free-brands-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2",
"axios": "^1.5.1",
"chart.js": "^4.4.0", "chart.js": "^4.4.0",
"email-validator": "^2.0.4", "email-validator": "^2.0.4",
"svelte-fa": "^3.0.4" "svelte-fa": "^3.0.4"
@@ -810,6 +811,21 @@
"dequal": "^2.0.3" "dequal": "^2.0.3"
} }
}, },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz",
"integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axobject-query": { "node_modules/axobject-query": {
"version": "3.2.1", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
@@ -902,6 +918,17 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true "dev": true
}, },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -988,6 +1015,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/dequal": { "node_modules/dequal": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -1349,6 +1384,38 @@
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
"dev": true "dev": true
}, },
"node_modules/follow-redirects": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -1693,6 +1760,25 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -2011,6 +2097,11 @@
"svelte": "^3.2.0 || ^4.0.0-next.0" "svelte": "^3.2.0 || ^4.0.0-next.0"
} }
}, },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/punycode": { "node_modules/punycode": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",

View File

@@ -26,6 +26,7 @@
"dependencies": { "dependencies": {
"@fortawesome/free-brands-svg-icons": "^6.4.2", "@fortawesome/free-brands-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2",
"axios": "^1.5.1",
"chart.js": "^4.4.0", "chart.js": "^4.4.0",
"email-validator": "^2.0.4", "email-validator": "^2.0.4",
"svelte-fa": "^3.0.4" "svelte-fa": "^3.0.4"

View File

@@ -1,30 +1,44 @@
<script> <script>
import Chart from 'chart.js/auto'; import Chart from 'chart.js/auto';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import axios from 'axios';
let chartValues = [20, 10, 5, 2, 20, 30, 45];
let chartLabels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
let ctx; let ctx;
let chartCanvas; let chartCanvas;
onMount(async () => { onMount(async () => {
ctx = chartCanvas.getContext('2d'); const config = {
headers: {
'Authorization': `Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYW4uYmFsYW5AZ21haWwuY29tIiwiaWF0IjoxNjk3NzQ0MjY3LCJleHAiOjE2OTc4MzA2Njd9.hzbEDDuOVCY_EQAA8xGlJskQ2FQjw8o0CtFKB1dKYOU`
}
};
try {
const response = await axios.get('http://localhost:8081/incomes/00112233-4455-6677-8899-aabbccddeeaa', config);
const incomeData = response.data; // Assuming the response is an array of income data
const chartLabels = incomeData.map(item => item.category.categoryName);
const chartValues = incomeData.map(item => item.amount);
ctx = chartCanvas.getContext('2d');
new Chart(ctx, { new Chart(ctx, {
type: 'line', type: 'bar', // Set chart type to 'bar' for a bar graph
data: { data: {
labels: chartLabels, labels: chartLabels,
datasets: [{ datasets: [{
label: 'Revenue', label: 'Revenue',
backgroundColor: 'rgb(255, 99, 132)', backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)', data: chartValues // Changed from 'data' to 'chartValues'
data: chartValues }]
}]
}, },
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false maintainAspectRatio: false
} }
}); });
} catch (error) {
console.error('Error:', error);
}
}); });
</script> </script>
@@ -34,15 +48,15 @@
<style> <style>
#chart { #chart {
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
transition: all 0.3s cubic-bezier(.25,.8,.25,1); transition: all 0.3s cubic-bezier(.25,.8,.25,1);
flex: 1; flex: 1;
border-radius: 10px; border-radius: 10px;
margin:10px; margin: 10px;
background-color: #ffdde2; background-color: #ffdde2;
} }
#chart:hover { #chart:hover {
box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22); box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
} }
</style> </style>

View File

@@ -1,45 +1,44 @@
<script> <script>
import chartjs from 'chart.js/auto'; import chartjs from 'chart.js/auto';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import axios from 'axios';
var randomScalingFactor = function() {
return Math.round(Math.random() * 100);
};
var config = {
type: 'pie',
data: {
datasets: [{
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
],
label: 'Dataset 1'
}],
labels: [
"Red",
"Orange",
"Yellow",
"Green",
"Blue"
]
},
options: {
responsive: true,
maintainAspectRatio: false
}
};
let ctx; let ctx;
let chartCanvas; let chartCanvas;
onMount(async (promise) => { onMount(async () => {
ctx = chartCanvas.getContext('2d'); const config = {
var chart = new chartjs(ctx, config); headers: {
'Authorization': `Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYW4uYmFsYW5AZ21haWwuY29tIiwiaWF0IjoxNjk3NzQ0MjY3LCJleHAiOjE2OTc4MzA2Njd9.hzbEDDuOVCY_EQAA8xGlJskQ2FQjw8o0CtFKB1dKYOU`
}
};
try {
const response = await axios.get('http://localhost:8081/incomes/00112233-4455-6677-8899-aabbccddeeaa', config);
const incomeData = response.data; // Assuming the response is an array of income data
// Extract income categories and their values
const chartLabels = incomeData.map(item => item.category.categoryName);
const chartValues = incomeData.map(item => item.amount);
ctx = chartCanvas.getContext('2d');
new chartjs(ctx, {
type: 'pie', // Set chart type to 'pie' for a pie chart
data: {
labels: chartLabels,
datasets: [{
data: chartValues,
backgroundColor: ['red', 'orange', 'yellow', 'green', 'blue'], // Customize colors as needed
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
} catch (error) {
console.error('Error:', error);
}
}); });
</script> </script>
@@ -49,15 +48,15 @@
<style> <style>
#chart { #chart {
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
transition: all 0.3s cubic-bezier(.25,.8,.25,1); transition: all 0.3s cubic-bezier(.25,.8,.25,1);
flex: 1; flex: 1;
border-radius: 10px; border-radius: 10px;
margin:10px; margin: 10px;
background-color: #ffdde2; background-color: #ffdde2;
} }
#chart:hover { #chart:hover {
box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22); box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
} }
</style> </style>