From cfd28a6cec758d0a0818dc12c33d25337294e820 Mon Sep 17 00:00:00 2001 From: Wouter Lefever Date: Mon, 2 Oct 2023 13:38:51 +0200 Subject: [PATCH] Feat: Add membercounter (#19) Co-authored-by: WouterLefever --- .../application/services/MemberService.java | 2 + .../services/MemberServiceImpl.java | 10 ++-- .../member/repositories/MemberRepository.java | 2 + .../member/infra/MemberRepositoryImpl.java | 5 ++ .../websocket/MemberCounterController.java | 25 +++++++++ .../rest/websocket/MessageController.java | 2 +- .../rest/websocket/WebSocketConfig.java | 10 +--- .../services/MemberServiceImplTest.java | 8 ++- .../infra/MemberRepositoryImplTest.java | 7 +++ .../MemberCounterControllerTest.java | 33 ++++++++++++ frontend/src/App.vue | 6 ++- .../svgs/{Linked data.svg => Linked_data.svg} | 0 ...eren NIV2.svg => LOGO_Vlaanderen_NIV2.svg} | 0 ...balheader.svg => divider_globalheader.svg} | 0 .../{hulp nodig.svg => hulp_nodig.svg} | 0 .../src/components/graph/KnowledgeGraph.vue | 2 +- .../src/components/headers/GlobalHeader.vue | 6 +-- .../membercounter/MemberCounter.vue | 53 +++++++++++++++++++ 18 files changed, 152 insertions(+), 19 deletions(-) create mode 100644 backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterController.java create mode 100644 backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterControllerTest.java rename frontend/src/assets/svgs/{Linked data.svg => Linked_data.svg} (100%) rename frontend/src/assets/svgs/global-header/{LOGO Vlaanderen NIV2.svg => LOGO_Vlaanderen_NIV2.svg} (100%) rename frontend/src/assets/svgs/global-header/{divider globalheader.svg => divider_globalheader.svg} (100%) rename frontend/src/assets/svgs/global-header/{hulp nodig.svg => hulp_nodig.svg} (100%) create mode 100644 frontend/src/components/membercounter/MemberCounter.vue 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 75d6828..62b274e 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 @@ -13,4 +13,6 @@ public interface MemberService { List getMembersInRectangle(Geometry rectangleGeometry, LocalDateTime timestamp, String timePeriod); MemberDto getMemberById(String memberId); + + long getNumberOfMembers(); } 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 f81273f..7b74e07 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 @@ -7,8 +7,7 @@ import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.MemberDto; 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.MemberExceptionHandler; -import be.informatievlaanderen.vsds.demonstrator.member.rest.websocket.WebSocketConfig; +import be.informatievlaanderen.vsds.demonstrator.member.rest.websocket.MessageController; import org.locationtech.jts.geom.Geometry; import org.opengis.referencing.operation.TransformException; import org.opengis.util.FactoryException; @@ -16,12 +15,10 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.wololo.jts2geojson.GeoJSONWriter; -import be.informatievlaanderen.vsds.demonstrator.member.rest.websocket.MessageController; import java.time.Duration; import java.time.LocalDateTime; import java.util.List; -import java.util.NoSuchElementException; @Service public class MemberServiceImpl implements MemberService { @@ -66,4 +63,9 @@ public MemberDto getMemberById(String memberId) { .map(memberGeometry -> new MemberDto(memberGeometry.getMemberId(), geoJSONWriter.write(memberGeometry.getGeometry()), memberGeometry.getTimestamp())) .orElseThrow(() -> new ResourceNotFoundException("Member", memberId)); } + + @Override + public long getNumberOfMembers() { + return repository.getNumberOfMembers(); + } } 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 b69a231..a87d8a8 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,4 +11,6 @@ public interface MemberRepository { void saveMember(Member geometry); List getMembersByGeometry(Geometry geometry, LocalDateTime startTime, LocalDateTime endTime); Optional findByMemberId(String memberId); + + long getNumberOfMembers(); } diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/infra/MemberRepositoryImpl.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/infra/MemberRepositoryImpl.java index 01e2364..7042e7d 100644 --- a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/infra/MemberRepositoryImpl.java +++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/infra/MemberRepositoryImpl.java @@ -37,4 +37,9 @@ public Optional findByMemberId(String memberId) { .findById(memberId) .map(entity -> new Member(entity.getMemberId(), entity.getGeometry(), entity.getTimestamp())); } + + @Override + public long getNumberOfMembers() { + return memberGeometryJpaRepo.count(); + } } diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterController.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterController.java new file mode 100644 index 0000000..bd9a4e6 --- /dev/null +++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterController.java @@ -0,0 +1,25 @@ +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 MemberCounterController { + private final SimpMessagingTemplate template; + private final MemberService memberService; + + @Autowired + public MemberCounterController(SimpMessagingTemplate template, MemberService memberService) { + this.template = template; + this.memberService = memberService; + } + + @Scheduled(fixedDelay = 60000) + public void send() { + long counter = memberService.getNumberOfMembers(); + this.template.convertAndSend("/broker/membercounter", counter); + } +} diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MessageController.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MessageController.java index 3f32754..324046f 100644 --- a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MessageController.java +++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MessageController.java @@ -10,7 +10,7 @@ @Controller public class MessageController { private SimpMessagingTemplate template; - private static final Logger log = LoggerFactory.getLogger(WebSocketConfig.class); + private static final Logger log = LoggerFactory.getLogger(MessageController.class); @Autowired public MessageController(SimpMessagingTemplate template) { diff --git a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/WebSocketConfig.java b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/WebSocketConfig.java index fa8bf79..0b11e39 100644 --- a/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/WebSocketConfig.java +++ b/backend/src/main/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/WebSocketConfig.java @@ -1,22 +1,16 @@ package be.informatievlaanderen.vsds.demonstrator.member.rest.websocket; -import be.informatievlaanderen.vsds.demonstrator.member.application.services.MemberServiceImpl; -import be.informatievlaanderen.vsds.demonstrator.member.application.valueobjects.MemberDto; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker +@EnableScheduling public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - private static final Logger log = LoggerFactory.getLogger(WebSocketConfig.class); @Override diff --git a/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberServiceImplTest.java b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberServiceImplTest.java index e8e0583..d9bba3c 100644 --- a/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberServiceImplTest.java +++ b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/application/services/MemberServiceImplTest.java @@ -8,7 +8,6 @@ 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.websocket.MessageController; -import be.informatievlaanderen.vsds.demonstrator.member.rest.websocket.WebSocketConfig; import org.apache.jena.rdf.model.Model; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFParser; @@ -140,6 +139,13 @@ void test_saveMember() throws IOException { verify(repository).saveMember(argThat(result -> result.getMemberId().equals(id))); } + @Test + void test_getNumberOfMembers() { + service.getNumberOfMembers(); + + verify(repository).getNumberOfMembers(); + } + private List initMembers() throws ParseException { final WKTReader reader = new WKTReader(); List members = new ArrayList<>(); diff --git a/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/infra/MemberRepositoryImplTest.java b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/infra/MemberRepositoryImplTest.java index b174aac..0ac5675 100644 --- a/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/infra/MemberRepositoryImplTest.java +++ b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/infra/MemberRepositoryImplTest.java @@ -110,6 +110,13 @@ void test_Saving() { verify(jpaRepository).save(argThat(entity -> entity.getMemberId().equals(member.getMemberId()))); } + @Test + void test_NumberCount(){ + repository.getNumberOfMembers(); + + verify(jpaRepository).count(); + } + private List initMembers() throws ParseException { final WKTReader reader = new WKTReader(); List members = new ArrayList<>(); 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 new file mode 100644 index 0000000..dab5ed8 --- /dev/null +++ b/backend/src/test/java/be/informatievlaanderen/vsds/demonstrator/member/rest/websocket/MemberCounterControllerTest.java @@ -0,0 +1,33 @@ +package be.informatievlaanderen.vsds.demonstrator.member.rest.websocket; + +import be.informatievlaanderen.vsds.demonstrator.member.application.services.MemberService; +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 static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MemberCounterControllerTest { + + @Mock + private MemberService memberService; + @Mock + private SimpMessagingTemplate simpMessagingTemplate; + @InjectMocks + private MemberCounterController memberCounterController; + + @Test + void test(){ + when(memberService.getNumberOfMembers()).thenReturn(76L); + memberCounterController.send(); + + verify(memberService).getNumberOfMembers(); + verify(simpMessagingTemplate).convertAndSend("/broker/membercounter",76L); + } + +} \ No newline at end of file diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 8545bd3..f54bce3 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,6 +1,7 @@