diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/Application.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/Application.java
index 9f905e4..49b7afb 100644
--- a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/Application.java
+++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/Application.java
@@ -3,9 +3,6 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Bean;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
public class Application {
diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberService.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberService.java
index 62b274e..23a5bd7 100644
--- a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberService.java
+++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberService.java
@@ -2,6 +2,7 @@
import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.IngestedMemberDto;
import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.MemberDto;
+import be.informatievlaanderen.vsds.demonstrator.member.rest.dtos.LineChartDto;
import org.locationtech.jts.geom.Geometry;
import java.time.LocalDateTime;
@@ -15,4 +16,6 @@ public interface MemberService {
MemberDto getMemberById(String memberId);
long getNumberOfMembers();
+
+ LineChartDto getLineChartDto();
}
diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberServiceImpl.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberServiceImpl.java
index 7b74e07..2c9a382 100644
--- a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberServiceImpl.java
+++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberServiceImpl.java
@@ -5,8 +5,10 @@
import be.informatievlaanderen.vsds.demonstrator.member.application.exceptions.ResourceNotFoundException;
import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.IngestedMemberDto;
import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.MemberDto;
+import be.informatievlaanderen.vsds.demonstrator.member.domain.member.entities.LineChart;
import be.informatievlaanderen.vsds.demonstrator.member.domain.member.entities.Member;
import be.informatievlaanderen.vsds.demonstrator.member.domain.member.repositories.MemberRepository;
+import be.informatievlaanderen.vsds.demonstrator.member.rest.dtos.LineChartDto;
import be.informatievlaanderen.vsds.demonstrator.member.rest.websocket.MessageController;
import org.locationtech.jts.geom.Geometry;
import org.opengis.referencing.operation.TransformException;
@@ -19,6 +21,7 @@
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
+import java.util.Map;
@Service
public class MemberServiceImpl implements MemberService {
@@ -68,4 +71,13 @@ public MemberDto getMemberById(String memberId) {
public long getNumberOfMembers() {
return repository.getNumberOfMembers();
}
+
+ @Override
+ public LineChartDto getLineChartDto() {
+ long numberOfMembers = getNumberOfMembers();
+ LocalDateTime startDate = LocalDateTime.now().minusDays(7);
+ List> values;
+ private final LocalDateTime startDate;
+
+ public LineChart(LocalDateTime startDate, long numberOfMembersOutsideFrame, List
> getValues() {
+ if (values.isEmpty())
+ calculatePointElements();
+ return values;
+ }
+}
diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/domain/member/repositories/MemberRepository.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/domain/member/repositories/MemberRepository.java
index a87d8a8..d169c0a 100644
--- a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/domain/member/repositories/MemberRepository.java
+++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/domain/member/repositories/MemberRepository.java
@@ -11,6 +11,6 @@ public interface MemberRepository {
void saveMember(Member geometry);
List
> values;
+
+ public LineChartDto(List
> values) {
+ this.labels = labels;
+ this.values = values;
+ }
+
+ public List
> getValues() {
+ return values;
+ }
+}
diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/LineChartController.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/LineChartController.java
new file mode 100644
index 0000000..dc43b0c
--- /dev/null
+++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/LineChartController.java
@@ -0,0 +1,24 @@
+package be.informatievlaanderen.vsds.demonstrator.member.rest.websocket;
+
+import be.informatievlaanderen.vsds.demonstrator.member.application.services.MemberService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.simp.SimpMessagingTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Controller;
+
+@Controller
+public class LineChartController {
+ private final SimpMessagingTemplate template;
+ private final MemberService memberService;
+
+ @Autowired
+ public LineChartController(SimpMessagingTemplate template, MemberService memberService) {
+ this.template = template;
+ this.memberService = memberService;
+ }
+
+ @Scheduled(fixedDelay = 1000)
+ public void send() {
+ this.template.convertAndSend("/broker/linechart", memberService.getLineChartDto());
+ }
+}
diff --git a/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/LineChartControllerTest.java b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/LineChartControllerTest.java
new file mode 100644
index 0000000..c344513
--- /dev/null
+++ b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/LineChartControllerTest.java
@@ -0,0 +1,37 @@
+package be.informatievlaanderen.vsds.demonstrator.member.rest.websocket;
+
+import be.informatievlaanderen.vsds.demonstrator.member.application.services.MemberService;
+import be.informatievlaanderen.vsds.demonstrator.member.rest.dtos.LineChartDto;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.messaging.simp.SimpMessagingTemplate;
+
+import java.util.List;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class LineChartControllerTest {
+
+ @Mock
+ private MemberService memberService;
+ @Mock
+ private SimpMessagingTemplate simpMessagingTemplate;
+ @InjectMocks
+ private LineChartController lineChartController;
+
+ @Test
+ void test_lineChartIsTransferredToWebsocket(){
+ LineChartDto lineChartDto = new LineChartDto(List.of(), List.of());
+ when(memberService.getLineChartDto()).thenReturn(lineChartDto);
+ lineChartController.send();
+
+ verify(memberService).getLineChartDto();
+ verify(simpMessagingTemplate).convertAndSend("/broker/linechart",lineChartDto);
+ }
+
+}
\ No newline at end of file
diff --git a/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterControllerTest.java b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterControllerTest.java
index dab5ed8..f272db1 100644
--- a/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterControllerTest.java
+++ b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterControllerTest.java
@@ -22,7 +22,7 @@ class MemberCounterControllerTest {
private MemberCounterController memberCounterController;
@Test
- void test(){
+ void test_numberOfMembersIsTransferredToWebsocket(){
when(memberService.getNumberOfMembers()).thenReturn(76L);
memberCounterController.send();
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 8970972..019f77d 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -11,14 +11,17 @@
"@livereader/graphly-d3-vue": "^1.1.2",
"@terraformer/wkt": "^2.2.0",
"axios": "^1.5.0",
+ "chart.js": "^4.1.1",
"d3": "^7.8.5",
"proj4": "^2.9.0",
"proj4leaflet": "^1.0.2",
"vue": "^3.3.4",
+ "vue-chartjs": "^5.2.0",
"vue-router": "^4.2.4",
"webstomp-client": "^1.2.6"
},
"devDependencies": {
+ "@types/chart.js": "^2.9.38",
"@vitejs/plugin-vue": "^4.3.1",
"leaflet": "^1.9.4",
"vite": "^4.4.9"
@@ -392,6 +395,11 @@
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
+ "node_modules/@kurkle/color": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
+ "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
+ },
"node_modules/@livereader/graphly-d3": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/@livereader/graphly-d3/-/graphly-d3-1.5.2.tgz",
@@ -416,6 +424,15 @@
"resolved": "https://registry.npmjs.org/@terraformer/wkt/-/wkt-2.2.0.tgz",
"integrity": "sha512-i33rTSqPtmO4sRdeznI0IEc9gpIZZIXN5kGhZ4rTwVtDccDKL3h4uia9cmWdRJlJMlG4Febxatw5b9ylI5YYuA=="
},
+ "node_modules/@types/chart.js": {
+ "version": "2.9.38",
+ "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.38.tgz",
+ "integrity": "sha512-rLoHHprkVEDpAXqke/xHalyXR+5Nv+3tfViwT/UnJZ41Wp/XPaSRlJKw2PU3S3tTCqKKyjkYai+VpeHoti79XQ==",
+ "dev": true,
+ "dependencies": {
+ "moment": "^2.10.2"
+ }
+ },
"node_modules/@vitejs/plugin-vue": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.4.tgz",
@@ -566,6 +583,17 @@
"proxy-from-env": "^1.1.0"
}
},
+ "node_modules/chart.js": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.1.1.tgz",
+ "integrity": "sha512-P0pCosNXp+LR8zO/QTkZKT6Hb7p0DPFtypEeVOf+6x06hX13NIb75R0DXUA4Ksx/+48chDQKtCCmRCviQRTqsA==",
+ "dependencies": {
+ "@kurkle/color": "^0.3.0"
+ },
+ "engines": {
+ "pnpm": "^7.0.0"
+ }
+ },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1100,9 +1128,9 @@
"dev": true
},
"node_modules/magic-string": {
- "version": "0.30.3",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz",
- "integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==",
+ "version": "0.30.4",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.4.tgz",
+ "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
@@ -1134,6 +1162,15 @@
"node": ">= 0.6"
}
},
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
@@ -1157,9 +1194,9 @@
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"node_modules/postcss": {
- "version": "8.4.30",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.30.tgz",
- "integrity": "sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==",
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"funding": [
{
"type": "opencollective",
@@ -1227,9 +1264,9 @@
"integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="
},
"node_modules/rollup": {
- "version": "3.29.3",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.3.tgz",
- "integrity": "sha512-T7du6Hum8jOkSWetjRgbwpM6Sy0nECYrYRSmZjayFcOddtKJWU4d17AC3HNUk7HRuqy4p+G7aEZclSHytqUmEg==",
+ "version": "3.29.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
+ "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
@@ -1335,6 +1372,15 @@
"@vue/shared": "3.3.4"
}
},
+ "node_modules/vue-chartjs": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.2.0.tgz",
+ "integrity": "sha512-d3zpKmGZr2OWHQ1xmxBcAn5ShTG917+/UCLaSpaCDDqT0U7DBsvFzTs69ZnHCgKoXT55GZDW8YEj9Av+dlONLA==",
+ "peerDependencies": {
+ "chart.js": "^4.1.1",
+ "vue": "^3.0.0-0 || ^2.7.0"
+ }
+ },
"node_modules/vue-router": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 7cb0305..c075281 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -11,14 +11,17 @@
"@livereader/graphly-d3-vue": "^1.1.2",
"@terraformer/wkt": "^2.2.0",
"axios": "^1.5.0",
+ "chart.js": "^4.1.1",
"d3": "^7.8.5",
"proj4": "^2.9.0",
"proj4leaflet": "^1.0.2",
"vue": "^3.3.4",
+ "vue-chartjs": "^5.2.0",
"vue-router": "^4.2.4",
"webstomp-client": "^1.2.6"
},
"devDependencies": {
+ "@types/chart.js": "^2.9.38",
"@vitejs/plugin-vue": "^4.3.1",
"leaflet": "^1.9.4",
"vite": "^4.4.9"
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index b70cb03..bd73153 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -2,6 +2,7 @@
import LeafletMap from './components/map/LeafletMap.vue'
import GlobalHeader from "@/components/headers/GlobalHeader.vue";
import MemberCounter from './components/membercounter/MemberCounter.vue'
+import LineChart from "@/components/linechart/LineChart.vue";
@@ -22,6 +23,9 @@ import MemberCounter from './components/membercounter/MemberCounter.vue'
up-to-date met de bron.