From a4821e4a65b07f2d5b032e2f32260c1de9d55857 Mon Sep 17 00:00:00 2001 From: orende <1337decker@gmail.com> Date: Thu, 27 Oct 2022 14:17:10 +0200 Subject: [PATCH 01/15] Replace hardcoded strings in booking and tracking web apps --- .../booking/facade/dto/CargoRoutingDTO.java | 2 + .../booking/web/CargoAdminController.java | 12 +++- .../tracking/CargoTrackingController.java | 6 +- .../tracking/CargoTrackingViewAdapter.java | 34 +++++---- .../tracking/TrackCommandValidator.java | 1 - src/main/resources/messages_en.properties | 61 +++++++++++++++- src/main/resources/messages_sv.properties | 72 +++++++++++++++++++ src/main/resources/templates/admin/list.html | 14 ++-- .../templates/admin/pickNewDestination.html | 10 +-- .../templates/admin/registrationForm.html | 12 ++-- .../templates/admin/selectItinerary.html | 23 +++--- src/main/resources/templates/admin/show.html | 26 +++---- .../resources/templates/adminDecorator.html | 6 +- src/main/resources/templates/track.html | 25 +++---- 14 files changed, 223 insertions(+), 81 deletions(-) create mode 100644 src/main/resources/messages_sv.properties diff --git a/src/main/java/se/citerus/dddsample/interfaces/booking/facade/dto/CargoRoutingDTO.java b/src/main/java/se/citerus/dddsample/interfaces/booking/facade/dto/CargoRoutingDTO.java index e76efff0a..21b3515ff 100644 --- a/src/main/java/se/citerus/dddsample/interfaces/booking/facade/dto/CargoRoutingDTO.java +++ b/src/main/java/se/citerus/dddsample/interfaces/booking/facade/dto/CargoRoutingDTO.java @@ -1,5 +1,7 @@ package se.citerus.dddsample.interfaces.booking.facade.dto; +import org.springframework.context.MessageSource; + import java.io.Serializable; import java.time.Instant; import java.time.ZoneOffset; diff --git a/src/main/java/se/citerus/dddsample/interfaces/booking/web/CargoAdminController.java b/src/main/java/se/citerus/dddsample/interfaces/booking/web/CargoAdminController.java index 868d1723a..2060d8a2d 100644 --- a/src/main/java/se/citerus/dddsample/interfaces/booking/web/CargoAdminController.java +++ b/src/main/java/se/citerus/dddsample/interfaces/booking/web/CargoAdminController.java @@ -2,12 +2,15 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import com.google.common.collect.ImmutableMap; import org.springframework.beans.propertyeditors.CustomDateEditor; +import org.springframework.context.MessageSource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.ServletRequestDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.support.RequestContextUtils; import se.citerus.dddsample.interfaces.booking.facade.BookingServiceFacade; import se.citerus.dddsample.interfaces.booking.facade.dto.CargoRoutingDTO; import se.citerus.dddsample.interfaces.booking.facade.dto.LegDTO; @@ -40,9 +43,11 @@ public final class CargoAdminController { private final BookingServiceFacade bookingServiceFacade; + private final MessageSource messageSource; - public CargoAdminController(BookingServiceFacade bookingServiceFacade) { + public CargoAdminController(BookingServiceFacade bookingServiceFacade, MessageSource messageSource) { this.bookingServiceFacade = bookingServiceFacade; + this.messageSource = messageSource; } @InitBinder @@ -52,6 +57,7 @@ private void initBinder(HttpServletRequest request, ServletRequestDataBinder bin @RequestMapping("/registration") public String registration(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception { + model.putAll(ImmutableMap.of("messageSource", messageSource, "locale", RequestContextUtils.getLocale(request))); List dtoList = bookingServiceFacade.listShippingLocations(); List unLocodeStrings = new ArrayList(); @@ -78,6 +84,7 @@ public void register(HttpServletRequest request, HttpServletResponse response, @RequestMapping("/list") public String list(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception { + model.putAll(ImmutableMap.of("messageSource", messageSource, "locale", RequestContextUtils.getLocale(request))); List cargoList = bookingServiceFacade.listAllCargos(); model.put("cargoList", cargoList); @@ -86,6 +93,7 @@ public String list(HttpServletRequest request, HttpServletResponse response, Map @RequestMapping("/show") public String show(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception { + model.putAll(ImmutableMap.of("messageSource", messageSource, "locale", RequestContextUtils.getLocale(request))); String trackingId = request.getParameter("trackingId"); CargoRoutingDTO dto = bookingServiceFacade.loadCargoForRouting(trackingId); model.put("cargo", dto); @@ -94,6 +102,7 @@ public String show(HttpServletRequest request, HttpServletResponse response, Map @RequestMapping("/selectItinerary") public String selectItinerary(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception { + model.putAll(ImmutableMap.of("messageSource", messageSource, "locale", RequestContextUtils.getLocale(request))); String trackingId = request.getParameter("trackingId"); List routeCandidates = bookingServiceFacade.requestPossibleRoutesForCargo(trackingId); @@ -127,6 +136,7 @@ public void assignItinerary(HttpServletRequest request, HttpServletResponse resp @RequestMapping(value = "/pickNewDestination") public String pickNewDestination(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception { + model.putAll(ImmutableMap.of("messageSource", messageSource, "locale", RequestContextUtils.getLocale(request))); List locations = bookingServiceFacade.listShippingLocations(); model.put("locations", locations); diff --git a/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingController.java b/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingController.java index b7eb1b604..84b99f1c2 100644 --- a/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingController.java +++ b/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingController.java @@ -29,7 +29,7 @@ * helps us shield the domain model classes. *

* - * @see CargoTrackingViewAdapter + * @see se.citerus.dddsample.interfaces.tracking.CargoTrackingViewAdapter * @see se.citerus.dddsample.interfaces.booking.web.CargoAdminController */ @Controller @@ -63,17 +63,17 @@ private String onSubmit(final HttpServletRequest request, final TrackCommand command, final Map model, final BindingResult bindingResult) { + final Locale locale = RequestContextUtils.getLocale(request); trackCommandValidator.validate(command, bindingResult); final TrackingId trackingId = new TrackingId(command.getTrackingId()); final Cargo cargo = cargoRepository.find(trackingId); if (cargo != null) { - final Locale locale = RequestContextUtils.getLocale(request); final List handlingEvents = handlingEventRepository.lookupHandlingHistoryOfCargo(trackingId).distinctEventsByCompletionTime(); model.put("cargo", new CargoTrackingViewAdapter(cargo, messageSource, locale, handlingEvents)); } else { - bindingResult.rejectValue("trackingId", "cargo.unknown_id", new Object[]{command.getTrackingId()}, "Unknown tracking id"); + bindingResult.rejectValue("trackingId", "cargo.unknown_id", new Object[]{command.getTrackingId()}, ""); } return "track"; } diff --git a/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingViewAdapter.java b/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingViewAdapter.java index 04ff20a57..b1f02eca4 100644 --- a/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingViewAdapter.java +++ b/src/main/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingViewAdapter.java @@ -23,8 +23,9 @@ public final class CargoTrackingViewAdapter { private final List events; private final String FORMAT = "yyyy-MM-dd hh:mm"; private final TimeZone timeZone; + private final SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT); - /** + /** * Constructor. * * @param cargo @@ -97,6 +98,14 @@ public String getStatusText() { return messageSource.getMessage(code, args, "[Unknown status]", locale); } + public String getEtaText() { + return messageSource.getMessage("cargo.routing.eta", new Object[]{getDestination(), getEta()}, locale); + } + + public String getStatusDescriptionText() { + return messageSource.getMessage("cargo.routing.result", new Object[]{getTrackingId(), getStatusText()}, locale); + } + /** * @return Cargo destination location. */ @@ -131,19 +140,20 @@ public String getNextExpectedActivity() { return ""; } - String text = "Next expected activity is to "; HandlingEvent.Type type = activity.type(); if (type.sameValueAs(HandlingEvent.Type.LOAD)) { - return - text + type.name().toLowerCase() + " cargo onto voyage " + activity.voyage().voyageNumber() + - " in " + activity.location().name(); - } else if (type.sameValueAs(HandlingEvent.Type.UNLOAD)) { - return - text + type.name().toLowerCase() + " cargo off of " + activity.voyage().voyageNumber() + - " in " + activity.location().name(); - } else { - return text + type.name().toLowerCase() + " cargo in " + activity.location().name(); - } + return messageSource.getMessage("cargo.routing.nextexpact." + type.name(), new Object[]{activity.voyage().voyageNumber(), activity.location().name()}, "Missing translation string", locale); + } else if (type.sameValueAs(HandlingEvent.Type.UNLOAD)) { + return messageSource.getMessage("cargo.routing.nextexpact." + type.name(), new Object[]{activity.voyage().voyageNumber(), activity.location().name()}, "Missing translation string", locale); + } else if (type.sameValueAs(HandlingEvent.Type.RECEIVE)) { + return messageSource.getMessage("cargo.routing.nextexpact." + type.name(), new Object[]{activity.location().name()}, "Missing translation string", locale); + } else if (type.sameValueAs(HandlingEvent.Type.CLAIM)) { + return messageSource.getMessage("cargo.routing.nextexpact." + type.name(), new Object[]{activity.location().name()}, "Missing translation string", locale); + } else if (type.sameValueAs(HandlingEvent.Type.CUSTOMS)) { + return messageSource.getMessage("cargo.routing.nextexpact." + type.name(), new Object[]{activity.location().name()}, "Missing translation string", locale); + } else { + return messageSource.getMessage("cargo.routing.nextexpact.unknown", null, "Missing translation string", locale); + } } /** diff --git a/src/main/java/se/citerus/dddsample/interfaces/tracking/TrackCommandValidator.java b/src/main/java/se/citerus/dddsample/interfaces/tracking/TrackCommandValidator.java index 8f8d39ebd..9d470468d 100644 --- a/src/main/java/se/citerus/dddsample/interfaces/tracking/TrackCommandValidator.java +++ b/src/main/java/se/citerus/dddsample/interfaces/tracking/TrackCommandValidator.java @@ -17,6 +17,5 @@ public boolean supports(@NonNull final Class clazz) { public void validate(@NonNull final Object object,@NonNull final Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "trackingId", "error.required", "Required"); } - } diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 356c2c2f6..5d649f814 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -4,10 +4,69 @@ cargo.status.ONBOARD_CARRIER=Onboard voyage {0} cargo.status.CLAIMED=Claimed cargo.status.UNKNOWN=Unknown +cargo.misrouted=Misrouted +cargo.notrouted=Not routed + deliveryHistory.eventDescription.NOT_RECEIVED=Cargo has not yet been received. deliveryHistory.eventDescription.LOAD=Loaded onto voyage {0} in {1}, at {2}. deliveryHistory.eventDescription.UNLOAD=Unloaded off voyage {0} in {1}, at {2}. deliveryHistory.eventDescription.RECEIVE=Received in {0}, at {1}. deliveryHistory.eventDescription.CLAIM=Claimed in {0}, at {1}. -deliveryHistory.eventDescription.CUSTOMS=Cleared customs in {0}, at {1}. \ No newline at end of file +deliveryHistory.eventDescription.CUSTOMS=Cleared customs in {0}, at {1}. + +booking.header=Cargo Booking and Routing +booking.listall=List all cargos +booking.booknew=Book new cargo +cargo.tracking.header=Tracking cargo +cargo.tracking.idinput=Enter your tracking id: +cargo.tracking.submitbutton=Track! +cargo.tracking.hint=Hint: try tracking "ABC123" or "JKL567". +cargo.tracking.handlinghistory=Handling History +cargo.tracking.misdirected=Cargo is misdirected +cargo.routing.result=Cargo {0} is now: {1} +cargo.routing.eta=Estimated time of arrival in {0}: {1} +cargo.routing.nextexpact.LOAD=Next expected activity is to load cargo onto voyage {0} in {1} +cargo.routing.nextexpact.UNLOAD=Next expected activity is to unload cargo off of voyage {0} in {1} +cargo.routing.nextexpact.RECEIVE=Next expected activity is to receive cargo in {0} +cargo.routing.nextexpact.CLAIM=Next expected activity is to claim cargo in {0} +cargo.routing.nextexpact.CUSTOMS=Next expected activity is to customs cargo in {0} +cargo.routing.nextexpact.unknown=Next expected activity is unknown + +cargo.admin.header=Cargo Administration +cargo.admin.tablecaption=All cargos +cargo.admin.tableheader.trackingid=Tracking ID +cargo.admin.tableheader.origin=Origin +cargo.admin.tableheader.destination=Destination +cargo.admin.tableheader.routed=Routed +cargo.admin.tableheader.arrivaldeadline=Arrival deadline: +cargo.admin.details.caption=Details for cargo +cargo.admin.details.picknewdest=Change destination +cargo.admin.details.arrivaldeadline=Arrival deadline +cargo.admin.details.selectitinerary=Route this cargo +cargo.admin.details.reroute=reroute this cargo +cargo.admin.details.misrouted=Cargo is misrouted +cargo.admin.details.itinerary=Itinerary +cargo.admin.details.voyageno=Voyage number +cargo.admin.details.load=Load +cargo.admin.details.unload=Unload +cargo.admin.newdest.change=Change destination for cargo +cargo.admin.newdest.currentdest=Current destination +cargo.admin.newdest.newdest=New destination +cargo.admin.newdest.submit=Change destination +cargo.admin.register.caption=Book new cargo +cargo.admin.register.book=Book +cargo.admin.itinerary.caption=Select route +cargo.admin.itinerary.summary=Cargo {0} is going from {1} to {2} +cargo.admin.itinerary.noroutecandidates=No routes found that satisfy the route specification. Try setting an arrival deadline further into the future (a few weeks at least). +cargo.admin.itinerary.routecandidatecaption=Route candidate {0} +cargo.admin.itinerary.voyage=Voyage +cargo.admin.itinerary.submit=Assign cargo to this route + +misc.yes=Yes +misc.no=No +misc.from=From +misc.to=To + +error.required=The tracking id must not be empty +cargo.unknown_id=Unknown tracking id \ No newline at end of file diff --git a/src/main/resources/messages_sv.properties b/src/main/resources/messages_sv.properties new file mode 100644 index 000000000..11fcafc60 --- /dev/null +++ b/src/main/resources/messages_sv.properties @@ -0,0 +1,72 @@ +cargo.status.NOT_RECEIVED=Ej mottagen +cargo.status.IN_PORT=I hamn {0} +cargo.status.ONBOARD_CARRIER=Ombord på resa {0} +cargo.status.CLAIMED=Upphämtad +cargo.status.UNKNOWN=Okänt + +cargo.misrouted=Rutt felplanerad +cargo.notrouted=Ej ruttplanerad + +deliveryHistory.eventDescription.NOT_RECEIVED=Godset har ännu ej anlänt. + +deliveryHistory.eventDescription.LOAD=Lastad på resa {0} i {1}, vid {2}. +deliveryHistory.eventDescription.UNLOAD=Avlastad från resa {0} i {1}, vid {2}. +deliveryHistory.eventDescription.RECEIVE=Mottagen i {0}, vid {1}. +deliveryHistory.eventDescription.CLAIM=Upphämtad i {0}, vid {1}. +deliveryHistory.eventDescription.CUSTOMS=Har förtullats i {0}, vid {1}. + +booking.header=Godsbokning och ruttplanering +booking.listall=Lista allt gods +booking.booknew=Boka nytt gods +cargo.tracking.header=Godsspårning +cargo.tracking.idinput=Skriv in spårningsid: +cargo.tracking.submitbutton=Spåra! +cargo.tracking.hint=Tips: Prova att söka på "ABC123" eller "JKL567". +cargo.tracking.handlinghistory=Hanteringshistorik +cargo.tracking.misdirected=Godset är felskickat +cargo.routing.result=Godset {0} är nu: {1} +cargo.routing.eta=Beräknad ankomsttid till {0}: {1} +cargo.routing.nextexpact.LOAD=Nästa förväntade aktivitet är att lasta godset ombord på resa {0} i {1} +cargo.routing.nextexpact.UNLOAD=Nästa förväntade aktivitet är att lasta av godset från resa {0} i {1} +cargo.routing.nextexpact.RECEIVE=Nästa förväntade aktivitet är att motta godset in {0} +cargo.routing.nextexpact.CLAIM=Nästa förväntade aktivitet är att upphämta godset i {0} +cargo.routing.nextexpact.CUSTOMS=Nästa förväntade aktivitet är att förtulla godset i {0} +cargo.routing.nextexpact.unknown=Nästa förväntade aktivitet är okänd + +cargo.admin.header=Godsadministration +cargo.admin.tablecaption=Allt gods +cargo.admin.tableheader.trackingid=Spårningsid +cargo.admin.tableheader.origin=Ursprung +cargo.admin.tableheader.destination=Destination +cargo.admin.tableheader.routed=Ruttplanerad +cargo.admin.tableheader.arrivaldeadline=Ankomstdeadline: +cargo.admin.details.caption=Detaljer för godset +cargo.admin.details.picknewdest=Ändra destination +cargo.admin.details.arrivaldeadline=Ankomstdeadline +cargo.admin.details.selectitinerary=Ruttplanera detta gods +cargo.admin.details.reroute=omplanera rutt för detta gods +cargo.admin.details.misrouted=Godsets rutt är felplanerad +cargo.admin.details.itinerary=Resplan +cargo.admin.details.voyageno=Resenummer +cargo.admin.details.load=Lasta +cargo.admin.details.unload=Lasta av +cargo.admin.newdest.change=Ändra destination för godset {0} +cargo.admin.newdest.currentdest=Nuvarande destination +cargo.admin.newdest.newdest=Ny destination +cargo.admin.newdest.submit=Ändra destination +cargo.admin.register.caption=Boka nytt gods +cargo.admin.register.book=Boka +cargo.admin.itinerary.caption=Välj rutt +cargo.admin.itinerary.summary=Godset {0} färdas från {1} till {2} +cargo.admin.itinerary.noroutecandidates=Inga rutter hittades som uppfyller ruttspecifikationen. Prova att välja en ankomstdeadline längre in i framtiden (åtminstone ett par veckor fram). +cargo.admin.itinerary.routecandidatecaption=Ruttkandidater {0} +cargo.admin.itinerary.voyage=Resa +cargo.admin.itinerary.submit=Tilldela rutten till godset + +misc.yes=Ja +misc.no=Nej +misc.from=Från +misc.to=Till + +error.required=Spårningsid:t får inte vara tomt +cargo.unknown_id=Okänt spårningsid \ No newline at end of file diff --git a/src/main/resources/templates/admin/list.html b/src/main/resources/templates/admin/list.html index 934f75f2b..04d116d1e 100644 --- a/src/main/resources/templates/admin/list.html +++ b/src/main/resources/templates/admin/list.html @@ -4,7 +4,7 @@ xmlns:th="http://www.thymeleaf.org"> - Cargo Administration + Cargo Administration @@ -13,13 +13,13 @@

- + - - - - + + + + @@ -30,7 +30,7 @@ - +
All cargosAll cargos
Tracking IDOriginDestinationRoutedTracking IDOriginDestinationRouted
Origin Final destinationRouted
diff --git a/src/main/resources/templates/admin/pickNewDestination.html b/src/main/resources/templates/admin/pickNewDestination.html index 92cfc426e..38b2b5d03 100644 --- a/src/main/resources/templates/admin/pickNewDestination.html +++ b/src/main/resources/templates/admin/pickNewDestination.html @@ -4,7 +4,7 @@ xmlns:th="http://www.thymeleaf.org"> - Cargo Administration + Cargo Administration