mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 14:12:11 +00:00
Added error messages with helping hints
This commit is contained in:
1 parent
8604cf83e6
commit
2035eb3832
14 files changed
+147
-78
No files matched your search
+1
-1
@@ -8,7 +8,7 @@ public interface QueryResult<AggregatedType> extends Serializable {
|
||||
int getRetrievedDataAmount();
|
||||
public int getFilteredDataAmount();
|
||||
public double getCalculationTimeInSeconds();
|
||||
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* @return a description what kind of results are contained.
|
||||
|
||||
+7
-2
@@ -11,8 +11,8 @@ public class QueryResultImpl<AggregatedType> implements QueryResult<AggregatedTy
|
||||
private long calculationTimeInNanos;
|
||||
|
||||
private String resultSignifier;
|
||||
private Unit unit;
|
||||
private int valueDecimals;
|
||||
private Unit unit;
|
||||
private int valueDecimals;
|
||||
|
||||
private Map<GroupKey, AggregatedType> results;
|
||||
|
||||
@@ -50,6 +50,11 @@ public class QueryResultImpl<AggregatedType> implements QueryResult<AggregatedTy
|
||||
this.calculationTimeInNanos = calculationTimeInNanos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return results.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResultSignifier() {
|
||||
return resultSignifier;
|
||||
|
||||
@@ -167,7 +167,7 @@ input.magnifier {
|
||||
height: 70px;
|
||||
margin: 0 auto;
|
||||
padding: 49px 0 0 80px;
|
||||
width: 300px;
|
||||
width: 400px;
|
||||
color: #7c7c7c;
|
||||
background: url(images/important-message.png) left center no-repeat;
|
||||
}
|
||||
+5
@@ -769,4 +769,9 @@ public interface StringMessages extends Messages {
|
||||
String queryResultsChartSubtitle(int retrievedDataAmount, int filteredDataAmount, double calculationTime);
|
||||
String noQuerySelected();
|
||||
String runAutomatically();
|
||||
String noStatisticSelectedError();
|
||||
String noCustomGrouperScriptTextError();
|
||||
String noDimensionToGroupBySelectedError();
|
||||
String noGrouperSelectedError();
|
||||
String queryNotValidBecause();
|
||||
}
|
||||
+6
-1
@@ -762,4 +762,9 @@ groupBy=Group by
|
||||
statisticToCalculate=Calculate statistic
|
||||
queryResultsChartSubtitle=Worked through {1}/{0} data entries in {2} seconds
|
||||
noQuerySelected=No query selected
|
||||
runAutomatically=Run automatically
|
||||
runAutomatically=Run automatically
|
||||
noStatisticSelectedError=No statistic to calculate is selected
|
||||
noCustomGrouperScriptTextError=The grouper script is empty
|
||||
noDimensionToGroupBySelectedError=No dimension to group by is selected
|
||||
noGrouperSelectedError=No grouper type is selected
|
||||
queryNotValidBecause=No query possible, because
|
||||
+6
-1
@@ -758,4 +758,9 @@ groupBy=Gruppieren nach
|
||||
statisticToCalculate=Berechne Kennzahl
|
||||
queryResultsChartSubtitle=Es wurden {1}/{0} Datensätze in {2} Sekunden verarbeitet
|
||||
noQuerySelected=Keine Abfrage ausgewählt
|
||||
runAutomatically=Automatisch ausführen
|
||||
runAutomatically=Automatisch ausführen
|
||||
noStatisticSelectedError=Keine zu berechnende Kennzahl ausgewählt ist
|
||||
noCustomGrouperScriptTextError=Das Grouper-Skript leer ist
|
||||
noDimensionToGroupBySelectedError=Keine Gruppierungs-Dimension ausgewählt ist
|
||||
noGrouperSelectedError=Kein Gruppierungs-Typ ausgewählt ist
|
||||
queryNotValidBecause=Keine Datenabfrage möglich, da
|
||||
+34
-17
@@ -1,5 +1,7 @@
|
||||
package com.sap.sailing.gwt.ui.datamining;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -25,25 +27,34 @@ public abstract class AbstractQueryComponentsProvider<DimensionType> extends Flo
|
||||
|
||||
listeners = new HashSet<QueryComponentsChangedListener<DimensionType>>();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean areComponentsValid() {
|
||||
return isGrouperValid() && isStatisticToCalculateValid() && isAggregatorValid();
|
||||
public Iterable<String> validateComponents() {
|
||||
Collection<String> errorMessages = new ArrayList<String>();
|
||||
|
||||
String grouperError = validateGrouper();
|
||||
if (grouperError != null && !grouperError.isEmpty()) {
|
||||
errorMessages.add(grouperError);
|
||||
}
|
||||
|
||||
String statisticError = validateStatisticAndAggregator();
|
||||
if (statisticError != null && !statisticError.isEmpty()) {
|
||||
errorMessages.add(statisticError);
|
||||
}
|
||||
|
||||
return errorMessages;
|
||||
}
|
||||
|
||||
private boolean isAggregatorValid() {
|
||||
return getAggregatorType() != null;
|
||||
}
|
||||
|
||||
private boolean isStatisticToCalculateValid() {
|
||||
return getStatisticToCalculate() != null;
|
||||
}
|
||||
|
||||
private boolean isGrouperValid() {
|
||||
ValidateGrouper: switch (getGrouperType()) {
|
||||
private String validateGrouper() {
|
||||
GrouperType grouper = getGrouperType();
|
||||
if (grouper == null) {
|
||||
return stringMessages.noGrouperSelectedError();
|
||||
}
|
||||
|
||||
ValidateGrouper: switch (grouper) {
|
||||
case Custom:
|
||||
if (getCustomGrouperScriptText().isEmpty()) {
|
||||
return false;
|
||||
return stringMessages.noCustomGrouperScriptTextError();
|
||||
}
|
||||
break;
|
||||
case Dimensions:
|
||||
@@ -52,14 +63,20 @@ public abstract class AbstractQueryComponentsProvider<DimensionType> extends Flo
|
||||
break ValidateGrouper;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return stringMessages.noDimensionToGroupBySelectedError();
|
||||
default:
|
||||
return false;
|
||||
return stringMessages.noGrouperSelectedError();
|
||||
}
|
||||
|
||||
return true;
|
||||
return null;
|
||||
}
|
||||
|
||||
private String validateStatisticAndAggregator() {
|
||||
return getStatisticAndAggregatorType() == null ? stringMessages.noStatisticSelectedError() : null;
|
||||
}
|
||||
|
||||
protected abstract StatisticAndAggregatorType getStatisticAndAggregatorType();
|
||||
|
||||
@Override
|
||||
public void addListener(QueryComponentsChangedListener<DimensionType> listener) {
|
||||
listeners.add(listener);
|
||||
|
||||
+25
-22
@@ -23,45 +23,48 @@ public abstract class AbstractResultsPanel<DimensionType, ResultType> extends Fl
|
||||
private QueryComponentsProvider<DimensionType> queryComponentsProvider;
|
||||
|
||||
private Label queryStatusLabel;
|
||||
private ResultsPresentator<ResultType> presentator;
|
||||
private ResultsPresenter<ResultType> presenter;
|
||||
|
||||
private Button runQueryButton;
|
||||
|
||||
public AbstractResultsPanel(StringMessages stringMessages, SailingServiceAsync sailingService,
|
||||
ErrorReporter errorReporter, QueryComponentsProvider<DimensionType> queryComponentsProvider, ResultsPresentator<ResultType> presentator) {
|
||||
ErrorReporter errorReporter, QueryComponentsProvider<DimensionType> queryComponentsProvider, ResultsPresenter<ResultType> presenter) {
|
||||
super();
|
||||
this.stringMessages = stringMessages;
|
||||
this.sailingService = sailingService;
|
||||
this.errorReporter = errorReporter;
|
||||
this.queryComponentsProvider = queryComponentsProvider;
|
||||
this.presenter = presenter;
|
||||
|
||||
add(createFunctionsPanel());
|
||||
this.presentator = presentator;
|
||||
add(this.presentator.getWidget());
|
||||
add(this.presenter.getWidget());
|
||||
runQuery();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void queryComponentsChanged(QueryComponentsProvider<DimensionType> componentsProvider) {
|
||||
if (componentsProvider.areComponentsValid()) {
|
||||
runQuery();
|
||||
} else {
|
||||
//TODO Display error message
|
||||
}
|
||||
runQuery();
|
||||
}
|
||||
|
||||
private void runQuery() {
|
||||
queryStatusLabel.setText(" | " + stringMessages.running());
|
||||
sendServerRequest(new AsyncCallback<QueryResult<ResultType>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error running the query: " + caught.getMessage());
|
||||
}
|
||||
@Override
|
||||
public void onSuccess(QueryResult<ResultType> result) {
|
||||
queryStatusLabel.setText(" | " + stringMessages.done());
|
||||
presentator.showResult(result);
|
||||
}
|
||||
});
|
||||
Iterable<String> errorMessages = queryComponentsProvider.validateComponents();
|
||||
if (errorMessages == null || !errorMessages.iterator().hasNext()) {
|
||||
queryStatusLabel.setText(" | " + stringMessages.running());
|
||||
sendServerRequest(new AsyncCallback<QueryResult<ResultType>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error running the query: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(QueryResult<ResultType> result) {
|
||||
queryStatusLabel.setText(" | " + stringMessages.done());
|
||||
presenter.showResult(result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
presenter.showError(stringMessages.queryNotValidBecause(), errorMessages);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void sendServerRequest(AsyncCallback<QueryResult<ResultType>> asyncCallback);
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ public class DataMiningPanel extends FlowPanel {
|
||||
GPSFixQueryComponentsPanel selectionPanel = new GPSFixQueryComponentsPanel(stringMessages, sailingService, errorReporter);
|
||||
this.add(selectionPanel);
|
||||
|
||||
ResultsPresentator<Number> resultsChart = new ResultsChart(stringMessages);
|
||||
ResultsPresenter<Number> resultsChart = new ResultsChart(stringMessages);
|
||||
GPSFixResultsPanel queryPanel = new GPSFixResultsPanel(stringMessages, sailingService, errorReporter, selectionPanel, resultsChart);
|
||||
this.add(queryPanel);
|
||||
|
||||
|
||||
+14
-7
@@ -112,6 +112,11 @@ public class GPSFixQueryComponentsPanel extends AbstractQueryComponentsProvider<
|
||||
return dimensionsToGroupBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StatisticAndAggregatorType getStatisticAndAggregatorType() {
|
||||
return statisticsListBox.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatisticType getStatisticToCalculate() {
|
||||
return statisticsListBox.getValue().getStatisticType();
|
||||
@@ -266,13 +271,15 @@ public class GPSFixQueryComponentsPanel extends AbstractQueryComponentsProvider<
|
||||
grouperTypeListBox.addValueChangeHandler(new ValueChangeHandler<GrouperType>() {
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<GrouperType> event) {
|
||||
switch (event.getValue()) {
|
||||
case Custom:
|
||||
groupByOptionsPanel.showWidget(1);
|
||||
break;
|
||||
case Dimensions:
|
||||
groupByOptionsPanel.showWidget(0);
|
||||
break;
|
||||
if (event.getValue() != null) {
|
||||
switch (event.getValue()) {
|
||||
case Custom:
|
||||
groupByOptionsPanel.showWidget(1);
|
||||
break;
|
||||
case Dimensions:
|
||||
groupByOptionsPanel.showWidget(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
notifyQueryComponentsChanged();
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@ import com.sap.sailing.gwt.ui.datamining.QueryComponentsProvider.GrouperType;
|
||||
public class GPSFixResultsPanel extends AbstractResultsPanel<SharedDimensions.GPSFix, Number> {
|
||||
|
||||
public GPSFixResultsPanel(StringMessages stringMessages, SailingServiceAsync sailingService,
|
||||
ErrorReporter errorReporter, QueryComponentsProvider<SharedDimensions.GPSFix> queryComponentsProvider, ResultsPresentator<Number> presentator) {
|
||||
super(stringMessages, sailingService, errorReporter, queryComponentsProvider, presentator);
|
||||
ErrorReporter errorReporter, QueryComponentsProvider<SharedDimensions.GPSFix> queryComponentsProvider, ResultsPresenter<Number> presenter) {
|
||||
super(stringMessages, sailingService, errorReporter, queryComponentsProvider, presenter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ public interface QueryComponentsProvider<DimensionType> {
|
||||
|
||||
public enum GrouperType { Dimensions, Custom }
|
||||
|
||||
public boolean areComponentsValid();
|
||||
public Iterable<String> validateComponents();
|
||||
|
||||
public Map<DimensionType, Collection<?>> getSelection();
|
||||
|
||||
|
||||
+39
-20
@@ -20,7 +20,7 @@ import org.moxieapps.gwt.highcharts.client.labels.AxisLabelsFormatter;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.XAxisLabels;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.YAxisLabels;
|
||||
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.HTML;
|
||||
import com.google.gwt.user.client.ui.RequiresResize;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
@@ -28,7 +28,7 @@ import com.sap.sailing.datamining.shared.GroupKey;
|
||||
import com.sap.sailing.datamining.shared.QueryResult;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
|
||||
public class ResultsChart implements ResultsPresentator<Number>, RequiresResize {
|
||||
public class ResultsChart implements ResultsPresenter<Number>, RequiresResize {
|
||||
|
||||
private StringMessages stringMessages;
|
||||
private SimplePanel mainPanel;
|
||||
@@ -39,37 +39,56 @@ public class ResultsChart implements ResultsPresentator<Number>, RequiresResize
|
||||
private Map<GroupKey, Integer> mainKeyToValueMap;
|
||||
private Map<Integer, GroupKey> valueToGroupKeyMap;
|
||||
|
||||
private Label noQuerySelectedLabel;
|
||||
private HTML errorLabel;
|
||||
|
||||
public ResultsChart(StringMessages stringMessages) {
|
||||
super();
|
||||
this.stringMessages = stringMessages;
|
||||
mainPanel = new SimplePanel();
|
||||
series = new HashMap<GroupKey, Series>();
|
||||
noQuerySelectedLabel = new Label(this.stringMessages.noQuerySelected() + ".");
|
||||
noQuerySelectedLabel.setStyleName("chart-importantMessage");
|
||||
errorLabel = new HTML();
|
||||
errorLabel.setStyleName("chart-importantMessage");
|
||||
|
||||
createChart();
|
||||
mainPanel.setWidget(noQuerySelectedLabel);
|
||||
mainPanel.setWidget(chart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showError(String error) {
|
||||
errorLabel.setHTML(error);
|
||||
mainPanel.setWidget(errorLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showError(String mainError, Iterable<String> detailedErrors) {
|
||||
StringBuilder errorBuilder = new StringBuilder(mainError + ":<br /><ul>");
|
||||
for (String detailedError : detailedErrors) {
|
||||
errorBuilder.append("<li>" + detailedError + "</li>");
|
||||
}
|
||||
errorBuilder.append("</ul>");
|
||||
showError(errorBuilder.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showResult(QueryResult<Number> result) {
|
||||
reset();
|
||||
|
||||
updateYAxisLabels(result);
|
||||
updateChartSubtitleAndSetChartAsWidget(result);
|
||||
|
||||
List<GroupKey> sortedKeys = getSortedKeysFrom(result);
|
||||
buildGroupKeyValueMaps(sortedKeys);
|
||||
|
||||
if (resultHasComplexKeys(result)) {
|
||||
displayComplexResult(result, sortedKeys);
|
||||
if (!result.isEmpty()) {
|
||||
resetChart();
|
||||
|
||||
updateYAxisLabels(result);
|
||||
updateChartSubtitleAndSetChartAsWidget(result);
|
||||
|
||||
List<GroupKey> sortedKeys = getSortedKeysFrom(result);
|
||||
buildGroupKeyValueMaps(sortedKeys);
|
||||
if (resultHasComplexKeys(result)) {
|
||||
displayComplexResult(result, sortedKeys);
|
||||
} else {
|
||||
displaySimpleResult(result, sortedKeys);
|
||||
}
|
||||
|
||||
chart.redraw();
|
||||
} else {
|
||||
displaySimpleResult(result, sortedKeys);
|
||||
showError(stringMessages.noDataFound() + ".");
|
||||
}
|
||||
|
||||
chart.redraw();
|
||||
}
|
||||
|
||||
private void updateYAxisLabels(QueryResult<? extends Number> result) {
|
||||
@@ -152,7 +171,7 @@ public class ResultsChart implements ResultsPresentator<Number>, RequiresResize
|
||||
return series.get(key);
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
private void resetChart() {
|
||||
chart.removeAllSeries(false);
|
||||
series = new HashMap<GroupKey, Series>();
|
||||
}
|
||||
|
||||
+5
-2
@@ -3,10 +3,13 @@ package com.sap.sailing.gwt.ui.datamining;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.datamining.shared.QueryResult;
|
||||
|
||||
public interface ResultsPresentator<ResultType> {
|
||||
public interface ResultsPresenter<ResultType> {
|
||||
|
||||
public Widget getWidget();
|
||||
|
||||
public void showResult(QueryResult<ResultType> result);
|
||||
|
||||
public Widget getWidget();
|
||||
public void showError(String error);
|
||||
public void showError(String mainError, Iterable<String> detailedErrors);
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user