From 7ed3c4bcb24571746815ef946c6790d86eb0955a Mon Sep 17 00:00:00 2001 From: Robert Wittek Date: Sun, 10 May 2020 01:26:01 +0200 Subject: [PATCH] FMD-53 generate qr codes in coceso, update to knockout 3.5.1 --- .../java/at/wrk/coceso/entity/Container.java | 17 +- main/resources/ReleaseNotes/2.7.0.md | 2 + .../service/impl/ContainerServiceImpl.java | 33 +- .../wrk/coceso/service/ContainerService.java | 9 +- .../config/DeploymentStatusProvider.java | 29 +- .../controller/data/ContainerController.java | 36 +- .../controller/view/WelcomeController.java | 29 +- .../classes/i18n/messages_de.properties | 1 + .../classes/i18n/messages_en.properties | 1 + .../src/main/webapp/WEB-INF/pages/home.jsp | 15 +- .../main/webapp/WEB-INF/pages/qr_codes.jsp | 103 +++ main/view/src/main/webapp/static/bower.json | 2 +- .../main/webapp/static/geobroker_qr_info.html | 36 + .../static/js/assets/knockout/knockout.js | 253 ++++---- .../webapp/static/js/assets/qrcode/qrcode.js | 614 ++++++++++++++++++ main/view/src/main/webapp/static/js/config.js | 6 +- .../js/edit/viewmodels/qr_code_filter.js | 112 ++++ .../src/main/webapp/static/js/qr_codes.js | 20 + main/view/src/main/webapp/static/license.html | 8 +- .../geobroker/contract/qr/ExternalUnit.java | 79 +++ .../controller/GeobrokerUnitController.java | 54 ++ .../manager/ConcurrentGeoBrokerManager.java | 10 + .../geobroker/manager/GeoBrokerManager.java | 4 + .../src/main/resources/geobroker.properties | 3 + .../coceso/plugins/gmaps/GmapsWrapper.java | 2 +- 25 files changed, 1317 insertions(+), 161 deletions(-) create mode 100644 main/view/src/main/webapp/WEB-INF/pages/qr_codes.jsp create mode 100644 main/view/src/main/webapp/static/geobroker_qr_info.html create mode 100644 main/view/src/main/webapp/static/js/assets/qrcode/qrcode.js create mode 100644 main/view/src/main/webapp/static/js/edit/viewmodels/qr_code_filter.js create mode 100644 main/view/src/main/webapp/static/js/qr_codes.js create mode 100644 plugin/geobroker/src/main/java/at/wrk/coceso/plugin/geobroker/contract/qr/ExternalUnit.java create mode 100644 plugin/geobroker/src/main/java/at/wrk/coceso/plugin/geobroker/controller/GeobrokerUnitController.java diff --git a/main/entity/src/main/java/at/wrk/coceso/entity/Container.java b/main/entity/src/main/java/at/wrk/coceso/entity/Container.java index 96ca7fcd..98460176 100644 --- a/main/entity/src/main/java/at/wrk/coceso/entity/Container.java +++ b/main/entity/src/main/java/at/wrk/coceso/entity/Container.java @@ -3,13 +3,28 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.MapKeyJoinColumn; +import javax.persistence.PrePersist; +import javax.persistence.PreUpdate; +import javax.persistence.Table; +import javax.persistence.Transient; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -import javax.persistence.*; @Entity @Table(name = "container") diff --git a/main/resources/ReleaseNotes/2.7.0.md b/main/resources/ReleaseNotes/2.7.0.md index 60467e43..40b195ee 100644 --- a/main/resources/ReleaseNotes/2.7.0.md +++ b/main/resources/ReleaseNotes/2.7.0.md @@ -16,3 +16,5 @@ * FMD-27 Auto-complete for street intersections * FMD-194 Provide one-time-actions of type "nextState" on geobroker API * FMD-23 Refactor links of PDF reports: use dropdown instead of separate buttons +* FMD-53 Generate QR code in CoCeSo +* FMD-53 Upgrade to knockout 3.5.1 diff --git a/main/service-impl/src/main/java/at/wrk/coceso/service/impl/ContainerServiceImpl.java b/main/service-impl/src/main/java/at/wrk/coceso/service/impl/ContainerServiceImpl.java index e4334380..f877c12c 100644 --- a/main/service-impl/src/main/java/at/wrk/coceso/service/impl/ContainerServiceImpl.java +++ b/main/service-impl/src/main/java/at/wrk/coceso/service/impl/ContainerServiceImpl.java @@ -1,8 +1,8 @@ package at.wrk.coceso.service.impl; import at.wrk.coceso.entity.Concern; -import at.wrk.coceso.entity.Unit; import at.wrk.coceso.entity.Container; +import at.wrk.coceso.entity.Unit; import at.wrk.coceso.entity.enums.Errors; import at.wrk.coceso.exceptions.ErrorsException; import at.wrk.coceso.repository.ContainerRepository; @@ -10,17 +10,22 @@ import at.wrk.coceso.service.ConcernService; import at.wrk.coceso.service.ContainerService; import at.wrk.coceso.utils.Initializer; +import com.google.common.collect.ImmutableList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service @Transactional class ContainerServiceImpl implements ContainerService { + private static final Logger LOG = LoggerFactory.getLogger(ContainerServiceImpl.class); @Autowired private ContainerRepository containerRepository; @@ -31,6 +36,21 @@ class ContainerServiceImpl implements ContainerService { @Autowired private ConcernService concernService; + @Override + public List getAll(final int concernId) { + Concern concern = concernService.getById(concernId); + + List containers; + if (concern != null) { + containers = getAll(concern); + } else { + LOG.info("Failed to read concern for concernId '{}'.", concernId); + containers = ImmutableList.of(); + } + + return containers; + } + @Override public List getAll(Concern concern) { List container = containerRepository.findByConcern(concern); @@ -54,7 +74,10 @@ public Container getRoot(Concern concern) { @Override public Set getSpare(Concern concern) { - return unitRepository.findSpare(concern).stream().map(Unit::getId).collect(Collectors.toSet()); + return unitRepository.findSpare(concern) + .stream() + .map(Unit::getId) + .collect(Collectors.toSet()); } @Override diff --git a/main/service/src/main/java/at/wrk/coceso/service/ContainerService.java b/main/service/src/main/java/at/wrk/coceso/service/ContainerService.java index 0bbd9b07..f5487b2c 100644 --- a/main/service/src/main/java/at/wrk/coceso/service/ContainerService.java +++ b/main/service/src/main/java/at/wrk/coceso/service/ContainerService.java @@ -2,15 +2,18 @@ import at.wrk.coceso.entity.Concern; import at.wrk.coceso.entity.Container; -import java.util.List; -import java.util.Set; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Set; + @Service @Transactional public interface ContainerService { + List getAll(int concernId); + List getAll(Concern concern); Container getRoot(Concern concern); @@ -25,7 +28,7 @@ public interface ContainerService { Container doRemoveUnit(int unitId); - static class ContainerPair { + class ContainerPair { public boolean notifyRoot = false; public Container previous = null; diff --git a/main/view/src/main/java/at/wrk/coceso/controller/config/DeploymentStatusProvider.java b/main/view/src/main/java/at/wrk/coceso/controller/config/DeploymentStatusProvider.java index 91aed728..4653f2c1 100644 --- a/main/view/src/main/java/at/wrk/coceso/controller/config/DeploymentStatusProvider.java +++ b/main/view/src/main/java/at/wrk/coceso/controller/config/DeploymentStatusProvider.java @@ -8,22 +8,35 @@ public class DeploymentStatusProvider { private static final Logger LOG = LoggerFactory.getLogger(DeploymentStatusProvider.class); + private static final String ALARM_TEXT_CLASS = "at.wrk.coceso.alarm.text.controller.AlarmTextController"; + private static final String GEOBROKER_CONTROLLER_CLASS = "at.wrk.coceso.plugin.geobroker.controller.GeobrokerUnitController"; + private final boolean alarmTextModuleDeployed; + private final boolean geoBrokerModuleDeployed; public DeploymentStatusProvider() { + this.alarmTextModuleDeployed = checkIfClassIsPresent(ALARM_TEXT_CLASS); + this.geoBrokerModuleDeployed = checkIfClassIsPresent(GEOBROKER_CONTROLLER_CLASS); + } + + public boolean isAlarmTextModuleDeployed() { + return alarmTextModuleDeployed; + } + + public boolean isGeoBrokerModuleDeployed() { + return geoBrokerModuleDeployed; + } + + private boolean checkIfClassIsPresent(final String className) { boolean alarmTextClassPresent; try { - Class.forName("at.wrk.coceso.alarm.text.controller.AlarmTextController"); - LOG.debug("Alarm Text Module is present in classpath."); + Class.forName(className); + LOG.info("Class was found during deployment status check: '{}'. Associated feature is ENABLED.", className); alarmTextClassPresent = true; } catch (ClassNotFoundException e) { + LOG.info("Class was not found during deployment status check: '{}'. Associated feature is DISABLED. Message: {}", className, e.getMessage()); alarmTextClassPresent = false; } - - this.alarmTextModuleDeployed = alarmTextClassPresent; - } - - public boolean isAlarmTextModuleDeployed() { - return alarmTextModuleDeployed; + return alarmTextClassPresent; } } diff --git a/main/view/src/main/java/at/wrk/coceso/controller/data/ContainerController.java b/main/view/src/main/java/at/wrk/coceso/controller/data/ContainerController.java index 3246cf6d..1b6468b4 100644 --- a/main/view/src/main/java/at/wrk/coceso/controller/data/ContainerController.java +++ b/main/view/src/main/java/at/wrk/coceso/controller/data/ContainerController.java @@ -10,10 +10,15 @@ import at.wrk.coceso.service.ContainerService; import at.wrk.coceso.service.ContainerWriteService; import at.wrk.coceso.utils.ActiveConcern; -import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; @RestController @PreAuthorize("@auth.hasAccessLevel('Edit')") @@ -29,36 +34,43 @@ public class ContainerController { private final EntityEventHandler entityEventHandler; @Autowired - public ContainerController(EntityEventFactory eehf) { - this.entityEventHandler = eehf.getEntityEventHandler(Container.class); + public ContainerController(final EntityEventFactory entityEventFactory) { + this.entityEventHandler = entityEventFactory.getEntityEventHandler(Container.class); } @RequestMapping(value = "getAll", produces = "application/json", method = RequestMethod.GET) - public SequencedResponse> getAll(@ActiveConcern Concern concern) { + public SequencedResponse> getAll(@ActiveConcern final Concern concern) { return new SequencedResponse<>(entityEventHandler.getHver(), entityEventHandler.getSeq(concern.getId()), containerService.getAll(concern)); } + @RequestMapping(value = "getAllForConcern", produces = "application/json", method = RequestMethod.GET) + public RestResponse getAll(@RequestParam(value = "concernId") final int concernId) { + return new RestResponse(true, new RestProperty("container", containerService.getAll(concernId))); + } + @RequestMapping(value = "updateContainer", produces = "application/json", method = RequestMethod.POST) - public RestResponse updateContainer(@RequestBody Container container, @ActiveConcern Concern concern) { - container = containerWriteService.update(container, concern); - return new RestResponse(true, new RestProperty("id", container.getId())); + public RestResponse updateContainer(@RequestBody final Container container, @ActiveConcern final Concern concern) { + Container updatedContainer = containerWriteService.update(container, concern); + return new RestResponse(true, new RestProperty("id", updatedContainer.getId())); } @RequestMapping(value = "removeContainer", produces = "application/json", method = RequestMethod.POST) - public RestResponse removeContainer(@RequestParam("container_id") int containerId) { + public RestResponse removeContainer(@RequestParam("container_id") final int containerId) { containerWriteService.remove(containerId); return new RestResponse(true); } @RequestMapping(value = "updateUnit", produces = "application/json", method = RequestMethod.POST) - public RestResponse updateUnit(@RequestParam("container_id") int containerId, - @RequestParam("unit_id") int unitId, @RequestParam("ordering") double ordering) { + public RestResponse updateUnit( + @RequestParam("container_id") final int containerId, + @RequestParam("unit_id") final int unitId, + @RequestParam("ordering") final double ordering) { containerWriteService.updateUnit(containerId, unitId, ordering); return new RestResponse(true); } @RequestMapping(value = "removeUnit", produces = "application/json", method = RequestMethod.POST) - public RestResponse removeUnit(@RequestParam("unit_id") int unitId) { + public RestResponse removeUnit(@RequestParam("unit_id") final int unitId) { containerWriteService.removeUnit(unitId); return new RestResponse(true); } diff --git a/main/view/src/main/java/at/wrk/coceso/controller/view/WelcomeController.java b/main/view/src/main/java/at/wrk/coceso/controller/view/WelcomeController.java index b923a46a..c50cf4da 100644 --- a/main/view/src/main/java/at/wrk/coceso/controller/view/WelcomeController.java +++ b/main/view/src/main/java/at/wrk/coceso/controller/view/WelcomeController.java @@ -1,5 +1,6 @@ package at.wrk.coceso.controller.view; +import at.wrk.coceso.controller.config.DeploymentStatusProvider; import at.wrk.coceso.data.AuthenticatedUser; import at.wrk.coceso.entity.Concern; import at.wrk.coceso.entity.User; @@ -9,6 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.web.WebAttributes; @@ -27,13 +29,23 @@ @Controller public class WelcomeController { + private final static Logger LOG = LoggerFactory.getLogger(WelcomeController.class); private static final Set ALLOWED_ERRORS = ImmutableSet.of(1); - private final static Logger LOG = LoggerFactory.getLogger(WelcomeController.class); + private final UserService userService; + private final DeploymentStatusProvider deploymentStatusProvider; + private final String publicGeoBrokerUrl; @Autowired - private UserService userService; + public WelcomeController( + final UserService userService, + final DeploymentStatusProvider deploymentStatusProvider, + final @Value("${geobroker.public.url:configuration-missing}") String publicGeoBrokerUrl) { + this.userService = userService; + this.deploymentStatusProvider = deploymentStatusProvider; + this.publicGeoBrokerUrl = publicGeoBrokerUrl.endsWith("/") ? publicGeoBrokerUrl : publicGeoBrokerUrl + "/"; + } @PreAuthorize("permitAll") @RequestMapping(value = "/", method = RequestMethod.GET) @@ -73,7 +85,7 @@ public String showHome( response.addCookie(new Cookie("concern", active.getId() + "")); } else { // Delete Cookie and active concern reference - LOG.info("{}: Active concern is already closed, clean up", authenticationUser); + LOG.info("{}: Active concern is already closed, cleaning up cookie", authenticationUser); response.addCookie(new Cookie("concern", null)); userService.setActiveConcern(authenticationUser, null); } @@ -81,9 +93,18 @@ public String showHome( // Add Userdetails to Model map.addAttribute("user", Initializer.init(user, User::getInternalAuthorities)); map.addAttribute("authenticatedUser", authenticationUser); + map.put("isGeoBrokerFeatureAvailable", deploymentStatusProvider.isGeoBrokerModuleDeployed()); - LOG.debug("{}: Started Home Screen", user); + LOG.debug("{}: Started Home Screen with model map: {}", user, map); return "home"; } + + @PreAuthorize("@auth.hasAccessLevel('Edit')") + @RequestMapping(value = "/geo/qr-codes", method = RequestMethod.GET) + public String showQrCodePage(final ModelMap map, @RequestParam(value = "concernId") final int concernId) { + map.put("concernId", concernId); + map.put("publicGeobrokerUrl", publicGeoBrokerUrl); + return "qr_codes"; + } } diff --git a/main/view/src/main/webapp/WEB-INF/classes/i18n/messages_de.properties b/main/view/src/main/webapp/WEB-INF/classes/i18n/messages_de.properties index 53ed7b6e..8fe3e615 100644 --- a/main/view/src/main/webapp/WEB-INF/classes/i18n/messages_de.properties +++ b/main/view/src/main/webapp/WEB-INF/classes/i18n/messages_de.properties @@ -207,6 +207,7 @@ concern.locked=Die aktuelle Ambulanz ist in einem anderen Fenster ge\u00 Falls das nicht funktioniert k\u00f6nnen Sie eine Aufhebung der Sperre erzwingen. concern.unlock=Sperre aufheben concern.addsection=Abschnitt hinzuf\u00fcgen +concern.qr.codes=QR Codes # Unit - Properties unit=Einheit diff --git a/main/view/src/main/webapp/WEB-INF/classes/i18n/messages_en.properties b/main/view/src/main/webapp/WEB-INF/classes/i18n/messages_en.properties index ead573b1..9be6fb40 100644 --- a/main/view/src/main/webapp/WEB-INF/classes/i18n/messages_en.properties +++ b/main/view/src/main/webapp/WEB-INF/classes/i18n/messages_en.properties @@ -207,6 +207,7 @@ concern.locked=Some page seems to lock the concern.
\ You can also force unlocking. concern.unlock=Force unlocking concern.addsection=Create section +concern.qr.codes=QR Codes # Unit - Properties unit=Unit diff --git a/main/view/src/main/webapp/WEB-INF/pages/home.jsp b/main/view/src/main/webapp/WEB-INF/pages/home.jsp index 66b7ff7a..2596659b 100644 --- a/main/view/src/main/webapp/WEB-INF/pages/home.jsp +++ b/main/view/src/main/webapp/WEB-INF/pages/home.jsp @@ -106,8 +106,8 @@ -
-
+ + + + + + + @@ -163,8 +170,8 @@ -
-