From 1ed01e76301c792e1770233eec2c168541b62990 Mon Sep 17 00:00:00 2001 From: Olivier Maury <Olivier.Maury@inrae.fr> Date: Tue, 21 May 2024 16:23:57 +0200 Subject: [PATCH] =?UTF-8?q?S=C3=A9parer=20LeftPanel=20de=20Layout.=20refs?= =?UTF-8?q?=20#90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/migration.sql | 13 + .../www/client/presenter/LayoutPresenter.java | 127 +------ .../client/presenter/LeftPanelPresenter.java | 182 ++++++++++ .../www/client/ui/chart/DailyValuesChart.java | 1 - .../www/client/view/LayoutView.java | 282 +-------------- .../www/client/view/LeftPanelView.java | 331 ++++++++++++++++++ www-server/pom.xml | 2 +- .../fr/agrometinfo/www/shared/module.gwt.xml | 3 +- 8 files changed, 548 insertions(+), 393 deletions(-) create mode 100644 www-client/src/main/java/fr/agrometinfo/www/client/presenter/LeftPanelPresenter.java create mode 100644 www-client/src/main/java/fr/agrometinfo/www/client/view/LeftPanelView.java diff --git a/sql/migration.sql b/sql/migration.sql index e3e2b7c..cc5cb5d 100644 --- a/sql/migration.sql +++ b/sql/migration.sql @@ -226,6 +226,19 @@ END $BODY$ language plpgsql; +-- +-- #88 +-- +CREATE OR REPLACE FUNCTION upgrade20240513() RETURNS boolean AS $BODY$ +BEGIN + UPDATE dailyvalue AS d + FROM normalvalue AS n ON n.indicator=d.indicator AND n.cell=d.cell AND n.doy=EXTRACT(DOY FROM d.date) + SET d.comparedvalue=COALESCE(d.computedvalue - n."medianvalue", 0); + RETURN true; +END; +$BODY$ +language plpgsql; + --- -- -- Keep this call at the end to apply migration functions. diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LayoutPresenter.java b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LayoutPresenter.java index 73a1d82..e0575f3 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LayoutPresenter.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LayoutPresenter.java @@ -1,26 +1,17 @@ package fr.agrometinfo.www.client.presenter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.Objects; import org.dominokit.rest.shared.request.FailedResponseBean; import com.google.gwt.core.client.GWT; -import fr.agrometinfo.www.client.App; -import fr.agrometinfo.www.client.event.LoadingEvent; -import fr.agrometinfo.www.client.event.LoadingEvent.LoadingEventType; -import fr.agrometinfo.www.client.i18n.AppConstants; import fr.agrometinfo.www.client.view.BaseView; import fr.agrometinfo.www.client.view.LayoutView; import fr.agrometinfo.www.client.view.MapView; import fr.agrometinfo.www.client.view.RightPanelView; import fr.agrometinfo.www.shared.dto.ChoiceDTO; import fr.agrometinfo.www.shared.dto.IndicatorDTO; -import fr.agrometinfo.www.shared.dto.PeriodDTO; -import fr.agrometinfo.www.shared.service.IndicatorServiceFactory; /** * Presenter for the general layout. @@ -46,27 +37,8 @@ public final class LayoutPresenter implements Presenter { */ void setDevMode(boolean isDevMode); - /** - * @param list indicator periods with indicators - */ - void setPeriods(List<PeriodDTO> list); - - /** - * @param list regions with indicators - */ - void setRegions(Map<String, String> list); - - /** - * @param list years of computed values - */ - void setYears(List<Integer> list); } - /** - * I18N constants. - */ - private static final AppConstants CSTS = GWT.create(AppConstants.class); - /** * Presenter for {@link MapView}. */ @@ -77,26 +49,11 @@ public final class LayoutPresenter implements Presenter { */ private final RightPanelPresenter rightPanelPresenter = new RightPanelPresenter(); - /** - * Periods from server. - */ - private List<PeriodDTO> periods; - /** * Related view. */ private final LayoutView view = new LayoutView(); - /** - * Region id : region name. - */ - private final Map<String, String> regions = new HashMap<>(); - - /** - * Year chosen by the user. - */ - private Integer chosenYear; - /** * @see https://github.com/gwtproject/gwt/issues/7631#issuecomment-110876116 * @return if the application is running in (Super) DevMode. @@ -106,77 +63,19 @@ public final class LayoutPresenter implements Presenter { } /** - * @param choice the user's choice + * @param choice the user's choice + * @param indicator related indicator for the choice + * @param periodName name of chosen period + * @param regionName name of chosen region */ - public void onChoiceChange(final ChoiceDTO choice) { + public void onChoiceChange(final ChoiceDTO choice, final IndicatorDTO indicator, final String periodName, + final String regionName) { GWT.log("LayoutPresenter.onChoiceChange()"); - IndicatorDTO chosenIndicator = null; - String periodName = ""; - for (final PeriodDTO period: periods) { - if (period.getCode().equals(choice.getPeriod())) { - periodName = period.getDescription(); - for (final IndicatorDTO indicator : period.getIndicators()) { - if (indicator.getCode().equals(choice.getIndicator())) { - chosenIndicator = indicator; - } - } - } - } - if ("0".equals(choice.getFeatureId())) { - choice.setFeatureId(null); - } - chosenYear = choice.getYear(); - final String regionName = regions.getOrDefault(choice.getFeatureId(), CSTS.metropolitanFrance()); - GWT.log("LayoutPresenter.onChoiceChange() a"); - mapPresenter.loadValues(choice, chosenIndicator, periodName, regionName); - GWT.log("LayoutPresenter.onChoiceChange() b"); + mapPresenter.loadValues(choice, indicator, periodName, regionName); rightPanelPresenter.loadValues(choice, periodName); GWT.log("LayoutPresenter.onChoiceChange() done"); } - /** - * Memorize periods. - * - * @param list periods from server. - */ - private void setPeriods(final List<PeriodDTO> list) { - this.periods = list; - view.setPeriods(list); - - App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.START)); - IndicatorServiceFactory.INSTANCE.getRegions(chosenYear) // - .onSuccess(this::setRegions) // - .onFailed(view::failureNotification) // - .onComplete(() -> App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.END))) // - .send(); - } - - /** - * @param list regions with indicators - */ - private void setRegions(final Map<String, String> list) { - regions.clear(); - regions.putAll(list); - view.setRegions(list); - } - - /** - * @param list years of computed values - */ - private void setYears(final List<Integer> list) { - view.setYears(list); - - if (!list.isEmpty()) { - chosenYear = list.get(list.size() - 1); - App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.START)); - IndicatorServiceFactory.INSTANCE.getPeriods(chosenYear) // - .onSuccess(this::setPeriods) // - .onFailed(view::failureNotification) // - .onComplete(() -> App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.END))) // - .send(); - } - } - /** * Display contact form. */ @@ -195,16 +94,14 @@ public final class LayoutPresenter implements Presenter { view.init(); view.setDevMode(isDevMode()); + final LeftPanelPresenter leftPanelPresenter = new LeftPanelPresenter(); + leftPanelPresenter.setLayoutView(view); + leftPanelPresenter.setLayoutPresenter(this); + leftPanelPresenter.start(); + rightPanelPresenter.setLayoutView(view); rightPanelPresenter.start(); new WelcomePresenter().start(); - - App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.START)); - IndicatorServiceFactory.INSTANCE.getYears() // - .onSuccess(this::setYears) // - .onFailed(view::failureNotification) // - .onComplete(() -> App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.END))) // - .send(); } } diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LeftPanelPresenter.java b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LeftPanelPresenter.java new file mode 100644 index 0000000..5f1207c --- /dev/null +++ b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LeftPanelPresenter.java @@ -0,0 +1,182 @@ +package fr.agrometinfo.www.client.presenter; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.gwt.core.client.GWT; + +import fr.agrometinfo.www.client.App; +import fr.agrometinfo.www.client.event.LoadingEvent; +import fr.agrometinfo.www.client.event.LoadingEvent.LoadingEventType; +import fr.agrometinfo.www.client.i18n.AppConstants; +import fr.agrometinfo.www.client.view.BaseView; +import fr.agrometinfo.www.client.view.LayoutView; +import fr.agrometinfo.www.client.view.LeftPanelView; +import fr.agrometinfo.www.shared.dto.ChoiceDTO; +import fr.agrometinfo.www.shared.dto.IndicatorDTO; +import fr.agrometinfo.www.shared.dto.PeriodDTO; +import fr.agrometinfo.www.shared.service.IndicatorServiceFactory; + +/** + * Presenter for the left panel in the LayoutView to display selectors. + * + * @author Olivier Maury + */ +public final class LeftPanelPresenter implements Presenter { + + /** + * Related view interface. + */ + public interface View extends BaseView<LeftPanelPresenter> { + /** + * @param list indicator periods with indicators + */ + void setPeriods(List<PeriodDTO> list); + + /** + * @param list regions with indicators + */ + void setRegions(Map<String, String> list); + + /** + * @param list years of computed values + */ + void setYears(List<Integer> list); + } + + /** + * I18N constants. + */ + private static final AppConstants CSTS = GWT.create(AppConstants.class); + + /** + * Periods from server. + */ + private List<PeriodDTO> periods; + + /** + * Region id : region name. + */ + private final Map<String, String> regions = new HashMap<>(); + + /** + * Related view. + */ + private View view; + + /** + * The layout handling the panel. + */ + private LayoutView layoutView; + + /** + * The presenter for the application layout. + */ + private LayoutPresenter layoutPresenter; + /** + * Year chosen by the user. + */ + private Integer chosenYear; + + /** + * @param choice the user's choice + */ + public void onChoiceChange(final ChoiceDTO choice) { + GWT.log("LeftPanelPresenter.onChoiceChange()"); + IndicatorDTO chosenIndicator = null; + String periodName = ""; + for (final PeriodDTO period : periods) { + if (period.getCode().equals(choice.getPeriod())) { + periodName = period.getDescription(); + for (final IndicatorDTO indicator : period.getIndicators()) { + if (indicator.getCode().equals(choice.getIndicator())) { + chosenIndicator = indicator; + } + } + } + } + if ("0".equals(choice.getFeatureId())) { + choice.setFeatureId(null); + } + chosenYear = choice.getYear(); + final String regionName = regions.getOrDefault(choice.getFeatureId(), CSTS.metropolitanFrance()); + layoutPresenter.onChoiceChange(choice, chosenIndicator, periodName, regionName); + } + + /** + * @param lPresenter presenter of LayoutView + */ + public void setLayoutPresenter(final LayoutPresenter lPresenter) { + layoutPresenter = lPresenter; + } + + /** + * @param lView the layout handling the panel. + */ + public void setLayoutView(final LayoutView lView) { + layoutView = lView; + } + + /** + * Memorize periods. + * + * @param list periods from server. + */ + private void setPeriods(final List<PeriodDTO> list) { + GWT.log("RightPanelPresenter.setPeriods()"); + this.periods = list; + view.setPeriods(list); + + App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.START)); + IndicatorServiceFactory.INSTANCE.getRegions(chosenYear) // + .onSuccess(this::setRegions) // + .onFailed(layoutView::failureNotification) // + .onComplete(() -> App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.END))) // + .send(); + } + + /** + * @param list regions with indicators + */ + private void setRegions(final Map<String, String> list) { + GWT.log("RightPanelPresenter.setRegions()"); + regions.clear(); + regions.putAll(list); + view.setRegions(list); + } + + /** + * @param list years of computed values + */ + private void setYears(final List<Integer> list) { + GWT.log("RightPanelPresenter.setYears()"); + view.setYears(list); + + if (!list.isEmpty()) { + chosenYear = list.get(list.size() - 1); + App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.START)); + IndicatorServiceFactory.INSTANCE.getPeriods(chosenYear) // + .onSuccess(this::setPeriods) // + .onFailed(layoutView::failureNotification) // + .onComplete(() -> App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.END))) // + .send(); + } + } + + @Override + public void start() { + GWT.log("RightPanelPresenter.start()"); + view = new LeftPanelView(layoutView.getLeftPanel()); + view.setPresenter(this); + view.init(); + + App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.START)); + IndicatorServiceFactory.INSTANCE.getYears() // + .onSuccess(this::setYears) // + .onFailed(layoutView::failureNotification) // + .onComplete(() -> App.getEventBus().fireEvent(LoadingEvent.of(LoadingEventType.END))) // + .send(); + + } +} diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/ui/chart/DailyValuesChart.java b/www-client/src/main/java/fr/agrometinfo/www/client/ui/chart/DailyValuesChart.java index 565e2fe..64b76c7 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/ui/chart/DailyValuesChart.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/ui/chart/DailyValuesChart.java @@ -95,7 +95,6 @@ public final class DailyValuesChart extends TimeSeriesLineChart { final LinkedList<TimeSeriesItem> q95Data = new LinkedList<>(); values.forEach((date, value) -> { - GWT.log("DailyValuesChart() " + date + "->" + value[SummaryDTO.COMPUTED_INDEX]); data.add(new TimeSeriesItem(date, value[SummaryDTO.COMPUTED_INDEX])); if (value[SummaryDTO.Q5_INDEX] != null) { q5Data.add(new TimeSeriesItem(date, value[SummaryDTO.Q5_INDEX])); 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 9708094..5f7e8ba 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 @@ -5,20 +5,13 @@ import static org.jboss.elemento.Elements.div; import static org.jboss.elemento.Elements.img; import static org.jboss.elemento.Elements.li; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; import java.util.StringJoiner; -import org.dominokit.domino.ui.forms.Select; -import org.dominokit.domino.ui.forms.SwitchButton; import org.dominokit.domino.ui.grid.flex.FlexItem; import org.dominokit.domino.ui.icons.Icons; import org.dominokit.domino.ui.icons.MdiIcon; import org.dominokit.domino.ui.layout.Layout; -import org.dominokit.domino.ui.lists.ListGroup; import org.dominokit.domino.ui.loaders.Loader; import org.dominokit.domino.ui.loaders.LoaderEffect; import org.dominokit.domino.ui.menu.Menu; @@ -41,7 +34,6 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLAnchorElement; import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; -import elemental2.dom.HTMLLabelElement; import elemental2.dom.MouseEvent; import fr.agrometinfo.www.client.App; import fr.agrometinfo.www.client.event.LoadingEvent; @@ -52,14 +44,8 @@ import fr.agrometinfo.www.client.presenter.LayoutPresenter; import fr.agrometinfo.www.client.presenter.MapPresenter; import fr.agrometinfo.www.client.presenter.RightPanelPresenter; import fr.agrometinfo.www.client.ui.AgroclimAppsMenu; -import fr.agrometinfo.www.client.ui.CollapsedSelect; -import fr.agrometinfo.www.client.ui.DominoListBuilder; -import fr.agrometinfo.www.client.ui.DominoSelectBuilder; import fr.agrometinfo.www.client.util.ApplicationUtils; -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; + /** * View for the general layout. @@ -73,15 +59,6 @@ implements LayoutPresenter.View, LoadingHandler { */ private static final AppConstants CSTS = GWT.create(AppConstants.class); - /** - * Code of indicator to show by default. - */ - private static final String DEFAULT_INDICATOR = "meant"; - - /** - * Code of period to show by default. - */ - private static final String DEFAULT_PERIOD = "year"; /** * The minimum screen width to display panels on startup. @@ -136,11 +113,6 @@ implements LayoutPresenter.View, LoadingHandler { } } - /** - * Choice from the user. - */ - private final ChoiceDTO choice = new ChoiceDTO(); - /** * Drop down menu for user actions. */ @@ -151,11 +123,6 @@ implements LayoutPresenter.View, LoadingHandler { */ private final Menu<String> dotDropMenu = Menu.<String>create().setUseSmallScreensDirection(false); - /** - * Selector for indicators. - */ - private final ListGroup<IndicatorDTO> indicatorSelect = ListGroup.create(); - /** * Application layout. */ @@ -177,36 +144,11 @@ implements LayoutPresenter.View, LoadingHandler { */ private MapPresenter mapPresenter; - /** - * Available indicator periods with indicators. - */ - private List<PeriodDTO> periods; - - /** - * Selector for indicator periods. - */ - private final Select<PeriodDTO> periodSelect = Select.create(CSTS.choosePeriod()); - - /** - * Selector for regions. - */ - private final Select<Entry<String, String>> regionSelect = Select.create(CSTS.chooseRegion()); - /** * Presenter for {@link RightPanelView}. */ private RightPanelPresenter rightPanelPresenter; - /** - * Summary of available indicators. - */ - private final HtmlContentBuilder<HTMLDivElement> summary = div().css("p-b-15"); - - /** - * Selector for year. - */ - private final Select<Entry<String, String>> yearSelect = Select.create(CSTS.chooseYear()); - /** * Counter for loading events. */ @@ -222,11 +164,6 @@ implements LayoutPresenter.View, LoadingHandler { */ private final HtmlContentBuilder<HTMLDivElement> links = div().css("links"); - /** - * The replacement of indicatorSelect when it is hidden. - */ - private final CollapsedSelect collapsedIndicatorSelect = new CollapsedSelect(CSTS.chooseIndicator(), ""); - /** * @param text link text * @param callback {@link EventCallbackFn<MouseEvent>} to be added to the click @@ -259,6 +196,13 @@ implements LayoutPresenter.View, LoadingHandler { this.notification(MSGS.failureResponse(getDetails(failedResponse))); } + /** + * @return the left panel {@link HTMLElement} wrapped as a {@link DominoElement} + */ + public DominoElement<HTMLElement> getLeftPanel() { + return layout.getLeftPanel(); + } + /** * Close the left panel if it is open. */ @@ -272,7 +216,6 @@ implements LayoutPresenter.View, LoadingHandler { @Override public void init() { GWT.log("LayoutView.initLayout()"); - choice.setLevel(FeatureLevel.REGION); layout = Layout.create("AgroMetInfo").show(); layout.css("app-layout"); final HTMLDivElement contentElement = div().element(); @@ -339,77 +282,6 @@ implements LayoutPresenter.View, LoadingHandler { }) // .add(Icons.CONTENT_ICONS.clear().clickable())); - panel.appendChild(summary); - - // - GWT.log("LayoutView.initLeftPanel() periods"); - panel.appendChild(periodSelect); - new DominoSelectBuilder<PeriodDTO>() // - .setSelect(periodSelect) // - .addValueChangeHandler(this::onPeriodChange) // - .build(); - periodSelect.setSearchable(false); - - // - GWT.log("LayoutView.initLeftPanel() indicators"); - collapsedIndicatorSelect.hide(); - panel.appendChild(collapsedIndicatorSelect.getRoot()); - final HtmlContentBuilder<HTMLDivElement> indicatorPanel = div().css("field-group lined list-group"); - final HtmlContentBuilder<HTMLLabelElement> indicatorLabel = Elements.label() // - .css("field-label") // - .add(Elements.span().textContent(CSTS.chooseIndicator())); - panel.appendChild(indicatorPanel// - .add(indicatorLabel) // - .add(indicatorSelect) // - ); - new DominoListBuilder<IndicatorDTO>() // - .setSelect(indicatorSelect) // - .addTextChangeHandler(collapsedIndicatorSelect::setSelectionText) // - .setTextFunction(IndicatorDTO::getDescription) // - .setValueFunction(IndicatorDTO::getCode) // - .addValueChangeHandler(this::onIndicatorChange) // - .build(); - - indicatorLabel.on(EventType.click, e -> { - indicatorPanel.hidden(true); - collapsedIndicatorSelect.show(); - }); - collapsedIndicatorSelect.onClick(e -> { - indicatorPanel.hidden(false); - collapsedIndicatorSelect.hide(); - }); - - // - GWT.log("LayoutView.initLeftPanel() regions"); - panel.appendChild(regionSelect); - new DominoSelectBuilder<Entry<String, String>>() // - .setSelect(regionSelect) // - .addValueChangeHandler(this::onRegionChange) // - .build(); - regionSelect.setSearchable(false); - - // - GWT.log("LayoutView.initLeftPanel() year"); - panel.appendChild(yearSelect); - new DominoSelectBuilder<Entry<String, String>>() // - .setSelect(yearSelect) // - .addValueChangeHandler(this::onYearChange); - yearSelect.setSearchable(false); - - // - GWT.log("LayoutView.initLeftPanel() comparison"); - final SwitchButton comparisonBtn = SwitchButton.create(CSTS.normalComparison(), CSTS.no(), CSTS.yes()) // - .value(false); - comparisonBtn.addChangeHandler(this::onComparisonChange); - comparisonBtn.addCss("comparison-btn"); - final HTMLElement info = Elements.createElement("details", HTMLElement.class); - final HTMLElement sum = Elements.createElement("summary", HTMLElement.class); - sum.innerHTML = "<i class='material-icons'>info_outline</i>"; - info.innerHTML = CSTS.normalComparisonTooltip(); - info.append(sum); - comparisonBtn.getFieldContainer().getFirstChild().appendChild(info); - panel.appendChild(comparisonBtn); - // finally layout.showLeftPanel(); } @@ -522,25 +394,6 @@ implements LayoutPresenter.View, LoadingHandler { return Notification.create(msg).setPosition(Notification.TOP_LEFT).show(); } - private void onChoiceChange() { - GWT.log("LayoutView.onChoiceChange()"); - if (choice.isValid()) { - getPresenter().onChoiceChange(choice); - } - } - - private void onComparisonChange(final boolean newValue) { - GWT.log("LayoutView.onComparisonChange()"); - choice.setComparison(newValue); - onChoiceChange(); - } - - private void onIndicatorChange(final String newValue) { - GWT.log("LayoutView.onIndicatorChange() " + newValue); - choice.setIndicator(newValue); - onChoiceChange(); - } - @Override public void onLoading(final LoadingEvent event) { GWT.log("LayoutView.onLoading() " + event); @@ -565,64 +418,6 @@ implements LayoutPresenter.View, LoadingHandler { GWT.log("LayoutView.onLoading() done"); } - private void onPeriodChange(final String newValue) { - GWT.log("LayoutView.onPeriodChange() " + newValue); - choice.setPeriod(newValue); - choice.setIndicator(null); - - // fill indicators - List<IndicatorDTO> list = null; - for (final PeriodDTO p : this.periods) { - if (p.getCode().equals(newValue)) { - list = p.getIndicators(); - break; - } - } - if (list == null || list.isEmpty()) { - indicatorSelect.clearElement(); - return; - } - GWT.log("LayoutView.onPeriodChange() Indicators : " + list); - final IndicatorDTO firstIndicator = list.get(0); - final IndicatorDTO defaultIndicator = list.stream() // - .filter(i -> DEFAULT_INDICATOR.equals(i.getCode())) // - .findFirst().orElse(firstIndicator); - new DominoListBuilder<IndicatorDTO>() // - .setSelect(indicatorSelect) // - .setTextFunction(IndicatorDTO::getDescription) // - .setValueFunction(IndicatorDTO::getCode) // - .removeOptions() // - .addOptions(list) // - .select(defaultIndicator) // - .build(); - // select "meant" - if (defaultIndicator != null) { - onIndicatorChange(defaultIndicator.getCode()); - } else { - onChoiceChange(); - } - } - - private void onRegionChange(final String newValue) { - GWT.log("LayoutView.onRegionChange()"); - if (newValue.length() > 2) { - choice.setFeatureId(null); - } else { - choice.setFeatureId(newValue); - } - onChoiceChange(); - } - - private void onYearChange(final String newValue) { - GWT.log("LayoutView.onYearChange()"); - try { - choice.setYear(Integer.valueOf(newValue)); - } catch (final NumberFormatException e) { - choice.setYear(null); - } - onChoiceChange(); - } - /** * To display an OpenLayers map, a container with a fixed height CSS property is * needed. @@ -670,50 +465,6 @@ implements LayoutPresenter.View, LoadingHandler { this.mapPresenter = presenter; } - @Override - public void setPeriods(final List<PeriodDTO> list) { - this.periods = list; - // summary - final StringJoiner sj = new StringJoiner(" "); - sj.add(MSGS.nbOfIndicatorPeriods(list.size())); - sj.add(MSGS.nbOfIndicators(list.stream().mapToInt(c -> c.getIndicators().size()).sum())); - summary.textContent(sj.toString()); - - if (this.periods.isEmpty()) { - return; - } - // display periods - GWT.log("LayoutView.setPeriods() : " + list); - final PeriodDTO defaultPeriod = list.stream() // - .filter(i -> DEFAULT_PERIOD.equals(i.getCode())) // - .findFirst().orElse(null); - - new DominoSelectBuilder<PeriodDTO>() // - .setSelect(periodSelect) // - .setTextFunction(PeriodDTO::getDescription) // - .setValueFunction(PeriodDTO::getCode) // - .addOptions(list) // - .select(defaultPeriod) // - .build(); - } - - @Override - public void setRegions(final Map<String, String> list) { - GWT.log("LayoutView.setRegions()"); - final String metropolitanFranceCode = "0"; - list.put(metropolitanFranceCode, CSTS.metropolitanFrance()); - final Entry<String, String> defaultRegion = list.entrySet().stream() // - .filter(e -> metropolitanFranceCode.equals(e.getKey())) // - .findFirst().orElse(null); - new DominoSelectBuilder<Entry<String, String>>() // - .setSelect(regionSelect) // - .setTextFunction(Entry<String, String>::getValue) // - .setValueFunction(Entry<String, String>::getKey) // - .addOptions(list.entrySet()) // - .select(defaultRegion) // - .build(); - } - /** * @param presenter presenter for {@link RightPanelView}. */ @@ -721,23 +472,6 @@ implements LayoutPresenter.View, LoadingHandler { this.rightPanelPresenter = presenter; } - @Override - public void setYears(final List<Integer> list) { - GWT.log("LayoutView.setYears()"); - final Map<String, String> yearOptions = new HashMap<>(); - list.forEach(y -> yearOptions.put(String.valueOf(y), String.valueOf(y))); - final Optional<Integer> defaultYear = list.stream().max(Integer::compare); - final Entry<String, String> yearEntry = yearOptions.entrySet().stream() // - .filter(e -> e.getKey().equals(String.valueOf(defaultYear.get()))) // - .findFirst().orElse(null); - new DominoSelectBuilder<Entry<String, String>>() // - .setSelect(yearSelect) // - .setTextFunction(Entry<String, String>::getValue) // - .setValueFunction(Entry<String, String>::getKey) // - .select(yearEntry) // - .addOptions(yearOptions.entrySet()); - } - /** * Open the right panel. */ diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/view/LeftPanelView.java b/www-client/src/main/java/fr/agrometinfo/www/client/view/LeftPanelView.java new file mode 100644 index 0000000..7918406 --- /dev/null +++ b/www-client/src/main/java/fr/agrometinfo/www/client/view/LeftPanelView.java @@ -0,0 +1,331 @@ +package fr.agrometinfo.www.client.view; + +import static org.jboss.elemento.Elements.div; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.StringJoiner; + +import org.dominokit.domino.ui.forms.Select; +import org.dominokit.domino.ui.forms.SwitchButton; +import org.dominokit.domino.ui.lists.ListGroup; +import org.dominokit.domino.ui.utils.DominoElement; +import org.jboss.elemento.Elements; +import org.jboss.elemento.EventType; +import org.jboss.elemento.HtmlContentBuilder; + +import com.google.gwt.core.client.GWT; + +import elemental2.dom.HTMLDivElement; +import elemental2.dom.HTMLElement; +import elemental2.dom.HTMLLabelElement; +import fr.agrometinfo.www.client.i18n.AppConstants; +import fr.agrometinfo.www.client.i18n.AppMessages; +import fr.agrometinfo.www.client.presenter.LeftPanelPresenter; +import fr.agrometinfo.www.client.ui.CollapsedSelect; +import fr.agrometinfo.www.client.ui.DominoListBuilder; +import fr.agrometinfo.www.client.ui.DominoSelectBuilder; +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; + +/** + * Right panel in the LayoutView to display data related to user choice. + * + * @author Olivier Maury + */ +public final class LeftPanelView extends AbstractBaseView<LeftPanelPresenter> implements LeftPanelPresenter.View { + /** + * I18N constants. + */ + private static final AppConstants CSTS = GWT.create(AppConstants.class); + + /** + * Code of indicator to show by default. + */ + private static final String DEFAULT_INDICATOR = "meant"; + + /** + * Code of period to show by default. + */ + private static final String DEFAULT_PERIOD = "year"; + + /** + * I18N messages. + */ + private static final AppMessages MSGS = GWT.create(AppMessages.class); + + /** + * Layout handling the panel. + */ + private final DominoElement<HTMLElement> panel; + + /** + * Summary of available indicators. + */ + private final HtmlContentBuilder<HTMLDivElement> summary = div().css("p-b-15"); + + /** + * Selector for indicator periods. + */ + private final Select<PeriodDTO> periodSelect = Select.create(CSTS.choosePeriod()); + + /** + * Choice from the user. + */ + private final ChoiceDTO choice = new ChoiceDTO(); + + /** + * Available indicator periods with indicators. + */ + private List<PeriodDTO> periods; + + /** + * Selector for indicators. + */ + private final ListGroup<IndicatorDTO> indicatorSelect = ListGroup.create(); + + /** + * Selector for regions. + */ + private final Select<Entry<String, String>> regionSelect = Select.create(CSTS.chooseRegion()); + + /** + * The replacement of indicatorSelect when it is hidden. + */ + private final CollapsedSelect collapsedIndicatorSelect = new CollapsedSelect(CSTS.chooseIndicator(), ""); + + /** + * Selector for year. + */ + private final Select<Entry<String, String>> yearSelect = Select.create(CSTS.chooseYear()); + + /** + * Constructor. + * + * @param leftPanel container for the panel. + */ + public LeftPanelView(final DominoElement<HTMLElement> leftPanel) { + GWT.log("LeftPanelView()"); + panel = leftPanel; + } + + @Override + public void init() { + + choice.setLevel(FeatureLevel.REGION); + + panel.appendChild(summary); + + // + GWT.log("LeftPanelView.initLeftPanel() periods"); + panel.appendChild(periodSelect); + new DominoSelectBuilder<PeriodDTO>() // + .setSelect(periodSelect) // + .addValueChangeHandler(this::onPeriodChange) // + .build(); + periodSelect.setSearchable(false); + + // + GWT.log("LeftPanelView.initLeftPanel() indicators"); + collapsedIndicatorSelect.hide(); + panel.appendChild(collapsedIndicatorSelect.getRoot()); + final HtmlContentBuilder<HTMLDivElement> indicatorPanel = div().css("field-group lined list-group"); + final HtmlContentBuilder<HTMLLabelElement> indicatorLabel = Elements.label() // + .css("field-label") // + .add(Elements.span().textContent(CSTS.chooseIndicator())); + panel.appendChild(indicatorPanel// + .add(indicatorLabel) // + .add(indicatorSelect) // + ); + new DominoListBuilder<IndicatorDTO>() // + .setSelect(indicatorSelect) // + .addTextChangeHandler(collapsedIndicatorSelect::setSelectionText) // + .setTextFunction(IndicatorDTO::getDescription) // + .setValueFunction(IndicatorDTO::getCode) // + .addValueChangeHandler(this::onIndicatorChange) // + .build(); + + indicatorLabel.on(EventType.click, e -> { + indicatorPanel.hidden(true); + collapsedIndicatorSelect.show(); + }); + collapsedIndicatorSelect.onClick(e -> { + indicatorPanel.hidden(false); + collapsedIndicatorSelect.hide(); + }); + + // + GWT.log("LeftPanelView.initLeftPanel() regions"); + panel.appendChild(regionSelect); + new DominoSelectBuilder<Entry<String, String>>() // + .setSelect(regionSelect) // + .addValueChangeHandler(this::onRegionChange) // + .build(); + regionSelect.setSearchable(false); + + // + GWT.log("LeftPanelView.initLeftPanel() year"); + panel.appendChild(yearSelect); + new DominoSelectBuilder<Entry<String, String>>() // + .setSelect(yearSelect) // + .addValueChangeHandler(this::onYearChange); + yearSelect.setSearchable(false); + + // + GWT.log("LeftPanelView.initLeftPanel() comparison"); + final SwitchButton comparisonBtn = SwitchButton.create(CSTS.normalComparison(), CSTS.no(), CSTS.yes()) // + .value(false); + comparisonBtn.addChangeHandler(this::onComparisonChange); + comparisonBtn.addCss("comparison-btn"); + final HTMLElement info = Elements.createElement("details", HTMLElement.class); + final HTMLElement sum = Elements.createElement("summary", HTMLElement.class); + sum.innerHTML = "<i class='material-icons'>info_outline</i>"; + info.innerHTML = CSTS.normalComparisonTooltip(); + info.append(sum); + comparisonBtn.getFieldContainer().getFirstChild().appendChild(info); + panel.appendChild(comparisonBtn); + } + + private void onChoiceChange() { + GWT.log("LeftPanelView.onChoiceChange()"); + if (choice.isValid()) { + getPresenter().onChoiceChange(choice); + } + } + + private void onComparisonChange(final boolean newValue) { + GWT.log("LeftPanelView.onComparisonChange()"); + choice.setComparison(newValue); + onChoiceChange(); + } + + private void onIndicatorChange(final String newValue) { + GWT.log("LeftPanelView.onIndicatorChange() " + newValue); + choice.setIndicator(newValue); + onChoiceChange(); + } + + private void onPeriodChange(final String newValue) { + GWT.log("LeftPanelView.onPeriodChange() " + newValue); + choice.setPeriod(newValue); + choice.setIndicator(null); + + // fill indicators + List<IndicatorDTO> list = null; + for (final PeriodDTO p : this.periods) { + if (p.getCode().equals(newValue)) { + list = p.getIndicators(); + break; + } + } + if (list == null || list.isEmpty()) { + indicatorSelect.clearElement(); + return; + } + GWT.log("LeftPanelView.onPeriodChange() Indicators : " + list); + final IndicatorDTO firstIndicator = list.get(0); + final IndicatorDTO defaultIndicator = list.stream() // + .filter(i -> DEFAULT_INDICATOR.equals(i.getCode())) // + .findFirst().orElse(firstIndicator); + new DominoListBuilder<IndicatorDTO>() // + .setSelect(indicatorSelect) // + .setTextFunction(IndicatorDTO::getDescription) // + .setValueFunction(IndicatorDTO::getCode) // + .removeOptions() // + .addOptions(list) // + .select(defaultIndicator); + GWT.log("LeftPanelView.onPeriodChange() defaultIndicator : " + defaultIndicator); + // select "meant" + if (defaultIndicator != null) { + onIndicatorChange(defaultIndicator.getCode()); + } else { + onChoiceChange(); + } + } + + private void onRegionChange(final String newValue) { + GWT.log("LeftPanelView.onRegionChange()"); + if (newValue.length() > 2) { + choice.setFeatureId(null); + } else { + choice.setFeatureId(newValue); + } + onChoiceChange(); + } + + private void onYearChange(final String newValue) { + GWT.log("LeftPanelView.onYearChange()"); + try { + choice.setYear(Integer.valueOf(newValue)); + } catch (final NumberFormatException e) { + choice.setYear(null); + } + onChoiceChange(); + } + + @Override + public void setPeriods(final List<PeriodDTO> list) { + GWT.log("LeftPanelView.setPeriods() : " + list); + this.periods = list; + // summary + final StringJoiner sj = new StringJoiner(" "); + sj.add(MSGS.nbOfIndicatorPeriods(list.size())); + sj.add(MSGS.nbOfIndicators(list.stream().mapToInt(c -> c.getIndicators().size()).sum())); + summary.textContent(sj.toString()); + + if (this.periods.isEmpty()) { + return; + } + // display periods + final PeriodDTO defaultPeriod = list.stream() // + .filter(i -> DEFAULT_PERIOD.equals(i.getCode())) // + .findFirst().orElse(null); + + new DominoSelectBuilder<PeriodDTO>() // + .setSelect(periodSelect) // + .setTextFunction(PeriodDTO::getDescription) // + .setValueFunction(PeriodDTO::getCode) // + .addOptions(list) // + .select(defaultPeriod) // + .build(); + } + + @Override + public void setRegions(final Map<String, String> list) { + GWT.log("LeftPanelView.setRegions()"); + final String metropolitanFranceCode = "0"; + list.put(metropolitanFranceCode, CSTS.metropolitanFrance()); + final Entry<String, String> defaultRegion = list.entrySet().stream() // + .filter(e -> metropolitanFranceCode.equals(e.getKey())) // + .findFirst().orElse(null); + new DominoSelectBuilder<Entry<String, String>>() // + .setSelect(regionSelect) // + .setTextFunction(Entry<String, String>::getValue) // + .setValueFunction(Entry<String, String>::getKey) // + .addOptions(list.entrySet()) // + .select(defaultRegion) // + .build(); + } + + @Override + public void setYears(final List<Integer> list) { + GWT.log("LeftPanelView.setYears()"); + final Map<String, String> yearOptions = new HashMap<>(); + list.forEach(y -> yearOptions.put(String.valueOf(y), String.valueOf(y))); + final Optional<Integer> defaultYear = list.stream().max(Integer::compare); + final Entry<String, String> yearEntry = yearOptions.entrySet().stream() // + .filter(e -> e.getKey().equals(String.valueOf(defaultYear.get()))) // + .findFirst().orElse(null); + new DominoSelectBuilder<Entry<String, String>>() // + .setSelect(yearSelect) // + .setTextFunction(Entry<String, String>::getValue) // + .setValueFunction(Entry<String, String>::getKey) // + .select(yearEntry) // + .addOptions(yearOptions.entrySet()); + } +} diff --git a/www-server/pom.xml b/www-server/pom.xml index 89c7e39..783b50e 100644 --- a/www-server/pom.xml +++ b/www-server/pom.xml @@ -164,7 +164,7 @@ <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> - <version>3.0.0</version> + <version>3.0.1</version> </dependency> <!-- fast-serialization --> <!-- https://mvnrepository.com/artifact/de.ruedigermoeller/fst --> diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/module.gwt.xml b/www-shared/src/main/java/fr/agrometinfo/www/shared/module.gwt.xml index 3d37b27..164dd77 100644 --- a/www-shared/src/main/java/fr/agrometinfo/www/shared/module.gwt.xml +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/module.gwt.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.9.0//EN" - "https://www.gwtproject.org/doctype/2.9.0/gwt-module.dtd"> +<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.11.0//EN" "https://www.gwtproject.org/doctype/2.11.0/gwt-module.dtd"> <module> <inherits name="org.dominokit.rest.Rest"/> <inherits name="org.dominokit.jackson.Jackson"/> -- GitLab