mirror of
https://github.com/frosch95/SmartCSV.fx.git
synced 2026-04-11 13:38:23 +02:00
error export implemented and message on error side bar includes column name
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
group 'ninja.javafx'
|
group 'ninja.javafx'
|
||||||
version '0.6-SNAPSHOT'
|
version '0.7-SNAPSHOT'
|
||||||
|
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'groovy'
|
apply plugin: 'groovy'
|
||||||
|
|||||||
71
src/main/java/ninja/javafx/smartcsv/export/ErrorExport.java
Normal file
71
src/main/java/ninja/javafx/smartcsv/export/ErrorExport.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package ninja.javafx.smartcsv.export;
|
||||||
|
|
||||||
|
import javafx.concurrent.Service;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
|
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import static java.text.MessageFormat.format;
|
||||||
|
import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this class exports the error messages into a log file
|
||||||
|
*/
|
||||||
|
@org.springframework.stereotype.Service
|
||||||
|
public class ErrorExport extends Service {
|
||||||
|
|
||||||
|
private CSVModel model;
|
||||||
|
private File file;
|
||||||
|
private ResourceBundle resourceBundle;
|
||||||
|
private String csvFilename;
|
||||||
|
|
||||||
|
public void setCsvFilename(String csvFilename) {
|
||||||
|
this.csvFilename = csvFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceBundle(ResourceBundle resourceBundle) {
|
||||||
|
this.resourceBundle = resourceBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModel(CSVModel model) {
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFile(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Task createTask() {
|
||||||
|
return new Task() {
|
||||||
|
@Override
|
||||||
|
protected Void call() throws Exception {
|
||||||
|
try {
|
||||||
|
StringWriter log = new StringWriter();
|
||||||
|
log.append(
|
||||||
|
format(resourceBundle.getString("log.header.message"),
|
||||||
|
csvFilename,
|
||||||
|
Integer.toString(model.getValidationError().size()))).append("\n\n");
|
||||||
|
for (ValidationError error:model.getValidationError()) {
|
||||||
|
log.append(
|
||||||
|
format(resourceBundle.getString("log.message"),
|
||||||
|
error.getLineNumber().toString(),
|
||||||
|
error.getColumn(),
|
||||||
|
getI18nValidatioMessage(resourceBundle, error))).append("\n");
|
||||||
|
}
|
||||||
|
Files.write(file.toPath(), log.toString().getBytes());
|
||||||
|
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
package ninja.javafx.smartcsv.fx;
|
package ninja.javafx.smartcsv.fx;
|
||||||
|
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.WeakListChangeListener;
|
import javafx.collections.WeakListChangeListener;
|
||||||
import javafx.concurrent.WorkerStateEvent;
|
import javafx.concurrent.WorkerStateEvent;
|
||||||
@@ -39,6 +40,7 @@ import javafx.scene.layout.BorderPane;
|
|||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import ninja.javafx.smartcsv.csv.CSVFileReader;
|
import ninja.javafx.smartcsv.csv.CSVFileReader;
|
||||||
import ninja.javafx.smartcsv.csv.CSVFileWriter;
|
import ninja.javafx.smartcsv.csv.CSVFileWriter;
|
||||||
|
import ninja.javafx.smartcsv.export.ErrorExport;
|
||||||
import ninja.javafx.smartcsv.files.FileStorage;
|
import ninja.javafx.smartcsv.files.FileStorage;
|
||||||
import ninja.javafx.smartcsv.fx.about.AboutController;
|
import ninja.javafx.smartcsv.fx.about.AboutController;
|
||||||
import ninja.javafx.smartcsv.fx.list.ErrorSideBar;
|
import ninja.javafx.smartcsv.fx.list.ErrorSideBar;
|
||||||
@@ -95,6 +97,9 @@ public class SmartCSVController extends FXMLController {
|
|||||||
public static final String CSV_FILTER_EXTENSION = "*.csv";
|
public static final String CSV_FILTER_EXTENSION = "*.csv";
|
||||||
public static final String JSON_FILTER_TEXT = "JSON files (*.json)";
|
public static final String JSON_FILTER_TEXT = "JSON files (*.json)";
|
||||||
public static final String JSON_FILTER_EXTENSION = "*.json";
|
public static final String JSON_FILTER_EXTENSION = "*.json";
|
||||||
|
public static final String EXPORT_LOG_FILTER_TEXT = "Error log files (*.log)";
|
||||||
|
public static final String EXPORT_LOG_FILTER_EXTENSION = "*.log";
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// injections
|
// injections
|
||||||
@@ -115,6 +120,9 @@ public class SmartCSVController extends FXMLController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SaveFileService saveFileService;
|
private SaveFileService saveFileService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ErrorExport errorExport;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private BorderPane applicationPane;
|
private BorderPane applicationPane;
|
||||||
|
|
||||||
@@ -157,6 +165,9 @@ public class SmartCSVController extends FXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
private MenuItem gotoLineMenuItem;
|
private MenuItem gotoLineMenuItem;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private MenuItem exportMenuItem;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Button saveButton;
|
private Button saveButton;
|
||||||
|
|
||||||
@@ -181,6 +192,9 @@ public class SmartCSVController extends FXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
private Button addRowButton;
|
private Button addRowButton;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Button exportButton;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label currentLineNumber;
|
private Label currentLineNumber;
|
||||||
|
|
||||||
@@ -370,6 +384,26 @@ public class SmartCSVController extends FXMLController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void export(ActionEvent actionEvent) {
|
||||||
|
final FileChooser fileChooser = new FileChooser();
|
||||||
|
|
||||||
|
//Set extension filter
|
||||||
|
final FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(EXPORT_LOG_FILTER_TEXT, EXPORT_LOG_FILTER_EXTENSION);
|
||||||
|
fileChooser.getExtensionFilters().add(extFilter);
|
||||||
|
fileChooser.setTitle("Save");
|
||||||
|
|
||||||
|
//Show open file dialog
|
||||||
|
File file = fileChooser.showSaveDialog(applicationPane.getScene().getWindow());
|
||||||
|
if (file != null) {
|
||||||
|
errorExport.setCsvFilename(currentCsvFile.getFile().getName());
|
||||||
|
errorExport.setModel(currentCsvFile.getContent());
|
||||||
|
errorExport.setFile(file);
|
||||||
|
errorExport.setResourceBundle(resourceBundle);
|
||||||
|
errorExport.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canExit() {
|
public boolean canExit() {
|
||||||
boolean canExit = true;
|
boolean canExit = true;
|
||||||
if (currentCsvFile.getContent() != null && currentCsvFile.isFileChanged()) {
|
if (currentCsvFile.getContent() != null && currentCsvFile.isFileChanged()) {
|
||||||
@@ -552,6 +586,8 @@ public class SmartCSVController extends FXMLController {
|
|||||||
* Creates new table view and add the new content
|
* Creates new table view and add the new content
|
||||||
*/
|
*/
|
||||||
private void resetContent() {
|
private void resetContent() {
|
||||||
|
resetExportButtons();
|
||||||
|
|
||||||
if (currentCsvFile.getContent() != null) {
|
if (currentCsvFile.getContent() != null) {
|
||||||
currentCsvFile.getContent().getValidationError().addListener(weakErrorListListener);
|
currentCsvFile.getContent().getValidationError().addListener(weakErrorListListener);
|
||||||
currentCsvFile.getContent().setValidationConfiguration(currentConfigFile.getContent());
|
currentCsvFile.getContent().setValidationConfiguration(currentConfigFile.getContent());
|
||||||
@@ -575,9 +611,22 @@ public class SmartCSVController extends FXMLController {
|
|||||||
setRightAnchor(tableView, 0.0);
|
setRightAnchor(tableView, 0.0);
|
||||||
tableWrapper.getChildren().setAll(tableView);
|
tableWrapper.getChildren().setAll(tableView);
|
||||||
errorSideBar.setModel(currentCsvFile.getContent());
|
errorSideBar.setModel(currentCsvFile.getContent());
|
||||||
|
binExportButtons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void binExportButtons() {
|
||||||
|
exportButton.disableProperty().bind(Bindings.isEmpty(currentCsvFile.getContent().getValidationError()));
|
||||||
|
exportMenuItem.disableProperty().bind(Bindings.isEmpty(currentCsvFile.getContent().getValidationError()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetExportButtons() {
|
||||||
|
exportButton.disableProperty().unbind();
|
||||||
|
exportMenuItem.disableProperty().unbind();
|
||||||
|
exportButton.disableProperty().setValue(true);
|
||||||
|
exportMenuItem.disableProperty().setValue(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a column with the given name to the tableview
|
* Adds a column with the given name to the tableview
|
||||||
* @param header name of the column header
|
* @param header name of the column header
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ import java.util.ResourceBundle;
|
|||||||
import static javafx.geometry.Pos.CENTER;
|
import static javafx.geometry.Pos.CENTER;
|
||||||
import static ninja.javafx.smartcsv.fx.util.ColorConstants.ERROR_COLOR;
|
import static ninja.javafx.smartcsv.fx.util.ColorConstants.ERROR_COLOR;
|
||||||
import static ninja.javafx.smartcsv.fx.util.ColorConstants.OK_COLOR;
|
import static ninja.javafx.smartcsv.fx.util.ColorConstants.OK_COLOR;
|
||||||
import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessage;
|
import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessageWithColumn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clickable side bar with error markers
|
* clickable side bar with error markers
|
||||||
@@ -158,7 +158,7 @@ public class ErrorSideBar extends Region {
|
|||||||
errorMarker.setStyle("-fx-background-color: " + ERROR_COLOR);
|
errorMarker.setStyle("-fx-background-color: " + ERROR_COLOR);
|
||||||
errorMarker.setOnMouseClicked(event -> selectedValidationError.setValue(error));
|
errorMarker.setOnMouseClicked(event -> selectedValidationError.setValue(error));
|
||||||
errorMarker.setOnMouseEntered(event -> {
|
errorMarker.setOnMouseEntered(event -> {
|
||||||
popOver.setContentNode(popupContent(getI18nValidatioMessage(resourceBundle, error)));
|
popOver.setContentNode(popupContent(getI18nValidatioMessageWithColumn(resourceBundle, error)));
|
||||||
popOver.show(errorMarker, -16);
|
popOver.show(errorMarker, -16);
|
||||||
});
|
});
|
||||||
return errorMarker;
|
return errorMarker;
|
||||||
|
|||||||
@@ -54,11 +54,20 @@ public class I18nValidationUtil {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getI18nValidatioMessageWithColumn(ResourceBundle resourceBundle, ValidationError error) {
|
||||||
|
return getI18nValidatioMessage(resourceBundle, error, resourceBundle.getString("column") + " " + error.getColumn() + " : ");
|
||||||
|
}
|
||||||
|
|
||||||
public static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error) {
|
public static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error) {
|
||||||
|
return getI18nValidatioMessage(resourceBundle, error, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error, String prefix) {
|
||||||
|
|
||||||
List<ValidationMessage> validationMessages = error.getMessages();
|
List<ValidationMessage> validationMessages = error.getMessages();
|
||||||
StringWriter message = new StringWriter();
|
StringWriter message = new StringWriter();
|
||||||
for (ValidationMessage validationMessage: validationMessages) {
|
for (ValidationMessage validationMessage: validationMessages) {
|
||||||
|
message.append(prefix);
|
||||||
if (resourceBundle.containsKey(validationMessage.getKey())) {
|
if (resourceBundle.containsKey(validationMessage.getKey())) {
|
||||||
String resourceText = resourceBundle.getString(validationMessage.getKey());
|
String resourceText = resourceBundle.getString(validationMessage.getKey());
|
||||||
if (validationMessage.getParameters().length > 0) {
|
if (validationMessage.getParameters().length > 0) {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public class ValidationError {
|
|||||||
|
|
||||||
private List<ValidationMessage> messages = new ArrayList<>();
|
private List<ValidationMessage> messages = new ArrayList<>();
|
||||||
private Integer lineNumber;
|
private Integer lineNumber;
|
||||||
|
private String column = "";
|
||||||
|
|
||||||
private ValidationError(Integer lineNumber) {
|
private ValidationError(Integer lineNumber) {
|
||||||
this.lineNumber = lineNumber;
|
this.lineNumber = lineNumber;
|
||||||
@@ -51,10 +52,19 @@ public class ValidationError {
|
|||||||
return new ValidationError(-1);
|
return new ValidationError(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ValidationError column(String column) {
|
||||||
|
this.column = column;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getLineNumber() {
|
public Integer getLineNumber() {
|
||||||
return lineNumber;
|
return lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getColumn() {
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
public List<ValidationMessage> getMessages() {
|
public List<ValidationMessage> getMessages() {
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public class Validator {
|
|||||||
public ValidationError isValid(Integer row, String column, String value) {
|
public ValidationError isValid(Integer row, String column, String value) {
|
||||||
ValidationError result = null;
|
ValidationError result = null;
|
||||||
if (hasConfig()) {
|
if (hasConfig()) {
|
||||||
ValidationError error = ValidationError.withLineNumber(row);
|
ValidationError error = ValidationError.withLineNumber(row).column(column);
|
||||||
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
||||||
if (validationMap != null) {
|
if (validationMap != null) {
|
||||||
for (Validation validation: validationMap.values()) {
|
for (Validation validation: validationMap.values()) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
application.name = SmartCSV.fx
|
application.name = SmartCSV.fx
|
||||||
application.version = 0.6
|
application.version = 0.7
|
||||||
|
|
||||||
# fxml views
|
# fxml views
|
||||||
fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml
|
fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml
|
||||||
|
|||||||
@@ -82,9 +82,14 @@
|
|||||||
.goto-icon {
|
.goto-icon {
|
||||||
-glyph-name: "SUBDIRECTORY_ARROW_RIGHT";
|
-glyph-name: "SUBDIRECTORY_ARROW_RIGHT";
|
||||||
-glyph-size: 16px;
|
-glyph-size: 16px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.export-icon {
|
||||||
|
-glyph-name: "BUG";
|
||||||
|
-glyph-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* toolbar customization based on http://fxexperience.com/2012/02/customized-segmented-toolbar-buttons/ */
|
/* toolbar customization based on http://fxexperience.com/2012/02/customized-segmented-toolbar-buttons/ */
|
||||||
|
|
||||||
#background {
|
#background {
|
||||||
@@ -149,6 +154,11 @@
|
|||||||
-fx-fill: white;
|
-fx-fill: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tool-bar .export-icon {
|
||||||
|
-glyph-size: 16px;
|
||||||
|
-fx-fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
.segmented-button-bar .button {
|
.segmented-button-bar .button {
|
||||||
-fx-background-color:
|
-fx-background-color:
|
||||||
-darkest-black,
|
-darkest-black,
|
||||||
|
|||||||
@@ -78,6 +78,11 @@
|
|||||||
<MaterialDesignIconView styleClass="preferences-icon" />
|
<MaterialDesignIconView styleClass="preferences-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem fx:id="exportMenuItem" disable="true" mnemonicParsing="false" onAction="#export" text="%menu.export">
|
||||||
|
<graphic>
|
||||||
|
<MaterialDesignIconView styleClass="export-icon" />
|
||||||
|
</graphic>
|
||||||
|
</MenuItem>
|
||||||
<SeparatorMenuItem mnemonicParsing="false" />
|
<SeparatorMenuItem mnemonicParsing="false" />
|
||||||
<MenuItem mnemonicParsing="false" onAction="#close" text="%menu.close">
|
<MenuItem mnemonicParsing="false" onAction="#close" text="%menu.close">
|
||||||
<graphic>
|
<graphic>
|
||||||
@@ -229,6 +234,14 @@
|
|||||||
<MaterialDesignIconView styleClass="preferences-icon" />
|
<MaterialDesignIconView styleClass="preferences-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button fx:id="exportButton" disable="true" mnemonicParsing="false" onAction="#export">
|
||||||
|
<tooltip>
|
||||||
|
<Tooltip text="%menu.export" />
|
||||||
|
</tooltip>
|
||||||
|
<graphic>
|
||||||
|
<MaterialDesignIconView styleClass="export-icon" />
|
||||||
|
</graphic>
|
||||||
|
</Button>
|
||||||
<Button mnemonicParsing="false" onAction="#close" styleClass="last">
|
<Button mnemonicParsing="false" onAction="#close" styleClass="last">
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip text="%menu.close" />
|
<Tooltip text="%menu.close" />
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ menu.preferences = Preferences
|
|||||||
menu.delete.row = Delete row
|
menu.delete.row = Delete row
|
||||||
menu.add.row = Add row
|
menu.add.row = Add row
|
||||||
menu.goto.line = Goto line
|
menu.goto.line = Goto line
|
||||||
|
menu.export = Export error log
|
||||||
|
|
||||||
title.validation.errors = Validation Errors:
|
title.validation.errors = Validation Errors:
|
||||||
|
|
||||||
@@ -78,4 +79,9 @@ dialog.validation.rules.title = Validation rules
|
|||||||
dialog.validation.rules.header = Validation rules of column "{0}"
|
dialog.validation.rules.header = Validation rules of column "{0}"
|
||||||
context.menu.edit.column.rules = Edit rules
|
context.menu.edit.column.rules = Edit rules
|
||||||
|
|
||||||
lineNumber = Selected line:
|
lineNumber = Selected line:
|
||||||
|
|
||||||
|
log.header.message = {0} has {1} errors
|
||||||
|
log.message = row {0} column {1} : {2}
|
||||||
|
|
||||||
|
column = column
|
||||||
@@ -23,6 +23,7 @@ menu.preferences = Einstellungen
|
|||||||
menu.delete.row = Zeile l\u00f6schen
|
menu.delete.row = Zeile l\u00f6schen
|
||||||
menu.add.row = Zeile hinzuf\u00fcgen
|
menu.add.row = Zeile hinzuf\u00fcgen
|
||||||
menu.goto.line = Springe zur Zeile
|
menu.goto.line = Springe zur Zeile
|
||||||
|
menu.export = Export Fehlerdatei
|
||||||
|
|
||||||
title.validation.errors = Fehler in der Datei:
|
title.validation.errors = Fehler in der Datei:
|
||||||
|
|
||||||
@@ -88,4 +89,9 @@ dialog.validation.rules.header = Pr\u00fcfregeln f\u00fcr die Spalte "{0}"
|
|||||||
|
|
||||||
context.menu.edit.column.rules = Pr\u00fcfregeln bearbeiten
|
context.menu.edit.column.rules = Pr\u00fcfregeln bearbeiten
|
||||||
|
|
||||||
lineNumber = Ausgew\u00e4hlte Zeile:
|
lineNumber = Ausgew\u00e4hlte Zeile:
|
||||||
|
|
||||||
|
log.header.message = {0} hat {1} Fehler
|
||||||
|
log.message = Zeile {0} Spalte {1} : {2}
|
||||||
|
|
||||||
|
column = Spalte
|
||||||
Reference in New Issue
Block a user