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