Compare commits

...

4 Commits

Author SHA1 Message Date
giavaphi 2312149256 Merge pull request #64 from schrom01/fix_tasklist-not-updated_M3
fix: Properly saving tasks
2022-11-21 09:21:26 +01:00
David Guler ffc7f5174e fix: Properly saving tasks
Tasks were not properly saved by the JsonTaskList, resulting in the newly created tasks being discarded immediately. Fixed by putting them into the taskMap in saveTask()
2022-11-21 09:15:29 +01:00
giavaphi 8d3fbc06ad added task list editor date cell factory 2022-11-21 07:03:45 +01:00
giavaphi dcb97f1c55 add and edit task list 2022-11-21 06:47:27 +01:00
7 changed files with 336 additions and 85 deletions

View File

@ -1,5 +1,6 @@
package ch.zhaw.gartenverwaltung; package ch.zhaw.gartenverwaltung;
import ch.zhaw.gartenverwaltung.bootstrap.AppLoader;
import ch.zhaw.gartenverwaltung.bootstrap.Inject; import ch.zhaw.gartenverwaltung.bootstrap.Inject;
import ch.zhaw.gartenverwaltung.io.PlantList; import ch.zhaw.gartenverwaltung.io.PlantList;
import ch.zhaw.gartenverwaltung.models.Garden; import ch.zhaw.gartenverwaltung.models.Garden;
@ -10,14 +11,18 @@ import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.Pest; import ch.zhaw.gartenverwaltung.types.Pest;
import ch.zhaw.gartenverwaltung.types.Plant; import ch.zhaw.gartenverwaltung.types.Plant;
import ch.zhaw.gartenverwaltung.types.Task; import ch.zhaw.gartenverwaltung.types.Task;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.Button; import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox; import javafx.scene.layout.Priority;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.IOException; import java.io.IOException;
@ -35,7 +40,12 @@ public class CropDetailController {
@Inject @Inject
private Garden garden; private Garden garden;
@Inject
AppLoader appLoader;
private static final Logger LOG = Logger.getLogger(CropDetailController.class.getName()); private static final Logger LOG = Logger.getLogger(CropDetailController.class.getName());
private final ListProperty<Task> taskListProperty = new SimpleListProperty<>(FXCollections.observableArrayList());
private final ListProperty<Pest> pestListProperty = new SimpleListProperty<>(FXCollections.observableArrayList());
@FXML @FXML
private ImageView imageView; private ImageView imageView;
@ -52,9 +62,6 @@ public class CropDetailController {
@FXML @FXML
private Label description_label; private Label description_label;
@FXML
private VBox growthPhases_vbox;
@FXML @FXML
private Label location_label; private Label location_label;
@ -64,9 +71,6 @@ public class CropDetailController {
@FXML @FXML
private Button location_button; private Button location_button;
@FXML
private VBox pests_vbox;
@FXML @FXML
private Label soil_label; private Label soil_label;
@ -74,11 +78,17 @@ public class CropDetailController {
private Label spacing_label; private Label spacing_label;
@FXML @FXML
private Button editTaskList_button; private Button addTask_button;
@FXML @FXML
void editTaskList() { private ListView<Task> taskList_listView;
@FXML
private ListView<Pest> pests_listView;
@FXML
void addTask() throws IOException {
createTaskDialog(true, null);
} }
/** /**
@ -128,25 +138,65 @@ public class CropDetailController {
} }
area_label.setText(""); area_label.setText("");
location_label.setText(""); location_label.setText("");
createTaskLists(crop);
createPestList(plant); setTaskListProperty(crop);
taskList_listView.itemsProperty().bind(taskListProperty);
pestListProperty.addAll(plant.pests());
pests_listView.itemsProperty().bind(pestListProperty);
} catch (HardinessZoneNotSetException | IOException e) { } catch (HardinessZoneNotSetException | IOException e) {
throw new PlantNotFoundException(); throw new PlantNotFoundException();
} }
setIconToButton(editTaskList_button, "editIcon.png"); setIconToButton(addTask_button, "addIcon.png");
setIconToButton(area_button, "areaIcon.png"); setIconToButton(area_button, "areaIcon.png");
setIconToButton(location_button, "locationIcon.png"); setIconToButton(location_button, "locationIcon.png");
setCellFactoryPests();
setCellFactoryTasks();
} }
private void createTaskLists(Crop crop) { private void setCellFactoryTasks() {
taskList_listView.setCellFactory(param -> new ListCell<>() {
@Override
protected void updateItem(Task task, boolean empty) {
super.updateItem(task, empty);
if (empty || task == null) {
setText(null);
setGraphic(null);
} else {
setText("");
setGraphic(createTaskHBox(task));
}
}
});
}
private void setCellFactoryPests() {
pests_listView.setCellFactory(param -> new ListCell<>() {
@Override
protected void updateItem(Pest pest, boolean empty) {
super.updateItem(pest, empty);
if (empty || pest == null) {
setText(null);
setGraphic(null);
} else {
setText("");
setGraphic(createPestHBox(pest));
}
}
});
}
private void setTaskListProperty(Crop crop) {
crop.getCropId().ifPresent(id -> { crop.getCropId().ifPresent(id -> {
List<Task> taskList; List<Task> taskList;
try { try {
taskList = gardenSchedule.getTaskListForCrop(id); taskList = gardenSchedule.getTaskListForCrop(id);
for (Task task : taskList) { taskListProperty.clear();
Label label = new Label(task.getDescription()); taskListProperty.addAll(taskList);
growthPhases_vbox.getChildren().add(label);
}
} catch (IOException e) { } catch (IOException e) {
// TODO: Alert // TODO: Alert
LOG.log(Level.SEVERE, "Could not get task list for crop", e.getCause()); LOG.log(Level.SEVERE, "Could not get task list for crop", e.getCause());
@ -154,22 +204,37 @@ public class CropDetailController {
}); });
} }
private void createPestList(Plant plant) { private HBox createTaskHBox(Task task) {
List<Pest> pests = plant.pests(); HBox hBox = new HBox();
for (Pest pest : pests) { Label taskName = new Label(task.getName()+": ");
Label label = new Label(pest.name() + ":"); taskName.setStyle("-fx-font-weight: bold");
label.setStyle("-fx-font-weight: bold"); Label taskDescription = new Label(task.getDescription());
HBox hBox = new HBox(); taskDescription.setWrapText(true);
hBox.fillHeightProperty(); taskDescription.setMaxWidth(2000);
Label label1 = new Label(pest.description()); HBox.setHgrow(taskDescription, Priority.ALWAYS);
label1.setAlignment(Pos.TOP_LEFT);
label1.setWrapText(true); Button edit = new Button();
label1.setMaxWidth(600); Button delete = new Button();
label1.setMaxHeight(100); setIconToButton(edit, "editIcon.png");
Button button = new Button("Get Counter Measures"); setIconToButton(delete, "deleteIcon.png");
hBox.getChildren().addAll(label1, button); edit.setOnAction(getEditTaskEvent(task));
pests_vbox.getChildren().addAll(label, hBox);
} hBox.getChildren().addAll(taskName, taskDescription, edit, delete);
return hBox;
}
private HBox createPestHBox(Pest pest) {
Label label = new Label(pest.name() + ": ");
label.setStyle("-fx-font-weight: bold");
HBox hBox = new HBox();
hBox.fillHeightProperty();
Label label1 = new Label(pest.description());
label1.setAlignment(Pos.TOP_LEFT);
label1.setWrapText(true);
label1.setMaxWidth(600);
Button button = new Button("Get Counter Measures");
hBox.getChildren().addAll(label, label1, button);
return hBox;
} }
/** /**
@ -184,4 +249,55 @@ public class CropDetailController {
imageView.setPreserveRatio(true); imageView.setPreserveRatio(true);
button.setGraphic(imageView); button.setGraphic(imageView);
} }
private EventHandler<ActionEvent> getEditTaskEvent(Task task) {
return (event) -> {
try {
createTaskDialog(false, task);
} catch (IOException e) {
e.printStackTrace();
}
};
}
private void createTaskDialog(boolean newTask, Task givenTask) throws IOException {
Dialog<Task> dialog = new Dialog<>();
dialog.setTitle("Set Task");
dialog.setHeaderText("Add/Edit Task:");
dialog.setResizable(false);
DialogPane dialogPane = dialog.getDialogPane();
ButtonType saveTask;
if(newTask) {
saveTask = new ButtonType("Add", ButtonBar.ButtonData.OK_DONE);
} else {
saveTask = new ButtonType("Save", ButtonBar.ButtonData.OK_DONE);
}
dialogPane.getButtonTypes().addAll(saveTask, ButtonType.CANCEL);
if (appLoader.loadPaneToDialog("TaskFormular.fxml", dialogPane) instanceof TaskFormularController controller) {
controller.setCorp(this.crop);
if (!newTask) {
controller.setTaskValue(givenTask);
}
dialog.setResultConverter(button -> button.equals(saveTask) ? controller.returnResult() : null);
dialog.showAndWait()
.ifPresent(task -> {
if (newTask) {
try {
gardenSchedule.addTask(task);
setTaskListProperty(this.crop);
} catch (IOException e) {
e.printStackTrace();
}
} else {
//ToDo method to edit task
setTaskListProperty(this.crop);
}
});
}
}
} }

View File

@ -0,0 +1,83 @@
package ch.zhaw.gartenverwaltung;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.GrowthPhaseType;
import ch.zhaw.gartenverwaltung.types.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.util.Callback;
import java.net.URL;
import java.time.LocalDate;
import java.util.ResourceBundle;
public class TaskFormularController implements Initializable {
private Crop crop;
@FXML
private TextArea description_area;
@FXML
private DatePicker end_datePicker;
@FXML
private TextField interval_field;
@FXML
private DatePicker start_datePicker;
@FXML
private TextField taskName_field;
public Task returnResult() {
Task task = new Task(taskName_field.getText(), description_area.getText(),
start_datePicker.getValue(), end_datePicker.getValue(),
Integer.parseInt(interval_field.getText()), crop.getCropId().get());
return task;
}
public void setCorp(Crop crop) {
this.crop = crop;
}
public void setTaskValue(Task task) {
taskName_field.setText(task.getName());
description_area.setText(task.getDescription());
start_datePicker.setValue(task.getStartDate());
end_datePicker.setValue(task.getEndDate().get());
interval_field.setText(task.getInterval().get().toString());
}
private Callback<DatePicker, DateCell> getDayCellFactory() {
return (datePicker) -> new DateCell() {
private final LocalDate today = LocalDate.now();
@Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
setDisable(true);
setStyle("-fx-background-color: #ffc0cb;");
if (item.compareTo(today) > 0 && item.compareTo(crop.getStartDate()) > 0) {
setDisable(false);
setStyle("-fx-background-color: #32CD32;");
}
}
};
}
@Override
public void initialize(URL location, ResourceBundle resources) {
start_datePicker.setDayCellFactory(getDayCellFactory());
start_datePicker.setEditable(false);
end_datePicker.setDayCellFactory(getDayCellFactory());
end_datePicker.setEditable(false);
}
}

View File

@ -106,6 +106,7 @@ public class JsonTaskList implements TaskList {
if(task.getId() == 0) { if(task.getId() == 0) {
task.withId(idProvider.incrementAndGet()); task.withId(idProvider.incrementAndGet());
} }
taskMap.put(task.getId(), task);
writeTaskListToFile(); writeTaskListToFile();
} }

View File

@ -3,6 +3,7 @@
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.ScrollPane?> <?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.ImageView?> <?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.AnchorPane?>
@ -12,13 +13,11 @@
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="785.0" prefWidth="899.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.CropDetailController">
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="785.0" prefWidth="899.0"
xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.CropDetailController">
<children> <children>
<ScrollPane fitToWidth="true" prefHeight="759.0" prefWidth="664.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <ScrollPane fitToWidth="true" prefHeight="759.0" prefWidth="664.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content> <content>
<VBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="503.0" prefWidth="897.0"> <VBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="781.0" prefWidth="897.0">
<padding> <padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding> </padding>
@ -85,22 +84,22 @@
<Insets bottom="10.0" /> <Insets bottom="10.0" />
</VBox.margin> </VBox.margin>
</Label> </Label>
<VBox fx:id="growthPhases_vbox" prefHeight="135.0" prefWidth="879.0"> <ListView fx:id="taskList_listView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="877.0" VBox.vgrow="ALWAYS">
<VBox.margin> <VBox.margin>
<Insets bottom="10.0" /> <Insets bottom="10.0" />
</VBox.margin> </VBox.margin>
</VBox> </ListView>
<Button fx:id="editTaskList_button" mnemonicParsing="false" onAction="#editTaskList" prefHeight="25.0" prefWidth="45.0"> <Button fx:id="addTask_button" mnemonicParsing="false" onAction="#addTask" prefHeight="25.0" prefWidth="45.0">
<VBox.margin> <VBox.margin>
<Insets bottom="10.0" /> <Insets bottom="10.0" />
</VBox.margin> </VBox.margin>
</Button> </Button>
<Label text="Pests:" /> <Label text="Pests:" />
<VBox fx:id="pests_vbox" prefHeight="200.0" prefWidth="100.0"> <ListView fx:id="pests_listView" maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<VBox.margin> <VBox.margin>
<Insets bottom="10.0" /> <Insets bottom="10.0" />
</VBox.margin> </VBox.margin>
</VBox> </ListView>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" VBox.vgrow="NEVER"> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" VBox.vgrow="NEVER">
<children> <children>
<Label text="Area:"> <Label text="Area:">

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="259.0" prefWidth="390.0" xmlns="http://javafx.com/javafx/17"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.TaskFormularController">
<children>
<VBox layoutX="14.0" layoutY="14.0" prefHeight="272.0" prefWidth="390.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
<children>
<HBox alignment="CENTER_LEFT" prefHeight="35.0" prefWidth="560.0">
<children>
<Label maxWidth="1.7976931348623157E308" text="Task name:" HBox.hgrow="ALWAYS" />
<TextField fx:id="taskName_field" promptText="Task Name" />
</children>
</HBox>
<HBox prefHeight="77.0" prefWidth="350.0">
<children>
<Label maxWidth="1.7976931348623157E308" text="Description:" HBox.hgrow="ALWAYS" />
<TextArea fx:id="description_area" prefHeight="73.0" prefWidth="206.0" promptText="Description" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" layoutX="30.0" layoutY="30.0" prefHeight="35.0" prefWidth="560.0">
<children>
<Label maxWidth="1.7976931348623157E308" text="Start Date:" HBox.hgrow="ALWAYS" />
<DatePicker fx:id="start_datePicker" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" layoutX="30.0" layoutY="143.0" prefHeight="35.0" prefWidth="560.0">
<children>
<Label maxWidth="1.7976931348623157E308" text="End Date:" HBox.hgrow="ALWAYS" />
<DatePicker fx:id="end_datePicker" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" layoutX="30.0" layoutY="30.0" prefHeight="35.0" prefWidth="560.0">
<children>
<Label maxWidth="1.7976931348623157E308" text="Interval:" HBox.hgrow="ALWAYS" />
<TextField fx:id="interval_field" promptText="Interval (e.g. 0, 1, 3 ...)" />
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>

View File

@ -184,15 +184,14 @@
"litersPerSqM": 15, "litersPerSqM": 15,
"interval": 4, "interval": 4,
"notes": [ "notes": [
] ]
}, },
"taskTemplates": [ "taskTemplates": [
{ {
"name": "hilling", "name": "Plant Sets",
"relativeStartDate": 0, "relativeStartDate": 0,
"relativeEndDate": 0, "relativeEndDate": 0,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ", "description": "Plant the sets about 5cm deep into the soil.",
"interval": null, "interval": null,
"isOptional": false "isOptional": false
} }
@ -232,7 +231,6 @@
"litersPerSqM": 0, "litersPerSqM": 0,
"interval": null, "interval": null,
"notes": [ "notes": [
] ]
}, },
"taskTemplates": [ "taskTemplates": [

View File

@ -1,56 +1,56 @@
[ [
{ {
"id" : 1, "id": 1,
"name" : "sow plant", "name": "sow plant",
"description": "Plant the seeds, crops in de bed.", "description": "Plant the seeds, crops in de bed.",
"startDate" : "2022-05-01", "startDate": "2022-05-01",
"endDate" : "2022-05-01", "endDate": "2022-05-01",
"interval" : 0, "interval": 0,
"cropId" : 0 "cropId": 0
}, },
{ {
"id" : 2, "id": 2,
"name" : "water plant", "name": "water plant",
"description": "water the plant, so that the soil is wet around the plant.", "description": "water the plant, so that the soil is wet around the plant.",
"startDate" : "2022-05-01", "startDate": "2022-05-01",
"endDate" : "2022-09-01", "endDate": "2022-09-01",
"interval" : 2, "interval": 2,
"cropId" : 0 "cropId": 0
}, },
{ {
"id" : 3, "id": 3,
"name" : "fertilize plant", "name": "fertilize plant",
"description": "The fertilizer has to be mixed with water. Then fertilize the plants soil with the mixture", "description": "The fertilizer has to be mixed with water. Then fertilize the plants soil with the mixture",
"startDate" : "2022-06-01", "startDate": "2022-06-01",
"endDate" : "2022-08-01", "endDate": "2022-08-01",
"interval" : 28, "interval": 28,
"cropId" : 0 "cropId": 0
}, },
{ {
"id" : 4, "id": 4,
"name" : "covering plant", "name": "covering plant",
"description": "Take a big enough coverage for the plants. Cover the whole plant with a bit space between the plant and the coverage", "description": "Take a big enough coverage for the plants. Cover the whole plant with a bit space between the plant and the coverage",
"startDate" : "2022-07-01", "startDate": "2022-07-01",
"endDate" : "2022-07-01", "endDate": "2022-07-01",
"interval" : 0, "interval": 0,
"cropId" : 0 "cropId": 0
}, },
{ {
"id" : 5, "id": 5,
"name" : "look after plant", "name": "look after plant",
"description": "Look for pest or illness at the leaves of the plant. Check the soil around the plant, if the roots are enough covered with soil", "description": "Look for pest or illness at the leaves of the plant. Check the soil around the plant, if the roots are enough covered with soil",
"startDate" : "2022-05-01", "startDate": "2022-05-01",
"endDate" : "2022-09-01", "endDate": "2022-09-01",
"interval" : 5, "interval": 5,
"cropId" : 0 "cropId": 0
}, },
{ {
"id" : 6, "id": 6,
"name" : "harvest plant", "name": "harvest plant",
"description": "Pull the ripe vegetables out from the soil. Clean them with clear, fresh water. ", "description": "Pull the ripe vegetables out from the soil. Clean them with clear, fresh water. ",
"startDate" : "2022-09-01", "startDate": "2022-09-01",
"endDate" : "2022-09-01", "endDate": "2022-09-01",
"interval" : 0, "interval": 0,
"cropId" : 0 "cropId": 0
} }
] ]