From 9f46b609eb6970c6e32f732e96ad1e199cfecad3 Mon Sep 17 00:00:00 2001 From: Olivier Maury <Olivier.Maury@inrae.fr> Date: Mon, 12 Feb 2024 17:45:12 +0100 Subject: [PATCH] =?UTF-8?q?Afficher=20les=20donn=C3=A9es=20d'une=20PRA=20e?= =?UTF-8?q?n=20cliquant=20sur=20la=20carte.=20fixes=20#19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/pmd-suppressions.properties | 2 + .../java/fr/agrometinfo/www/client/App.java | 14 +++ .../www/client/event/FeatureSelectEvent.java | 80 ++++++++++++++ .../client/event/FeatureSelectHandler.java | 13 +++ .../www/client/event/package-info.java | 4 + .../www/client/i18n/AppConstants.java | 6 ++ .../www/client/i18n/AppMessages.java | 23 +++- .../www/client/presenter/MapPresenter.java | 11 +- .../client/presenter/RightPanelPresenter.java | 42 ++++++-- .../www/client/view/LayoutView.java | 6 +- .../agrometinfo/www/client/view/MapView.java | 29 ++++- .../www/client/view/RightPanelView.java | 102 +++++++++++++++--- .../client/i18n/AppConstants_fr.properties | 1 + .../www/client/i18n/AppMessages_fr.properties | 3 + .../agrometinfo/www/client/public/style.css | 3 + .../www/server/dao/MonthlyValueDao.java | 15 ++- .../server/dao/MonthlyValueDaoHibernate.java | 29 ++++- .../www/server/dao/PraDailyValueDao.java | 22 ++++ .../server/dao/PraDailyValueDaoHibernate.java | 29 ++++- .../fr/agrometinfo/www/server/dao/PraDao.java | 6 ++ .../www/server/dao/PraDaoHibernate.java | 8 ++ .../www/server/rs/IndicatorResource.java | 53 +++++++-- .../dao/MonthlyValueDaoHibernateTest.java | 2 +- .../www/server/dao/PraDaoHibernateTest.java | 8 ++ .../www/server/rs/IndicatorResourceTest.java | 4 + www-shared/config/pmd-suppressions.properties | 2 + .../agrometinfo/www/shared/dto/ChoiceDTO.java | 51 ++++++--- .../www/shared/dto/FeatureLevel.java | 22 ++++ .../www/shared/dto/SimpleFeature.java | 63 +++++++++++ .../www/shared/dto/SummaryDTO.java | 66 ++++++++---- .../www/shared/service/IndicatorService.java | 12 ++- 31 files changed, 640 insertions(+), 91 deletions(-) create mode 100644 www-client/src/main/java/fr/agrometinfo/www/client/event/FeatureSelectEvent.java create mode 100644 www-client/src/main/java/fr/agrometinfo/www/client/event/FeatureSelectHandler.java create mode 100644 www-client/src/main/java/fr/agrometinfo/www/client/event/package-info.java create mode 100644 www-shared/src/main/java/fr/agrometinfo/www/shared/dto/FeatureLevel.java create mode 100644 www-shared/src/main/java/fr/agrometinfo/www/shared/dto/SimpleFeature.java diff --git a/config/pmd-suppressions.properties b/config/pmd-suppressions.properties index a842bcf..98b2c2e 100644 --- a/config/pmd-suppressions.properties +++ b/config/pmd-suppressions.properties @@ -9,6 +9,8 @@ fr.agrometinfo.www.shared.dto.IndicatorDTO_MapperImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.PeriodDTOBeanJsonDeserializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.PeriodDTOBeanJsonSerializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.PeriodDTO_MapperImpl=UnnecessaryImport +fr.agrometinfo.www.shared.dto.SimpleFeatureBeanJsonDeserializerImpl=UnnecessaryImport +fr.agrometinfo.www.shared.dto.SimpleFeatureBeanJsonSerializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.SummaryDTOBeanJsonDeserializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.SummaryDTOBeanJsonSerializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.SummaryDTO_MapperImpl=UnnecessaryImport diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/App.java b/www-client/src/main/java/fr/agrometinfo/www/client/App.java index f86a85a..52b5c38 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/App.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/App.java @@ -1,6 +1,9 @@ package fr.agrometinfo.www.client; import org.dominokit.rest.DominoRestConfig; +import org.gwtproject.event.shared.Event; +import org.gwtproject.event.shared.EventBus; +import org.gwtproject.event.shared.SimpleEventBus; import org.pepstock.charba.client.Charba; import com.google.gwt.core.client.EntryPoint; @@ -17,6 +20,17 @@ import fr.agrometinfo.www.client.presenter.LoginPresenter; * @author Olivier Maury */ public class App implements EntryPoint { + /** + * Dispatches {@link Event}s to interested parties. + */ + private static final EventBus EVENT_BUS = new SimpleEventBus(); + + /** + * @return {@link Event}s dispatcher. + */ + public static EventBus getEventBus() { + return EVENT_BUS; + } private boolean isLoggedIn() { // fake check diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/event/FeatureSelectEvent.java b/www-client/src/main/java/fr/agrometinfo/www/client/event/FeatureSelectEvent.java new file mode 100644 index 0000000..ac12ef8 --- /dev/null +++ b/www-client/src/main/java/fr/agrometinfo/www/client/event/FeatureSelectEvent.java @@ -0,0 +1,80 @@ +package fr.agrometinfo.www.client.event; + +import org.gwtproject.event.shared.Event; + +import fr.agrometinfo.www.shared.dto.FeatureLevel; + +/** + * Event when the user click on a geographic feature on the map. + * + * @author Olivier Maury + */ +public final class FeatureSelectEvent extends Event<FeatureSelectHandler> { + + /** + * Event type. + */ + public static final Type<FeatureSelectHandler> TYPE = new Type<>(); + + /** + * Builder. + * + * @param level Level of selected feature. + * @param id Id of selected feature. + * @return built event + */ + public static FeatureSelectEvent of(final FeatureLevel level, final String id) { + final FeatureSelectEvent event = new FeatureSelectEvent(); + event.setId(id); + event.setLevel(level); + return event; + } + + /** + * Id of selected feature. + */ + private String id; + + /** + * Level of selected feature. + */ + private FeatureLevel level; + + @Override + protected void dispatch(final FeatureSelectHandler handler) { + handler.onFeatureSelect(this); + } + + @Override + public Type<FeatureSelectHandler> getAssociatedType() { + return TYPE; + } + + /** + * @return Id of selected feature. + */ + public String getId() { + return id; + } + + /** + * @return Level of selected feature. + */ + public FeatureLevel getLevel() { + return level; + } + + /** + * @param value Id of selected feature. + */ + public void setId(final String value) { + this.id = value; + } + + /** + * @param value Level of selected feature. + */ + public void setLevel(final FeatureLevel value) { + this.level = value; + } +} diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/event/FeatureSelectHandler.java b/www-client/src/main/java/fr/agrometinfo/www/client/event/FeatureSelectHandler.java new file mode 100644 index 0000000..66f2910 --- /dev/null +++ b/www-client/src/main/java/fr/agrometinfo/www/client/event/FeatureSelectHandler.java @@ -0,0 +1,13 @@ +package fr.agrometinfo.www.client.event; + +/** + * Handler for {@link FeatureSelectEvent}. + * + * @author Olivier Maury + */ +public interface FeatureSelectHandler { + /** + * @param event event with feature selection + */ + void onFeatureSelect(FeatureSelectEvent event); +} diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/event/package-info.java b/www-client/src/main/java/fr/agrometinfo/www/client/event/package-info.java new file mode 100644 index 0000000..a753af3 --- /dev/null +++ b/www-client/src/main/java/fr/agrometinfo/www/client/event/package-info.java @@ -0,0 +1,4 @@ +/** + * {@link org.gwtproject.event.shared.Event} implementations for the event bus. + */ +package fr.agrometinfo.www.client.event; diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppConstants.java b/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppConstants.java index 8ccc4f6..1cc0025 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppConstants.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppConstants.java @@ -87,6 +87,12 @@ public interface AppConstants extends com.google.gwt.i18n.client.ConstantsWithLo @DefaultStringValue("Compare two maps") String comparisonMap(); + /** + * @return translation + */ + @DefaultStringValue("period 1990 − 2020") + String comparisonPeriod(); + /** * @return translation */ diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppMessages.java b/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppMessages.java index 17d5038..c9ba9ce 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppMessages.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppMessages.java @@ -27,6 +27,13 @@ public interface AppMessages extends Messages { @DefaultMessage("Average value for the indicator {0} ({1}) at {2} in {3}") String averageValue(String indicator, String period, String region, int year); + /** + * @param id cell id + * @return translation + */ + @DefaultMessage("Cell #{0}") + String cell(String id); + /** * @param indicator chosen indicator * @param period chosen period @@ -67,6 +74,20 @@ public interface AppMessages extends Messages { */ @DefaultMessage("{0} indicators.") @AlternateMessage({"=0", "No indicator.", // - "=1", "1 indicator."}) + "=1", "1 indicator."}) String nbOfIndicators(@PluralCount int nb); + + /** + * @param name + * @return translation + */ + @DefaultMessage("Petite Région Agricole \"{0}\"") + String pra(String name); + + /** + * @param name + * @return translation + */ + @DefaultMessage("Region \"{0}\"") + String region(String name); } diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/MapPresenter.java b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/MapPresenter.java index f8e380b..df4bc0b 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/MapPresenter.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/MapPresenter.java @@ -8,10 +8,13 @@ import org.geojson.FeatureCollection; import com.google.gwt.core.client.GWT; import elemental2.dom.HTMLDivElement; +import fr.agrometinfo.www.client.App; +import fr.agrometinfo.www.client.event.FeatureSelectEvent; import fr.agrometinfo.www.client.util.ApplicationUtils; import fr.agrometinfo.www.client.view.BaseView; import fr.agrometinfo.www.client.view.MapView; import fr.agrometinfo.www.shared.dto.ChoiceDTO; +import fr.agrometinfo.www.shared.dto.FeatureLevel; import fr.agrometinfo.www.shared.dto.IndicatorDTO; import fr.agrometinfo.www.shared.service.IndicatorService; @@ -66,14 +69,18 @@ public final class MapPresenter implements Presenter { if (choice.getPeriod() != null) { request.addQueryParam("period", choice.getPeriod()); } - if (choice.getRegion() != null) { - request.addQueryParam("region", choice.getRegion()); + if (choice.getFeatureId() != null) { + request.addQueryParam("region", choice.getFeatureId()); } request.addQueryParam("year", String.valueOf(choice.getYear())); request.addQueryParam("comparison", String.valueOf(choice.getComparison())); request.onSuccess(response -> view.setGeoJson(response.getBodyAsString(), indicator)).send(); } + public void onFeatureSelect(final String id) { + App.getEventBus().fireEvent(FeatureSelectEvent.of(FeatureLevel.PRA, id)); + } + /** * @param mapContainer container for the map */ diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/RightPanelPresenter.java b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/RightPanelPresenter.java index e472bc7..ebc372a 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/RightPanelPresenter.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/RightPanelPresenter.java @@ -6,6 +6,9 @@ import com.google.gwt.core.client.GWT; import elemental2.dom.DomGlobal; import elemental2.dom.HTMLElement; +import fr.agrometinfo.www.client.App; +import fr.agrometinfo.www.client.event.FeatureSelectEvent; +import fr.agrometinfo.www.client.event.FeatureSelectHandler; import fr.agrometinfo.www.client.view.BaseView; import fr.agrometinfo.www.client.view.LayoutView; import fr.agrometinfo.www.client.view.RightPanelView; @@ -19,7 +22,7 @@ import fr.agrometinfo.www.shared.service.IndicatorServiceFactory; * * @author Olivier Maury */ -public final class RightPanelPresenter implements Presenter { +public final class RightPanelPresenter implements FeatureSelectHandler, Presenter { /** * Related view interface. */ @@ -47,6 +50,11 @@ public final class RightPanelPresenter implements Presenter { void show(); } + /** + * Last choice. + */ + private ChoiceDTO currentChoice; + /** * Related view. */ @@ -65,18 +73,13 @@ public final class RightPanelPresenter implements Presenter { /** * Load indicator values on the panel. * - * @param choice user choice for the indicator values + * @param c user choice for the indicator values */ - public void loadValues(final ChoiceDTO choice) { - GWT.log("RightPanelPresenter.loadValues() " + choice); - Integer regionId; - try { - regionId = Integer.valueOf(choice.getRegion()); - } catch (final NumberFormatException e) { - regionId = null; - } + public void loadValues(final ChoiceDTO c) { + GWT.log("RightPanelPresenter.loadValues() " + c); + currentChoice = c; IndicatorServiceFactory.INSTANCE - .getSummary(choice.getIndicator(), choice.getPeriod(), regionId, choice.getYear()) // + .getSummary(c.getIndicator(), c.getPeriod(), c.getLevel(), c.getFeatureId(), c.getYear()) // .onSuccess(view::setSummary)// .onFailed(layoutView::failureNotification)// .send(); @@ -86,6 +89,22 @@ public final class RightPanelPresenter implements Presenter { } } + @Override + public void onFeatureSelect(final FeatureSelectEvent event) { + if (currentChoice == null) { + return; + } + final ChoiceDTO choice = new ChoiceDTO(); + choice.setComparison(currentChoice.getComparison()); + choice.setIndicator(currentChoice.getIndicator()); + choice.setPeriod(currentChoice.getPeriod()); + choice.setFeatureId(event.getId()); + choice.setLevel(event.getLevel()); + choice.setYear(currentChoice.getYear()); + loadValues(choice); + view.show(); + } + /** * @param mapContainer container for the map */ @@ -103,6 +122,7 @@ public final class RightPanelPresenter implements Presenter { @Override public void start() { GWT.log("RightPanelPresenter.start()"); + App.getEventBus().addHandler(FeatureSelectEvent.TYPE, this); view = new RightPanelView(layoutView, container); view.setPresenter(this); view.init(); diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/view/LayoutView.java b/www-client/src/main/java/fr/agrometinfo/www/client/view/LayoutView.java index 8c172b6..1da2a22 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/view/LayoutView.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/view/LayoutView.java @@ -53,6 +53,7 @@ import fr.agrometinfo.www.client.presenter.RightPanelPresenter; import fr.agrometinfo.www.client.ui.AgroclimAppsMenu; import fr.agrometinfo.www.client.ui.HTMLSelectElementBuilder; import fr.agrometinfo.www.shared.dto.ChoiceDTO; +import fr.agrometinfo.www.shared.dto.FeatureLevel; import fr.agrometinfo.www.shared.dto.IndicatorDTO; import fr.agrometinfo.www.shared.dto.PeriodDTO; @@ -203,6 +204,7 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen public void init() { GWT.log("initLayout()"); DomGlobal.console.info("initLayout()"); + choice.setLevel(FeatureLevel.REGION); layout = Layout.create("AgroMetInfo").show(); final EmptyContentBuilder<HTMLImageElement> logoElem = Elements.img("app/img/logo_etat-agrometinfo.svg"); layout.setLogo(logoElem); @@ -432,9 +434,9 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen private void onRegionChange(final String newValue) { if (newValue.length() > 2) { - choice.setRegion(null); + choice.setFeatureId(null); } else { - choice.setRegion(newValue); + choice.setFeatureId(newValue); } onChoiceChange(); } diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/view/MapView.java b/www-client/src/main/java/fr/agrometinfo/www/client/view/MapView.java index a8790e8..883662f 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/view/MapView.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/view/MapView.java @@ -32,8 +32,11 @@ import ol.OLFactory; import ol.View; import ol.ViewOptions; import ol.color.Color; +import ol.events.condition.Condition; import ol.format.GeoJson; import ol.format.GeoJsonFeatureOptions; +import ol.interaction.Select; +import ol.interaction.SelectOptions; import ol.layer.Base; import ol.layer.Group; import ol.layer.LayerGroupOptions; @@ -240,11 +243,27 @@ public final class MapView extends HtmlContentBuilder<HTMLElement> implements Ma super(element.element()); } + /** + * Mouse click interaction to select a cell. + */ + private void addClickInteractions() { + final SelectOptions selectOptions = new SelectOptions(); + selectOptions.setCondition(Condition.getClick()); + selectOptions.setMulti(false); + final Style style = createCellStyle(Color.getColorFromString("blue"), new Color(255, 0, 0, 0.5f)); + selectOptions.setStyle((f, r) -> new Style[] {style}); + + // create a select interaction + final Select selectFeature = new Select(selectOptions); + map.addInteraction(selectFeature); + + selectFeature.on("select", event -> onFeatureClick(selectFeature.getFeatures())); + } + private Feature[] colorizeFeatures(final Feature[] features) { for (final Feature f : features) { final Double value = getValue(f); final String color = "#" + ColorSequenceManager.getColorForValue(colorIntervals, value); - // GWT.log("Feature #" + f.getId() + ", value=" + value + ", color=" + color); final Color foreground = Color.getColorFromString(color); final Style style = createCellStyle(foreground, foreground); f.setStyle(style); @@ -298,6 +317,14 @@ public final class MapView extends HtmlContentBuilder<HTMLElement> implements Ma // add some interactions removeContextMenuRightClick(); + addClickInteractions(); + } + + private void onFeatureClick(final Collection<Feature> features) { + if (features == null || features.isEmpty()) { + return; + } + this.getPresenter().onFeatureSelect(features.item(0).getId()); } /** diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/view/RightPanelView.java b/www-client/src/main/java/fr/agrometinfo/www/client/view/RightPanelView.java index 9184a0e..c571611 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/view/RightPanelView.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/view/RightPanelView.java @@ -8,6 +8,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.dominokit.domino.ui.button.Button; import org.dominokit.domino.ui.cards.Card; import org.dominokit.domino.ui.grid.Column; import org.dominokit.domino.ui.grid.Row; @@ -15,7 +16,9 @@ import org.dominokit.domino.ui.icons.Icons; import org.dominokit.domino.ui.notifications.Notification; import org.dominokit.domino.ui.utils.DominoElement; import org.dominokit.domino.ui.utils.TextNode; +import org.jboss.elemento.Elements; import org.jboss.elemento.EventType; +import org.jboss.elemento.HtmlContentBuilder; import org.pepstock.charba.client.AbstractChart; import org.pepstock.charba.client.BarChart; import org.pepstock.charba.client.IsChart; @@ -44,9 +47,12 @@ import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat; import com.google.gwt.i18n.client.NumberFormat; +import elemental2.dom.EventListener; import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; +import elemental2.dom.HTMLHeadingElement; import elemental2.dom.Node; +import fr.agrometinfo.www.client.event.FeatureSelectEvent; import fr.agrometinfo.www.client.i18n.AppConstants; import fr.agrometinfo.www.client.i18n.AppMessages; import fr.agrometinfo.www.client.presenter.RightPanelPresenter; @@ -137,14 +143,19 @@ public final class RightPanelView implements RightPanelPresenter.View { private final Card averageCard = Card.create(); /** - * Container for bar chart displaying monthly values. + * Back link. */ - private final DominoElement<HTMLDivElement> barChartContainer = DominoElement.div(); + private final Button backBtn = Button.create(Icons.ALL.arrow_back()); /** - * Container for bar chart displaying daily values. + * Event listener for click on {@link RightPanelView#backBtn}. */ - private final DominoElement<HTMLDivElement> lineChartContainer = DominoElement.div(); + private EventListener backBtnClickListener = null; + + /** + * Container for bar chart displaying monthly values. + */ + private final DominoElement<HTMLDivElement> barChartContainer = DominoElement.div(); /** * Card for the daily comparison value for the user choice. @@ -156,16 +167,30 @@ public final class RightPanelView implements RightPanelPresenter.View { */ private final DominoElement<HTMLElement> container; + /** + * Panel header. + */ + private final HtmlContentBuilder<HTMLHeadingElement> header = Elements.h(3); + /** * Layout handling the panel. */ private final LayoutView layoutView; + /** + * Container for bar chart displaying daily values. + */ + private final DominoElement<HTMLDivElement> lineChartContainer = DominoElement.div(); + + /** + * Related presenter. + */ + private RightPanelPresenter presenter; + /** * Values according to user's choice. */ private SummaryDTO summary; - /** * Constructor. * @@ -176,6 +201,7 @@ public final class RightPanelView implements RightPanelPresenter.View { layoutView = view; container = div; } + private void createBarChart(final Map<String, Float> monthlyValues) { GWT.log("RightPanelView.createBarChart() " + monthlyValues.size()); final BarChart chart = new BarChart(); @@ -258,12 +284,21 @@ public final class RightPanelView implements RightPanelPresenter.View { @Override public void init() { - container.add(a() // - .on(EventType.click, e -> hide()) // - .add(Icons.CONTENT_ICONS.clear().clickable())); + backBtn.style().setDisplay("none"); + + container.add(DominoElement.div() // + .add(backBtn)// + .add(a() // + .on(EventType.click, e -> hide()) // + .css("float-right") // + .add(Icons.CONTENT_ICONS.clear().clickable())) // + ); + + container.add(header); averageCard.addHeaderAction(Icons.ACTION_ICONS.info_outline(), e -> this.showDescription(false)); comparisonCard.addHeaderAction(Icons.ACTION_ICONS.info_outline(), e -> this.showDescription(true)); + comparisonCard.setDescription(CSTS.comparisonPeriod()); container.add(Row.create() // .addColumn(Column.span6().add(averageCard)) // @@ -279,30 +314,67 @@ public final class RightPanelView implements RightPanelPresenter.View { @Override public void setPresenter(final RightPanelPresenter p) { - // Do nothing + presenter = p; } @Override public void setSummary(final SummaryDTO data) { GWT.log("RightPanelView.setSummary()"); summary = data; - String region = data.getRegion(); - if (region == null || region.isEmpty()) { - region = CSTS.metropolitanFrance(); + + final String featureName = data.getFeatureName(); + final String title; + if (featureName == null || featureName.isEmpty()) { + title = CSTS.metropolitanFrance(); + } else { + switch (data.getChoice().getLevel()) { + case CELL: + title = MSGS.cell(featureName); + break; + case PRA: + title = MSGS.pra(featureName); + break; + case REGION: + title = MSGS.region(featureName); + break; + default: + throw new UnsupportedOperationException("Level not handled: " + data.getChoice().getLevel()); + + } + } + if (data.getParentFeature() != null) { + backBtn.getTextSpan().textContent(data.getParentFeature().getName()); + if (backBtnClickListener != null) { + backBtn.removeEventListener(EventType.click, backBtnClickListener); + } + backBtnClickListener = e -> { + final FeatureSelectEvent event = new FeatureSelectEvent(); + event.setId(data.getParentFeature().getId()); + event.setLevel(data.getParentFeature().getLevel()); + presenter.onFeatureSelect(event); + }; + backBtn.addClickListener(backBtnClickListener); + backBtn.style().setDisplay("inline-block"); + } else { + backBtn.style().setDisplay("none"); } + final NumberFormat nf = NumberFormat.getFormat("0.#"); final DateTimeFormat df = DateTimeFormat.getFormat(PredefinedFormat.DATE_MEDIUM); + header.element().innerHTML = ""; + header.add(title); + header.add(Elements.br()); + header.add(Elements.small(df.format(data.getDate()))); + final IndicatorDTO indicator = data.getIndicator(); // Average averageCard.setTitle(indicator.getDescription()); - averageCard.setDescription(df.format(data.getDate())); averageCard.getBody().clearElement(); averageCard.getBody().appendChild(TextNode.of(nf.format(data.getAverageValue()) + " " + indicator.getUnit())); // Comparison comparisonCard.setTitle(CSTS.normalComparison()); - comparisonCard.setDescription(df.format(data.getDate())); comparisonCard.getBody().clearElement(); comparisonCard.getBody() .appendChild(TextNode.of(nf.format(data.getComparedValue()) + " " + indicator.getUnit())); @@ -319,7 +391,7 @@ public final class RightPanelView implements RightPanelPresenter.View { private void showDescription(final boolean comparison) { final IndicatorDTO indicator = summary.getIndicator(); - String region = summary.getRegion(); + String region = summary.getFeatureName(); if (region == null) { region = CSTS.metropolitanFrance(); } diff --git a/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppConstants_fr.properties b/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppConstants_fr.properties index 319a98a..06f764d 100644 --- a/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppConstants_fr.properties +++ b/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppConstants_fr.properties @@ -12,6 +12,7 @@ chooseRegion= Choisir une région chooseYear= Choisir une année close = Fermer comparisonMap = Carte comparative +comparisonPeriod = Période 1990 − 2020 contactDataGathering = Les informations recueillies à partir de ce formulaire sont nécessaires au traitement de votre message par l’équipe d’AgroMetInfo. contactEmailField= Adresse courriel contactMessageField= Votre message diff --git a/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppMessages_fr.properties b/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppMessages_fr.properties index bec7c84..67b0d6f 100644 --- a/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppMessages_fr.properties +++ b/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppMessages_fr.properties @@ -1,6 +1,7 @@ # Ce fichier est encodé en UTF-8. account = Compte de {0} ({1}) averageValue = Valeur moyenne de l’indicateur {0} ({1}) en {2} sur {3} +cell = Maille n°{0} comparedValue = Écart moyen de la valeur de l’indicateur {0} ({1}) en {2} sur {3} failureStatusCode = Code d’état HTTP : {0} nbOfIndicatorPeriods[\=0] = Aucune période. @@ -11,3 +12,5 @@ nbOfIndicators[\=0] = Aucun indicateur. nbOfIndicators[\=1] = Un indicateur. nbOfIndicators[one] = Un indicateur. nbOfIndicators = {0} indicateurs. +pra = Petite région agricole «\u00A0{0}\u00A0» +region = Région «\u00A0{0}\u00A0» diff --git a/www-client/src/main/resources/fr/agrometinfo/www/client/public/style.css b/www-client/src/main/resources/fr/agrometinfo/www/client/public/style.css index f15f686..0de56fb 100644 --- a/www-client/src/main/resources/fr/agrometinfo/www/client/public/style.css +++ b/www-client/src/main/resources/fr/agrometinfo/www/client/public/style.css @@ -107,6 +107,9 @@ select { padding-bottom: 6px; padding-top: 6px; } +.float-right { + float: right; +} div.idp { padding: 0.5em; } diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/MonthlyValueDao.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/MonthlyValueDao.java index 3ca7b5f..0fdbd0f 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/MonthlyValueDao.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/MonthlyValueDao.java @@ -5,6 +5,7 @@ import java.util.List; import fr.agrometinfo.www.server.model.Indicator; import fr.agrometinfo.www.server.model.MonthlyValue; +import fr.agrometinfo.www.server.model.Pra; import fr.agrometinfo.www.server.model.Region; /** @@ -22,13 +23,23 @@ public interface MonthlyValueDao { */ List<MonthlyValue> find(Indicator indicator, LocalDate date); + /** + * Last 12 monthly values for the indicator and all cells of a PRA. + * + * @param indicator indicator + * @param date date for the value last date + * @param pra PRA + * @return values + */ + List<MonthlyValue> find(Indicator indicator, LocalDate date, Pra pra); + /** * Last 12 monthly values for the indicator and all cells of a region. * * @param indicator indicator - * @param region region * @param date date for the value last date + * @param region region * @return values */ - List<MonthlyValue> find(Indicator indicator, Region region, LocalDate date); + List<MonthlyValue> find(Indicator indicator, LocalDate date, Region region); } diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/MonthlyValueDaoHibernate.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/MonthlyValueDaoHibernate.java index 54c3632..b6ebd90 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/MonthlyValueDaoHibernate.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/MonthlyValueDaoHibernate.java @@ -6,6 +6,7 @@ import java.util.Map; import fr.agrometinfo.www.server.model.Indicator; import fr.agrometinfo.www.server.model.MonthlyValue; +import fr.agrometinfo.www.server.model.Pra; import fr.agrometinfo.www.server.model.Region; import jakarta.enterprise.context.ApplicationScoped; @@ -43,23 +44,43 @@ public class MonthlyValueDaoHibernate extends DaoHibernate<MonthlyValue> impleme } @Override - public final List<MonthlyValue> find(final Indicator indicator, final Region region, final LocalDate date) { + public final List<MonthlyValue> find(final Indicator indicator, final LocalDate date, final Pra pra) { final var jpql = """ SELECT new fr.agrometinfo.www.server.model.MonthlyValue( EXTRACT(YEAR FROM t.date) AS year, EXTRACT(MONTH FROM t.date) AS month, """ + indicator.getAggregationType() + """ (t.computedValue) AS value) - FROM DailyValue AS t + FROM PraDailyValue AS t WHERE t.indicator=:indicator AND t.date BETWEEN :startdate AND :enddate AND - t.cell.department.region=:region AND + t.pra=:pra AND t.computedValue IS NOT NULL GROUP BY year, month ORDER BY year ASC, month ASC"""; return super.findAllByJPQL(jpql, - Map.of("indicator", indicator, "startdate", date.minusYears(1), "enddate", date, "region", region), + Map.of("indicator", indicator, "startdate", date.minusYears(1), "enddate", date, "pra", pra), MonthlyValue.class); } + @Override + public final List<MonthlyValue> find(final Indicator indicator, final LocalDate date, final Region region) { + final var jpql = """ + SELECT new fr.agrometinfo.www.server.model.MonthlyValue( + EXTRACT(YEAR FROM t.date) AS year, + EXTRACT(MONTH FROM t.date) AS month, + """ + indicator.getAggregationType() + """ + (t.computedValue) AS value) + FROM DailyValue AS t + WHERE t.indicator=:indicator AND + t.date BETWEEN :startdate AND :enddate AND + t.cell.department.region=:region AND + t.computedValue IS NOT NULL + GROUP BY year, month + ORDER BY year ASC, month ASC"""; + return super.findAllByJPQL(jpql, + Map.of("indicator", indicator, "startdate", date.minusYears(1), "enddate", date, "region", region), + MonthlyValue.class); + } + } diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDao.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDao.java index cfb65a0..f83e54d 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDao.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDao.java @@ -6,6 +6,7 @@ import java.util.Map; import fr.agrometinfo.www.server.model.DailyValue; import fr.agrometinfo.www.server.model.Indicator; +import fr.agrometinfo.www.server.model.Pra; import fr.agrometinfo.www.server.model.PraDailyValue; import fr.agrometinfo.www.server.model.Region; @@ -25,6 +26,16 @@ public interface PraDailyValueDao { */ List<PraDailyValue> find(Indicator indicator, LocalDate date); + /** + * Value for the indicator, the day and the PRA. + * + * @param indicator indicator + * @param date date for the value + * @param pra PRA + * @return value + */ + PraDailyValue find(Indicator indicator, LocalDate date, Pra pra); + /** * Values for the indicator, the day and all PRAs of a region. * @@ -85,6 +96,17 @@ public interface PraDailyValueDao { */ Map<LocalDate, Float> findDailyValues(Indicator indicator, LocalDate start, LocalDate end); + /** + * Daily values for the indicator between 2 dates for a PRA. + * + * @param indicator indicator + * @param start period start + * @param end period end + * @param pra related PRA + * @return values + */ + Map<LocalDate, Float> findDailyValues(Indicator indicator, LocalDate start, LocalDate end, Pra pra); + /** * Daily values for the indicator between 2 dates for a region. * diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDaoHibernate.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDaoHibernate.java index bf92ef4..defb112 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDaoHibernate.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDailyValueDaoHibernate.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.stream.Collectors; import fr.agrometinfo.www.server.model.Indicator; +import fr.agrometinfo.www.server.model.Pra; import fr.agrometinfo.www.server.model.PraDailyValue; import fr.agrometinfo.www.server.model.Region; import jakarta.enterprise.context.ApplicationScoped; @@ -33,6 +34,12 @@ public class PraDailyValueDaoHibernate extends DaoHibernate<PraDailyValue> imple return super.findAllByJPQL(jpql, Map.of("indicator", indicator, "date", date), PraDailyValue.class); } + @Override + public final PraDailyValue find(final Indicator indicator, final LocalDate date, final Pra pra) { + final var jpql = "SELECT t FROM PraDailyValue t WHERE t.indicator=:indicator AND t.date=:date AND t.pra=:pra"; + return super.findOneByJPQL(jpql, Map.of("indicator", indicator, "date", date, "pra", pra), PraDailyValue.class); + } + @Override public final List<PraDailyValue> find(final Indicator indicator, final Region region, final LocalDate date) { final var jpql = """ @@ -73,8 +80,8 @@ public class PraDailyValueDaoHibernate extends DaoHibernate<PraDailyValue> imple } @Override - public final Double findAverageComputedValue(final Indicator indicator, final LocalDate date, - final Integer regionId) { + public final Double findAverageComputedValue(final Indicator indicator, + final LocalDate date, final Integer regionId) { final var jpql = """ SELECT AVG(t.computedValue) FROM PraDailyValue AS t @@ -101,6 +108,24 @@ public class PraDailyValueDaoHibernate extends DaoHibernate<PraDailyValue> imple return findDailyValues(jpql, params); } + @Override + public final Map<LocalDate, Float> findDailyValues(final Indicator indicator, final LocalDate start, + final LocalDate end, final Pra pra) { + final var jpql = """ + SELECT t.date AS date, AVG(t.computedValue) AS value + FROM PraDailyValue AS t + WHERE t.indicator=:indicator AND t.date BETWEEN :start AND :end AND t.pra=:pra + GROUP BY t.date + ORDER BY t.date ASC + """; + final Map<String, Object> params = Map.of(// + "indicator", indicator, // + "pra", pra, // + "start", start, // + "end", end); + return findDailyValues(jpql, params); + } + @Override public final Map<LocalDate, Float> findDailyValues(final Indicator indicator, final LocalDate start, final LocalDate end, final Region region) { diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDao.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDao.java index d50f658..5351112 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDao.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDao.java @@ -20,4 +20,10 @@ public interface PraDao { * @return all PRAs */ List<Pra> findAll(); + + /** + * @param code PRA code + * @return found PRA + */ + Pra findByCode(String code); } diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDaoHibernate.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDaoHibernate.java index 48ed4f9..52d56de 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDaoHibernate.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/PraDaoHibernate.java @@ -1,5 +1,7 @@ package fr.agrometinfo.www.server.dao; +import java.util.Map; + import fr.agrometinfo.www.server.model.Pra; import jakarta.enterprise.context.ApplicationScoped; @@ -18,4 +20,10 @@ public class PraDaoHibernate extends DaoHibernate<Pra> implements PraDao { super(Pra.class); } + @Override + public final Pra findByCode(final String code) { + final var jpql = "SELECT t FROM Pra t WHERE t.code=:code"; + return super.findOneByJPQL(jpql, Map.of("code", code), Pra.class); + } + } diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java b/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java index 6441181..0003b7d 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java @@ -21,17 +21,21 @@ import fr.agrometinfo.www.server.dao.CellDao; import fr.agrometinfo.www.server.dao.IndicatorDao; import fr.agrometinfo.www.server.dao.MonthlyValueDao; import fr.agrometinfo.www.server.dao.PraDailyValueDao; +import fr.agrometinfo.www.server.dao.PraDao; import fr.agrometinfo.www.server.dao.RegionDao; import fr.agrometinfo.www.server.model.Indicator; import fr.agrometinfo.www.server.model.MonthlyValue; +import fr.agrometinfo.www.server.model.Pra; import fr.agrometinfo.www.server.model.PraDailyValue; import fr.agrometinfo.www.server.model.Region; import fr.agrometinfo.www.server.util.DateUtils; import fr.agrometinfo.www.server.util.LocaleUtils; import fr.agrometinfo.www.shared.dto.ChoiceDTO; import fr.agrometinfo.www.shared.dto.ErrorResponseDTO; +import fr.agrometinfo.www.shared.dto.FeatureLevel; import fr.agrometinfo.www.shared.dto.IndicatorDTO; import fr.agrometinfo.www.shared.dto.PeriodDTO; +import fr.agrometinfo.www.shared.dto.SimpleFeature; import fr.agrometinfo.www.shared.dto.SummaryDTO; import fr.agrometinfo.www.shared.service.IndicatorService; import jakarta.annotation.PostConstruct; @@ -139,6 +143,12 @@ public class IndicatorResource implements IndicatorService { @Inject private MonthlyValueDao monthlyValueDao; + /** + * DAO for {@link Pra}. + */ + @Inject + private PraDao praDao; + /** * DAO for {@link Region}. */ @@ -215,7 +225,8 @@ public class IndicatorResource implements IndicatorService { @Produces(MediaType.APPLICATION_JSON) @Override public SummaryDTO getSummary(@QueryParam(value = "indicator") final String indicatorUid, - @QueryParam(value = "period") final String periodCode, @QueryParam(value = "region") final Integer regionId, + @QueryParam(value = "period") final String periodCode, + @QueryParam(value = "level") final FeatureLevel level, @QueryParam(value = "id") final String id, @QueryParam(value = "year") final Integer year) { checkRequired(indicatorUid, "indicator"); checkRequired(periodCode, "period"); @@ -242,26 +253,49 @@ public class IndicatorResource implements IndicatorService { final Map<Date, Float> dailyValues = new TreeMap<>(); final Map<String, Float> monthlyValues; final LocalDate yearAgo = date.minusYears(1); - final Region region; + final SimpleFeature parentFeature; + final String featureName; + Integer regionId; + try { + regionId = Integer.valueOf(id); + } catch (final NumberFormatException e) { + regionId = null; + } if (regionId == null) { - region = null; + featureName = null; averageValue = praDailyValueDao.findAverageComputedValue(indicator, date); comparedValue = praDailyValueDao.findAverageComparedValue(indicator, date); tmpDailyValues = praDailyValueDao.findDailyValues(indicator, yearAgo, date); monthlyValues = toMonthlyValues(monthlyValueDao.find(indicator, date), i18n); + parentFeature = null; + } else if (level == FeatureLevel.PRA) { + final Pra pra = praDao.findByCode(id); + final PraDailyValue value = praDailyValueDao.find(indicator, date, pra); + averageValue = value.getComputedValue().doubleValue(); + comparedValue = value.getComparedValue().doubleValue(); + tmpDailyValues = praDailyValueDao.findDailyValues(indicator, yearAgo, date, pra); + monthlyValues = toMonthlyValues(monthlyValueDao.find(indicator, date, pra), i18n); + featureName = pra.getName(); + parentFeature = new SimpleFeature(); + parentFeature.setId(String.valueOf(pra.getDepartment().getRegion().getId())); + parentFeature.setLevel(FeatureLevel.REGION); + parentFeature.setName(pra.getDepartment().getRegion().getName()); } else { - region = regionDao.find(regionId); + final Region region = regionDao.find(regionId); averageValue = praDailyValueDao.findAverageComputedValue(indicator, date, regionId); comparedValue = praDailyValueDao.findAverageComparedValue(indicator, date, regionId); tmpDailyValues = praDailyValueDao.findDailyValues(indicator, yearAgo, date, region); - monthlyValues = toMonthlyValues(monthlyValueDao.find(indicator, region, date), i18n); + monthlyValues = toMonthlyValues(monthlyValueDao.find(indicator, date, region), i18n); + featureName = region.getName(); + parentFeature = null; } tmpDailyValues.forEach((d, v) -> dailyValues.put(DateUtils.toDate(d), v)); final var choice = new ChoiceDTO(); choice.setIndicator(indicatorUid); + choice.setLevel(level); choice.setPeriod(periodCode); - choice.setRegion(String.valueOf(regionId)); + choice.setFeatureId(String.valueOf(regionId)); choice.setYear(year); final var dto = new SummaryDTO(); if (averageValue != null) { @@ -273,12 +307,13 @@ public class IndicatorResource implements IndicatorService { } dto.setDate(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant())); dto.setDailyValues(dailyValues); + if (featureName != null) { + dto.setFeatureName(featureName); + } dto.setIndicator(toDTO(indicator, locale)); dto.setMonthlyValues(monthlyValues); + dto.setParentFeature(parentFeature); dto.setPeriod(getTranslation(indicator.getPeriod().getNames(), locale)); - if (region != null) { - dto.setRegion(region.getName()); - } return dto; } diff --git a/www-server/src/test/java/fr/agrometinfo/www/server/dao/MonthlyValueDaoHibernateTest.java b/www-server/src/test/java/fr/agrometinfo/www/server/dao/MonthlyValueDaoHibernateTest.java index 9305203..3056f0b 100644 --- a/www-server/src/test/java/fr/agrometinfo/www/server/dao/MonthlyValueDaoHibernateTest.java +++ b/www-server/src/test/java/fr/agrometinfo/www/server/dao/MonthlyValueDaoHibernateTest.java @@ -31,7 +31,7 @@ class MonthlyValueDaoHibernateTest { final var indicator = indicatorDao.findByCodeAndPeriod("rainsum", "year"); final var date = dailyValueDao.findLastDate(indicator, 2023); final var region = dailyValueDao.findRegions().get(0); - final var actual = dao.find(indicator, region, date); + final var actual = dao.find(indicator, date, region); assertNotNull(actual); assertEquals(1, actual.size()); final Float expected = 22.F; diff --git a/www-server/src/test/java/fr/agrometinfo/www/server/dao/PraDaoHibernateTest.java b/www-server/src/test/java/fr/agrometinfo/www/server/dao/PraDaoHibernateTest.java index d295365..6eaac6a 100644 --- a/www-server/src/test/java/fr/agrometinfo/www/server/dao/PraDaoHibernateTest.java +++ b/www-server/src/test/java/fr/agrometinfo/www/server/dao/PraDaoHibernateTest.java @@ -39,4 +39,12 @@ public class PraDaoHibernateTest { final int expected = 42; assertEquals(expected, first.getCoordinates().length); } + + @Test + void findByCode() { + final var code = "01195"; + final var actual = dao.findByCode(code); + assertNotNull(actual); + assertEquals(code, actual.getCode()); + } } diff --git a/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java b/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java index daa30b0..9df22fa 100644 --- a/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java +++ b/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java @@ -17,6 +17,8 @@ import fr.agrometinfo.www.server.dao.MonthlyValueDao; import fr.agrometinfo.www.server.dao.MonthlyValueDaoHibernate; import fr.agrometinfo.www.server.dao.PraDailyValueDao; import fr.agrometinfo.www.server.dao.PraDailyValueDaoHibernate; +import fr.agrometinfo.www.server.dao.PraDao; +import fr.agrometinfo.www.server.dao.PraDaoHibernate; import fr.agrometinfo.www.server.dao.RegionDao; import fr.agrometinfo.www.server.dao.RegionDaoHibernate; import jakarta.ws.rs.core.Application; @@ -38,6 +40,7 @@ class IndicatorResourceTest extends JerseyTest { protected final Application configure() { final CellDao cellDao = new CellDaoHibernate(); final PraDailyValueDao praDailyValueDao = new PraDailyValueDaoHibernate(); + final PraDao praDao = new PraDaoHibernate(); final IndicatorDao indicatorDao = new IndicatorDaoHibernate(); final MonthlyValueDao monthlyValueDao = new MonthlyValueDaoHibernate(); final RegionDao regionDao = new RegionDaoHibernate(); @@ -46,6 +49,7 @@ class IndicatorResourceTest extends JerseyTest { public void configure() { bind(cellDao).to(CellDao.class); bind(praDailyValueDao).to(PraDailyValueDao.class); + bind(praDao).to(PraDao.class); bind(indicatorDao).to(IndicatorDao.class); bind(monthlyValueDao).to(MonthlyValueDao.class); bind(regionDao).to(RegionDao.class); diff --git a/www-shared/config/pmd-suppressions.properties b/www-shared/config/pmd-suppressions.properties index 86faec2..0864a4a 100644 --- a/www-shared/config/pmd-suppressions.properties +++ b/www-shared/config/pmd-suppressions.properties @@ -9,6 +9,8 @@ fr.agrometinfo.www.shared.dto.IndicatorDTO_MapperImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.PeriodDTOBeanJsonDeserializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.PeriodDTOBeanJsonSerializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.PeriodDTO_MapperImpl=UnnecessaryImport +fr.agrometinfo.www.shared.dto.SimpleFeatureBeanJsonDeserializerImpl=UnnecessaryImport +fr.agrometinfo.www.shared.dto.SimpleFeatureBeanJsonSerializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.SummaryDTOBeanJsonDeserializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.SummaryDTOBeanJsonSerializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.SummaryDTO_MapperImpl=UnnecessaryImport diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ChoiceDTO.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ChoiceDTO.java index 0794bbc..b35993c 100644 --- a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ChoiceDTO.java +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ChoiceDTO.java @@ -28,9 +28,14 @@ public final class ChoiceDTO { private String period; /** - * Chosen region. + * ID of chosen feature (region in left panel, PRA on map). */ - private String region; + private String featureId; + + /** + * Level of chosen feature (region in left panel or PRA on map). + */ + private FeatureLevel level; /** * Chosen year. @@ -44,6 +49,13 @@ public final class ChoiceDTO { return Boolean.TRUE.equals(comparison); } + /** + * @return Id of chosen feature + */ + public String getFeatureId() { + return featureId; + } + /** * @return ID of chosen indicator. */ @@ -52,17 +64,17 @@ public final class ChoiceDTO { } /** - * @return Period code of chosen indicator. + * @return Level of chosen feature (region in left panel or PRA on map). */ - public String getPeriod() { - return period; + public FeatureLevel getLevel() { + return level; } /** - * @return Chosen region. + * @return Period code of chosen indicator. */ - public String getRegion() { - return region; + public String getPeriod() { + return period; } /** @@ -89,6 +101,13 @@ public final class ChoiceDTO { this.comparison = value; } + /** + * @param value ID of chosen feature (region in left panel or PRA on map). + */ + public void setFeatureId(final String value) { + this.featureId = value; + } + /** * @param value ID of chosen indicator. */ @@ -97,17 +116,17 @@ public final class ChoiceDTO { } /** - * @param value Period code of chosen indicator. + * @param value Level of chosen feature (region in left panel or PRA on map). */ - public void setPeriod(final String value) { - this.period = value; + public void setLevel(final FeatureLevel value) { + this.level = value; } /** - * @param value Chosen region. + * @param value Period code of chosen indicator. */ - public void setRegion(final String value) { - this.region = value; + public void setPeriod(final String value) { + this.period = value; } /** @@ -119,8 +138,8 @@ public final class ChoiceDTO { @Override public String toString() { - return "ChoiceDTO [comparison=" + comparison + ", indicator=" + indicator + ", period=" + period + ", region=" - + region + ", year=" + year + "]"; + return "ChoiceDTO [comparison=" + comparison + ", indicator=" + indicator + ", period=" + period + + ", featureId=" + featureId + ", level=" + level + ", year=" + year + "]"; } } diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/FeatureLevel.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/FeatureLevel.java new file mode 100644 index 0000000..d5ab468 --- /dev/null +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/FeatureLevel.java @@ -0,0 +1,22 @@ +package fr.agrometinfo.www.shared.dto; + +/** + * Level of selected feature. + * + * @author Olivier Maury + */ +public enum FeatureLevel { + /** + * SAFRAN cell. + */ + CELL, + /** + * Petite Région Agricole. + */ + PRA, + /** + * Region. + */ + REGION; +} + diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/SimpleFeature.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/SimpleFeature.java new file mode 100644 index 0000000..0f7d4b3 --- /dev/null +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/SimpleFeature.java @@ -0,0 +1,63 @@ +package fr.agrometinfo.www.shared.dto; + +/** + * A geographic object. + * + * @author Olivier Maury + */ +public class SimpleFeature { + /** + * Unique identifier. + */ + private String id; + /** + * Display name. + */ + private String name; + /** + * Level. + */ + private FeatureLevel level; + + /** + * @return Unique identifier. + */ + public final String getId() { + return id; + } + + /** + * @return Level. + */ + public final FeatureLevel getLevel() { + return level; + } + + /** + * @return Display name. + */ + public final String getName() { + return name; + } + + /** + * @param value Unique identifier. + */ + public final void setId(final String value) { + this.id = value; + } + + /** + * @param value Level. + */ + public final void setLevel(final FeatureLevel value) { + this.level = value; + } + + /** + * @param value Display name. + */ + public final void setName(final String value) { + this.name = value; + } +} diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/SummaryDTO.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/SummaryDTO.java index 913c23d..a6ba9f0 100644 --- a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/SummaryDTO.java +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/SummaryDTO.java @@ -16,23 +16,32 @@ public class SummaryDTO { * Average daily value of the indicator for the user choice. */ private Float averageValue; - /** - * Average daily comparison value of the indicator for the user choice. - */ - private Float comparedValue; + /** * User choice. */ private ChoiceDTO choice; + + /** + * Average daily comparison value of the indicator for the user choice. + */ + private Float comparedValue; + /** * Last daily values for the indicator. */ private Map<Date, Float> dailyValues; + /** * Date of the last simulation. */ private Date date; + /** + * Feature name (region, PRA, cell). + */ + private String featureName; + /** * Chosen indicator. */ @@ -44,19 +53,22 @@ public class SummaryDTO { private Map<String, Float> monthlyValues; /** - * Period name. + * The parent feature if exists. */ - private String period; + private SimpleFeature parentFeature; + /** - * Region name. + * Period name. */ - private String region; + private String period; + /** * @return Average daily value of the indicator for the user choice. */ public final Float getAverageValue() { return averageValue; } + /** * @return User choice. */ @@ -85,6 +97,13 @@ public class SummaryDTO { return date; } + /** + * @return Feature name. + */ + public final String getFeatureName() { + return featureName; + } + /** * @return Chosen indicator. */ @@ -100,17 +119,17 @@ public class SummaryDTO { } /** - * @return period name + * @return The parent feature if exists. */ - public String getPeriod() { - return period; + public final SimpleFeature getParentFeature() { + return parentFeature; } /** - * @return Region name. + * @return period name */ - public final String getRegion() { - return region; + public String getPeriod() { + return period; } /** @@ -148,6 +167,13 @@ public class SummaryDTO { this.date = value; } + /** + * @param name Feature name. + */ + public final void setFeatureName(final String name) { + this.featureName = name; + } + /** * @param value Chosen indicator. */ @@ -163,16 +189,16 @@ public class SummaryDTO { } /** - * @param name period name + * @param feature The parent feature or null. */ - public final void setPeriod(final String name) { - this.period = name; + public final void setParentFeature(final SimpleFeature feature) { + this.parentFeature = feature; } /** - * @param name Region name. + * @param name period name */ - public final void setRegion(final String name) { - this.region = name; + public final void setPeriod(final String name) { + this.period = name; } } diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/service/IndicatorService.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/service/IndicatorService.java index 58cefca..cd3d633 100644 --- a/www-shared/src/main/java/fr/agrometinfo/www/shared/service/IndicatorService.java +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/service/IndicatorService.java @@ -10,6 +10,7 @@ import javax.ws.rs.QueryParam; import org.dominokit.rest.shared.request.service.annotations.RequestFactory; import org.geojson.FeatureCollection; +import fr.agrometinfo.www.shared.dto.FeatureLevel; import fr.agrometinfo.www.shared.dto.PeriodDTO; import fr.agrometinfo.www.shared.dto.SummaryDTO; @@ -63,20 +64,21 @@ public interface IndicatorService { Map<String, String> getRegions(); /** - * @param indicator indicator coe + * @param indicator indicator code * @param period period code - * @param region region ID + * @param level feature level + * @param id feature ID * @param year year * @return indicator summary for the user choice. */ @GET @Path(PATH_SUMMARY) SummaryDTO getSummary(@QueryParam(value = "indicator") String indicator, - @QueryParam(value = "period") String period, @QueryParam(value = "region") Integer region, - @QueryParam(value = "year") Integer year); + @QueryParam(value = "period") String period, @QueryParam(value = "level") FeatureLevel level, + @QueryParam(value = "id") String id, @QueryParam(value = "year") Integer year); /** - * @param indicator indicator coe + * @param indicator indicator code * @param period period code * @param region region ID * @param year year -- GitLab